Compare commits
9 Commits
pipeline
...
98ef35b532
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98ef35b532 | ||
|
|
f4757979cc | ||
|
|
a580fc6cbd | ||
|
|
00b696b3f0 | ||
|
|
cbaa5bfbca | ||
|
|
9a0eadc514 | ||
|
|
60b784e365 | ||
|
|
95b9d7d52a | ||
|
|
093062f7b2 |
14
.gitignore
vendored
@@ -15,6 +15,14 @@
|
|||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
|
||||||
|
# project-specific build artifacts
|
||||||
|
/src/Website/build/
|
||||||
|
/src/Website/storybook-static/
|
||||||
|
/src/Website/.react-router/
|
||||||
|
/src/Website/playwright-report/
|
||||||
|
/src/Website/test-results/
|
||||||
|
/test-results/
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.pem
|
*.pem
|
||||||
@@ -42,6 +50,9 @@ next-env.d.ts
|
|||||||
|
|
||||||
# vscode
|
# vscode
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
/cloudinary-images
|
/cloudinary-images
|
||||||
|
|
||||||
@@ -487,3 +498,6 @@ FodyWeavers.xsd
|
|||||||
.env.dev
|
.env.dev
|
||||||
.env.test
|
.env.test
|
||||||
.env.prod
|
.env.prod
|
||||||
|
|
||||||
|
*storybook.log
|
||||||
|
storybook-static
|
||||||
|
|||||||
957
LICENSE.md
285
README.md
@@ -1,261 +1,142 @@
|
|||||||
# The Biergarten App
|
# The Biergarten App
|
||||||
|
|
||||||
A social platform for craft beer enthusiasts to discover breweries, share reviews, and
|
The Biergarten App is a multi-project monorepo with a .NET backend and an active React
|
||||||
connect with fellow beer lovers.
|
Router frontend in `src/Website`. The current website focuses on account flows, theme
|
||||||
|
switching, shared UI components, Storybook coverage, and integration with the API.
|
||||||
|
|
||||||
**Documentation**
|
## Documentation
|
||||||
|
|
||||||
- [Getting Started](docs/getting-started.md) - Setup and installation
|
- [Getting Started](docs/getting-started.md) - Local setup for backend and active website
|
||||||
- [Architecture](docs/architecture.md) - System design and patterns
|
- [Architecture](docs/architecture.md) - Current backend and frontend architecture
|
||||||
- [Database](docs/database.md) - Schema and stored procedures
|
- [Docker Guide](docs/docker.md) - Container-based backend development and testing
|
||||||
- [Docker Guide](docs/docker.md) - Container deployment
|
- [Testing](docs/testing.md) - Backend and frontend test commands
|
||||||
- [Testing](docs/testing.md) - Test strategy and commands
|
- [Environment Variables](docs/environment-variables.md) - Active configuration reference
|
||||||
- [Environment Variables](docs/environment-variables.md) - Configuration reference
|
- [Token Validation](docs/token-validation.md) - JWT validation architecture
|
||||||
|
- [Legacy Website Archive](docs/archive/legacy-website-v1.md) - Archived notes for the old Next.js frontend
|
||||||
|
|
||||||
**Diagrams**
|
## Diagrams
|
||||||
|
|
||||||
- [Architecture](docs/diagrams/pdf/architecture.pdf) - Layered architecture
|
- [Architecture](docs/diagrams-out/architecture.svg) - Layered architecture
|
||||||
- [Deployment](docs/diagrams/pdf/deployment.pdf) - Docker topology
|
- [Deployment](docs/diagrams-out/deployment.svg) - Docker topology
|
||||||
- [Authentication Flow](docs/diagrams/pdf/authentication-flow.pdf) - Auth sequence
|
- [Authentication Flow](docs/diagrams-out/authentication-flow.svg) - Auth sequence
|
||||||
- [Database Schema](docs/diagrams/pdf/database-schema.pdf) - Entity relationships
|
- [Database Schema](docs/diagrams-out/database-schema.svg) - Entity relationships
|
||||||
|
|
||||||
## Project Status
|
## Current Status
|
||||||
|
|
||||||
**Active Development** - Transitioning from full-stack Next.js to multi-project monorepo
|
Active areas in the repository:
|
||||||
|
|
||||||
- Core authentication and user management APIs
|
- .NET 10 backend with layered architecture and SQL Server
|
||||||
- Database schema with migrations and seeding
|
- React Router 7 website in `src/Website`
|
||||||
- Layered architecture (Domain, Service, Infrastructure, Repository, API)
|
- Shared Biergarten theme system with a theme guide route
|
||||||
- Comprehensive test suite (unit + integration)
|
- Storybook stories and browser-based checks for shared UI
|
||||||
- Frontend integration with .NET API (in progress)
|
- Auth demo flows for home, login, register, dashboard, logout, and confirmation
|
||||||
- Migration from Next.js serverless functions
|
- Toast-based feedback for auth outcomes
|
||||||
|
|
||||||
---
|
Legacy area retained for reference:
|
||||||
|
|
||||||
|
- `src/Website-v1` contains the archived Next.js frontend and is no longer the active website
|
||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
**Backend**: .NET 10, ASP.NET Core, SQL Server 2022, DbUp **Frontend**: Next.js 14+,
|
- **Backend**: .NET 10, ASP.NET Core, SQL Server 2022, DbUp
|
||||||
TypeScript, TailwindCSS **Testing**: xUnit, Reqnroll (BDD), FluentAssertions, Moq
|
- **Frontend**: React 19, React Router 7, Vite 7, Tailwind CSS 4, DaisyUI 5
|
||||||
**Infrastructure**: Docker, Docker Compose **Security**: Argon2id password hashing, JWT
|
- **UI Documentation**: Storybook 10, Vitest browser mode, Playwright
|
||||||
(HS256)
|
- **Testing**: xUnit, Reqnroll (BDD), FluentAssertions, Moq
|
||||||
|
- **Infrastructure**: Docker, Docker Compose
|
||||||
---
|
- **Security**: Argon2id password hashing, JWT access/refresh/confirmation tokens
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Prerequisites
|
### Backend
|
||||||
|
|
||||||
- [.NET SDK 10+](https://dotnet.microsoft.com/download)
|
|
||||||
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
|
|
||||||
- [Node.js 18+](https://nodejs.org/) (for frontend)
|
|
||||||
|
|
||||||
### Start Development Environment
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone repository
|
|
||||||
git clone https://github.com/aaronpo97/the-biergarten-app
|
git clone https://github.com/aaronpo97/the-biergarten-app
|
||||||
cd the-biergarten-app
|
cd the-biergarten-app
|
||||||
|
|
||||||
# Configure environment
|
|
||||||
cp .env.example .env.dev
|
cp .env.example .env.dev
|
||||||
|
|
||||||
# Start all services
|
|
||||||
docker compose -f docker-compose.dev.yaml up -d
|
docker compose -f docker-compose.dev.yaml up -d
|
||||||
|
|
||||||
# View logs
|
|
||||||
docker compose -f docker-compose.dev.yaml logs -f
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Access**:
|
Backend access:
|
||||||
|
|
||||||
- API: http://localhost:8080/swagger
|
- API Swagger: http://localhost:8080/swagger
|
||||||
- Health: http://localhost:8080/health
|
- Health Check: http://localhost:8080/health
|
||||||
|
|
||||||
### Run Tests
|
### Frontend
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
|
cd src/Website
|
||||||
|
npm install
|
||||||
|
API_BASE_URL=http://localhost:8080 SESSION_SECRET=dev-secret npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Results are in `./test-results/`
|
Optional frontend tools:
|
||||||
|
|
||||||
---
|
```bash
|
||||||
|
cd src/Website
|
||||||
|
npm run storybook
|
||||||
|
npm run test:storybook
|
||||||
|
npm run test:storybook:playwright
|
||||||
|
```
|
||||||
|
|
||||||
## Repository Structure
|
## Repository Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/Core/ Backend projects (.NET)
|
||||||
|
src/Website/ Active React Router frontend
|
||||||
|
src/Website-v1/ Archived legacy Next.js frontend
|
||||||
|
docs/ Active project documentation
|
||||||
|
docs/archive/ Archived legacy documentation
|
||||||
```
|
```
|
||||||
src/Core/ # Backend (.NET)
|
|
||||||
├── API/
|
|
||||||
│ ├── API.Core/ # ASP.NET Core Web API
|
|
||||||
│ └── API.Specs/ # Integration tests (Reqnroll)
|
|
||||||
├── Database/
|
|
||||||
│ ├── Database.Migrations/ # DbUp migrations
|
|
||||||
│ └── Database.Seed/ # Data seeding
|
|
||||||
├── Domain.Entities/ # Domain models
|
|
||||||
├── Infrastructure/ # Cross-cutting concerns
|
|
||||||
│ ├── Infrastructure.Jwt/
|
|
||||||
│ ├── Infrastructure.PasswordHashing/
|
|
||||||
│ ├── Infrastructure.Email/
|
|
||||||
│ ├── Infrastructure.Repository/
|
|
||||||
│ └── Infrastructure.Repository.Tests/
|
|
||||||
└── Service/ # Business logic
|
|
||||||
├── Service.Auth/
|
|
||||||
├── Service.Auth.Tests/
|
|
||||||
└── Service.UserManagement/
|
|
||||||
|
|
||||||
Website/ # Frontend (Next.js)
|
|
||||||
docs/ # Documentation
|
|
||||||
docs/diagrams/ # PlantUML diagrams
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
### Implemented
|
Implemented today:
|
||||||
|
|
||||||
- User registration and authentication
|
- User registration and login against the API
|
||||||
- JWT token-based auth
|
- JWT-based auth with access, refresh, and confirmation flows
|
||||||
- Argon2id password hashing
|
- SQL Server migrations and seed projects
|
||||||
- SQL Server with stored procedures
|
- Shared form components and auth screens
|
||||||
- Database migrations (DbUp)
|
- Theme switching with Lager, Stout, Cassis, and Weizen variants
|
||||||
- Docker containerization
|
- Storybook documentation and automated story interaction tests
|
||||||
- Comprehensive test suite
|
- Toast feedback for auth-related outcomes
|
||||||
- Swagger/OpenAPI documentation
|
|
||||||
- Health checks
|
|
||||||
|
|
||||||
### Planned
|
Planned next:
|
||||||
|
|
||||||
- [ ] Brewery discovery and management
|
- Brewery discovery and management
|
||||||
- [ ] Beer reviews and ratings
|
- Beer reviews and ratings
|
||||||
- [ ] Social following/followers
|
- Social follow relationships
|
||||||
- [ ] Geospatial brewery search
|
- Geospatial brewery experiences
|
||||||
- [ ] Image upload (Cloudinary)
|
- Additional frontend routes beyond the auth demo
|
||||||
- [ ] Email notifications
|
|
||||||
- [ ] OAuth integration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture Highlights
|
|
||||||
|
|
||||||
### Layered Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
API Layer (Controllers)
|
|
||||||
│
|
|
||||||
Service Layer (Business Logic)
|
|
||||||
│
|
|
||||||
Infrastructure Layer (Repositories, JWT, Email)
|
|
||||||
│
|
|
||||||
Domain Layer (Entities)
|
|
||||||
│
|
|
||||||
Database (SQL Server + Stored Procedures)
|
|
||||||
```
|
|
||||||
|
|
||||||
### SQL-First Approach
|
|
||||||
|
|
||||||
- All queries via stored procedures
|
|
||||||
- No ORM (no Entity Framework)
|
|
||||||
- Version-controlled schema
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- **Password Hashing**: Argon2id (64MB memory, 4 iterations)
|
|
||||||
- **JWT Tokens**: HS256 with configurable expiration
|
|
||||||
- **Credential Rotation**: Built-in password change support
|
|
||||||
|
|
||||||
See [Architecture Guide](docs/architecture.md) for details.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The project includes three test suites:
|
Backend suites:
|
||||||
|
|
||||||
| Suite | Type | Framework | Purpose |
|
- `API.Specs` - integration tests
|
||||||
| ---------------------- | ----------- | -------------- | ---------------------- |
|
- `Infrastructure.Repository.Tests` - repository unit tests
|
||||||
| **API.Specs** | Integration | Reqnroll (BDD) | End-to-end API testing |
|
- `Service.Auth.Tests` - service unit tests
|
||||||
| **Repository.Tests** | Unit | xUnit | Data access layer |
|
|
||||||
| **Service.Auth.Tests** | Unit | xUnit + Moq | Business logic |
|
|
||||||
|
|
||||||
**Run All Tests**:
|
Frontend suites:
|
||||||
|
|
||||||
|
- Storybook interaction tests via Vitest
|
||||||
|
- Storybook browser regression checks via Playwright
|
||||||
|
|
||||||
|
Run all backend tests with Docker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
|
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Run Individual Test Suite**:
|
See [Testing](docs/testing.md) for the full command list.
|
||||||
|
|
||||||
```bash
|
|
||||||
cd src/Core
|
|
||||||
dotnet test API/API.Specs/API.Specs.csproj
|
|
||||||
dotnet test Infrastructure/Infrastructure.Repository.Tests/Infrastructure.Repository.Tests.csproj
|
|
||||||
dotnet test Service/Service.Auth.Tests/Service.Auth.Tests.csproj
|
|
||||||
```
|
|
||||||
|
|
||||||
See [Testing Guide](docs/testing.md) for more information.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Docker Environments
|
|
||||||
|
|
||||||
The project uses three Docker Compose configurations:
|
|
||||||
|
|
||||||
| File | Purpose | Features |
|
|
||||||
| ---------------------------- | ------------- | ------------------------------------------------- |
|
|
||||||
| **docker-compose.dev.yaml** | Development | Persistent data, hot reload, Swagger UI |
|
|
||||||
| **docker-compose.test.yaml** | CI/CD Testing | Isolated DB, auto-exit, test results export |
|
|
||||||
| **docker-compose.prod.yaml** | Production | Optimized builds, health checks, restart policies |
|
|
||||||
|
|
||||||
**Common Commands**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Development
|
|
||||||
docker compose -f docker-compose.dev.yaml up -d
|
|
||||||
docker compose -f docker-compose.dev.yaml logs -f api.core
|
|
||||||
docker compose -f docker-compose.dev.yaml down -v
|
|
||||||
|
|
||||||
# Testing
|
|
||||||
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
|
|
||||||
docker compose -f docker-compose.test.yaml down -v
|
|
||||||
|
|
||||||
# Build
|
|
||||||
docker compose -f docker-compose.dev.yaml build
|
|
||||||
docker compose -f docker-compose.dev.yaml build --no-cache
|
|
||||||
```
|
|
||||||
|
|
||||||
See [Docker Guide](docs/docker.md) for troubleshooting and advanced usage.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Required Environment Variables
|
Common active variables:
|
||||||
|
|
||||||
**Backend** (`.env.dev`):
|
- Backend: `DB_SERVER`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `ACCESS_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `CONFIRMATION_TOKEN_SECRET`
|
||||||
|
- Frontend: `API_BASE_URL`, `SESSION_SECRET`, `NODE_ENV`
|
||||||
|
|
||||||
```bash
|
See [Environment Variables](docs/environment-variables.md) for details.
|
||||||
DB_SERVER=sqlserver,1433
|
|
||||||
DB_NAME=Biergarten
|
|
||||||
DB_USER=sa
|
|
||||||
DB_PASSWORD=YourStrong!Passw0rd
|
|
||||||
JWT_SECRET=<min-32-chars>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Frontend** (`.env.local`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
BASE_URL=http://localhost:3000
|
|
||||||
NODE_ENV=development
|
|
||||||
CONFIRMATION_TOKEN_SECRET=<generated>
|
|
||||||
RESET_PASSWORD_TOKEN_SECRET=<generated>
|
|
||||||
SESSION_SECRET=<generated>
|
|
||||||
# + External services (Cloudinary, Mapbox, SparkPost)
|
|
||||||
```
|
|
||||||
|
|
||||||
See [Environment Variables Guide](docs/environment-variables.md) for complete reference.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
This document describes the architecture patterns and design decisions for The Biergarten
|
This document describes the active architecture of The Biergarten App.
|
||||||
App.
|
|
||||||
|
|
||||||
## High-Level Overview
|
## High-Level Overview
|
||||||
|
|
||||||
The Biergarten App follows a **multi-project monorepo** architecture with clear separation
|
The Biergarten App is a monorepo with a clear split between the backend and the active
|
||||||
between backend and frontend:
|
website:
|
||||||
|
|
||||||
- **Backend**: .NET 10 Web API with SQL Server
|
- **Backend**: .NET 10 Web API with SQL Server and a layered architecture
|
||||||
- **Frontend**: Next.js with TypeScript
|
- **Frontend**: React 19 + React Router 7 website in `src/Website`
|
||||||
- **Architecture Style**: Layered architecture with SQL-first approach
|
- **Architecture Style**: Layered backend plus server-rendered React frontend
|
||||||
|
|
||||||
|
The legacy Next.js frontend has been retained in `src/Website-v1` for reference only and is
|
||||||
|
documented in [archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||||
|
|
||||||
## Diagrams
|
## Diagrams
|
||||||
|
|
||||||
For visual representations, see:
|
For visual representations, see:
|
||||||
|
|
||||||
- [architecture.pdf](diagrams/pdf/architecture.pdf) - Layered architecture diagram
|
- [architecture.svg](diagrams-out/architecture.svg) - Layered architecture diagram
|
||||||
- [deployment.pdf](diagrams/pdf/deployment.pdf) - Docker deployment diagram
|
- [deployment.svg](diagrams-out/deployment.svg) - Docker deployment diagram
|
||||||
- [authentication-flow.pdf](diagrams/pdf/authentication-flow.pdf) - Authentication
|
- [authentication-flow.svg](diagrams-out/authentication-flow.svg) - Authentication workflow
|
||||||
workflow
|
- [database-schema.svg](diagrams-out/database-schema.svg) - Database relationships
|
||||||
- [database-schema.pdf](diagrams/pdf/database-schema.pdf) - Database relationships
|
|
||||||
|
|
||||||
Generate diagrams with: `make diagrams`
|
|
||||||
|
|
||||||
## Backend Architecture
|
## Backend Architecture
|
||||||
|
|
||||||
@@ -217,39 +216,49 @@ public interface IAuthRepository
|
|||||||
|
|
||||||
## Frontend Architecture
|
## Frontend Architecture
|
||||||
|
|
||||||
### Next.js Application Structure
|
### Active Website (`src/Website`)
|
||||||
|
|
||||||
```
|
The current website is a React Router 7 application with server-side rendering enabled.
|
||||||
Website/src/
|
|
||||||
├── components/ # React components
|
```text
|
||||||
├── pages/ # Next.js routes
|
src/Website/
|
||||||
├── contexts/ # React context providers
|
├── app/
|
||||||
├── hooks/ # Custom React hooks
|
│ ├── components/ Shared UI such as Navbar, FormField, SubmitButton, ToastProvider
|
||||||
├── controllers/ # Business logic layer
|
│ ├── lib/ Auth helpers, schemas, and theme metadata
|
||||||
├── services/ # API communication
|
│ ├── routes/ Route modules for home, login, register, dashboard, confirm, theme
|
||||||
├── requests/ # API request builders
|
│ ├── root.tsx App shell and global providers
|
||||||
├── validation/ # Form validation schemas
|
│ └── app.css Theme tokens and global styling
|
||||||
├── config/ # Configuration & env vars
|
├── .storybook/ Storybook config and preview setup
|
||||||
└── prisma/ # Database schema (current)
|
├── stories/ Storybook stories for shared UI and themes
|
||||||
|
├── tests/playwright/ Storybook Playwright coverage
|
||||||
|
└── package.json Frontend scripts and dependencies
|
||||||
```
|
```
|
||||||
|
|
||||||
### Migration Strategy
|
### Frontend Responsibilities
|
||||||
|
|
||||||
The frontend is **transitioning** from a standalone architecture to integrate with the
|
- Render the auth demo and theme guide routes
|
||||||
.NET API:
|
- Manage cookie-backed website session state
|
||||||
|
- Call the .NET API for login, registration, token refresh, and confirmation
|
||||||
|
- Provide shared UI building blocks for forms, navigation, themes, and toasts
|
||||||
|
- Supply Storybook documentation and browser-based component verification
|
||||||
|
|
||||||
**Current State**:
|
### Theme System
|
||||||
|
|
||||||
- Uses Prisma ORM with Postgres (Neon)
|
The active website uses semantic DaisyUI theme tokens backed by four Biergarten themes:
|
||||||
- Has its own server-side API routes
|
|
||||||
- Direct database access from Next.js
|
|
||||||
|
|
||||||
**Target State**:
|
- Biergarten Lager
|
||||||
|
- Biergarten Stout
|
||||||
|
- Biergarten Cassis
|
||||||
|
- Biergarten Weizen
|
||||||
|
|
||||||
- Pure client-side Next.js app
|
All component styling should prefer semantic tokens such as `primary`, `success`,
|
||||||
- All data via .NET API
|
`surface`, and `highlight` instead of hard-coded color values.
|
||||||
- No server-side database access
|
|
||||||
- JWT-based authentication
|
### Legacy Frontend
|
||||||
|
|
||||||
|
The previous Next.js frontend has been archived at `src/Website-v1`. Active product and
|
||||||
|
engineering documentation should point to `src/Website`, while legacy notes live in
|
||||||
|
[archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||||
|
|
||||||
## Security Architecture
|
## Security Architecture
|
||||||
|
|
||||||
@@ -385,7 +394,7 @@ dependencies
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD-SHELL', 'sqlcmd health check']
|
test: ["CMD-SHELL", "sqlcmd health check"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
retries: 12
|
retries: 12
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
|||||||
56
docs/archive/legacy-website-v1.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Legacy Website Archive (`src/Website-v1`)
|
||||||
|
|
||||||
|
This archive captures high-level notes about the previous Biergarten frontend so active
|
||||||
|
project documentation can focus on the current website in `src/Website`.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- `src/Website-v1` is retained for historical reference only
|
||||||
|
- It is not the active frontend used by current setup, docs, or testing guidance
|
||||||
|
- New product and engineering work should target `src/Website`
|
||||||
|
|
||||||
|
## Legacy Stack Summary
|
||||||
|
|
||||||
|
The archived frontend used a different application model from the current website:
|
||||||
|
|
||||||
|
- Next.js 14
|
||||||
|
- React 18
|
||||||
|
- Prisma
|
||||||
|
- Postgres / Neon-hosted database workflows
|
||||||
|
- Next.js API routes and server-side controllers
|
||||||
|
- Additional third-party integrations such as Cloudinary, Mapbox, and SparkPost
|
||||||
|
|
||||||
|
## Why It Was Archived
|
||||||
|
|
||||||
|
The active website moved to a React Router-based frontend that talks directly to the .NET
|
||||||
|
API. As part of that shift, the main docs were updated to describe:
|
||||||
|
|
||||||
|
- `src/Website` as the active frontend
|
||||||
|
- React Router route modules and server rendering
|
||||||
|
- Storybook-based component documentation and tests
|
||||||
|
- Current frontend runtime variables: `API_BASE_URL`, `SESSION_SECRET`, and `NODE_ENV`
|
||||||
|
|
||||||
|
## Legacy Documentation Topics Moved Out of Active Docs
|
||||||
|
|
||||||
|
The following categories were removed from active documentation and intentionally archived:
|
||||||
|
|
||||||
|
- Next.js application structure guidance
|
||||||
|
- Prisma and Postgres frontend setup
|
||||||
|
- Legacy frontend environment variables
|
||||||
|
- External service setup that only applied to `src/Website-v1`
|
||||||
|
- Old frontend local setup instructions
|
||||||
|
|
||||||
|
## When To Use This Archive
|
||||||
|
|
||||||
|
Use this file only if you need to:
|
||||||
|
|
||||||
|
- inspect the historical frontend implementation
|
||||||
|
- compare old flows against the current website
|
||||||
|
- migrate or recover legacy logic from `src/Website-v1`
|
||||||
|
|
||||||
|
For all active work, use:
|
||||||
|
|
||||||
|
- [Getting Started](../getting-started.md)
|
||||||
|
- [Architecture](../architecture.md)
|
||||||
|
- [Environment Variables](../environment-variables.md)
|
||||||
|
- [Testing](../testing.md)
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
# Environment Variables
|
# Environment Variables
|
||||||
|
|
||||||
Complete documentation for all environment variables used in The Biergarten App.
|
This document covers the active environment variables used by the current Biergarten
|
||||||
|
stack.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The application uses environment variables for configuration across:
|
The application uses environment variables for:
|
||||||
|
|
||||||
- **.NET API Backend** - Database connections, JWT secrets
|
- **.NET API backend** - database connections, token secrets, runtime settings
|
||||||
- **Next.js Frontend** - External services, authentication
|
- **React Router website** - API base URL and session signing
|
||||||
- **Docker Containers** - Runtime configuration
|
- **Docker containers** - environment-specific orchestration
|
||||||
|
|
||||||
## Configuration Patterns
|
## Configuration Patterns
|
||||||
|
|
||||||
@@ -16,10 +17,10 @@ The application uses environment variables for configuration across:
|
|||||||
|
|
||||||
Direct environment variable access via `Environment.GetEnvironmentVariable()`.
|
Direct environment variable access via `Environment.GetEnvironmentVariable()`.
|
||||||
|
|
||||||
### Frontend (Next.js)
|
### Frontend (`src/Website`)
|
||||||
|
|
||||||
Centralized configuration module at `src/Website/src/config/env/index.ts` with Zod
|
The active website reads runtime values from the server environment for its auth and API
|
||||||
validation.
|
integration.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
@@ -128,91 +129,38 @@ ASPNETCORE_URLS=http://0.0.0.0:8080 # Binding address and port
|
|||||||
DOTNET_RUNNING_IN_CONTAINER=true # Flag for container execution
|
DOTNET_RUNNING_IN_CONTAINER=true # Flag for container execution
|
||||||
```
|
```
|
||||||
|
|
||||||
## Frontend Variables (Next.js)
|
## Frontend Variables (`src/Website`)
|
||||||
|
|
||||||
Create `.env.local` in the `Website/` directory.
|
The active website does not use the old Next.js/Prisma environment model. Its core runtime
|
||||||
|
variables are:
|
||||||
### Base Configuration
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
BASE_URL=http://localhost:3000 # Application base URL
|
API_BASE_URL=http://localhost:8080 # Base URL for the .NET API
|
||||||
NODE_ENV=development # Environment: development, production, test
|
SESSION_SECRET=<generated-secret> # Cookie session signing secret
|
||||||
|
NODE_ENV=development # Standard Node runtime mode
|
||||||
```
|
```
|
||||||
|
|
||||||
### Authentication & Sessions
|
### Frontend Variable Details
|
||||||
|
|
||||||
```bash
|
#### `API_BASE_URL`
|
||||||
# Token signing secrets (use openssl rand -base64 127)
|
|
||||||
CONFIRMATION_TOKEN_SECRET=<generated-secret> # Email confirmation tokens
|
|
||||||
RESET_PASSWORD_TOKEN_SECRET=<generated-secret> # Password reset tokens
|
|
||||||
SESSION_SECRET=<generated-secret> # Session cookie signing
|
|
||||||
|
|
||||||
# Session configuration
|
- **Required**: Yes for local development
|
||||||
SESSION_TOKEN_NAME=biergarten # Cookie name (optional)
|
- **Default in code**: `http://localhost:8080`
|
||||||
SESSION_MAX_AGE=604800 # Cookie max age in seconds (optional, default: 1 week)
|
- **Used by**: `src/Website/app/lib/auth.server.ts`
|
||||||
```
|
- **Purpose**: Routes website auth actions to the .NET API
|
||||||
|
|
||||||
**Security Requirements**:
|
#### `SESSION_SECRET`
|
||||||
|
|
||||||
- All secrets should be 127+ characters
|
- **Required**: Strongly recommended in all environments
|
||||||
- Generate using cryptographically secure random functions
|
- **Default in local code path**: `dev-secret-change-me`
|
||||||
- Never reuse secrets across environments
|
- **Used by**: React Router cookie session storage in `auth.server.ts`
|
||||||
- Rotate secrets periodically in production
|
- **Purpose**: Signs and validates the website session cookie
|
||||||
|
|
||||||
### Database (Current - Prisma/Postgres)
|
#### `NODE_ENV`
|
||||||
|
|
||||||
**Note**: Frontend currently uses Neon Postgres. Will migrate to .NET API.
|
- **Required**: No
|
||||||
|
- **Typical values**: `development`, `production`, `test`
|
||||||
```bash
|
- **Purpose**: Controls secure cookie behavior and runtime mode
|
||||||
POSTGRES_PRISMA_URL=postgresql://user:pass@host/db?pgbouncer=true # Pooled connection
|
|
||||||
POSTGRES_URL_NON_POOLING=postgresql://user:pass@host/db # Direct connection (migrations)
|
|
||||||
SHADOW_DATABASE_URL=postgresql://user:pass@host/shadow_db # Prisma shadow DB (optional)
|
|
||||||
```
|
|
||||||
|
|
||||||
### External Services
|
|
||||||
|
|
||||||
#### Cloudinary (Image Hosting)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=your-cloud-name # Public, client-accessible
|
|
||||||
CLOUDINARY_KEY=your-api-key # Server-side API key
|
|
||||||
CLOUDINARY_SECRET=your-api-secret # Server-side secret
|
|
||||||
```
|
|
||||||
|
|
||||||
**Setup Steps**:
|
|
||||||
|
|
||||||
1. Sign up at [cloudinary.com](https://cloudinary.com)
|
|
||||||
2. Navigate to Dashboard
|
|
||||||
3. Copy Cloud Name, API Key, and API Secret
|
|
||||||
|
|
||||||
**Note**: `NEXT_PUBLIC_` prefix makes variable accessible in client-side code.
|
|
||||||
|
|
||||||
#### Mapbox (Maps & Geocoding)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
MAPBOX_ACCESS_TOKEN=pk.your-public-token
|
|
||||||
```
|
|
||||||
|
|
||||||
**Setup Steps**:
|
|
||||||
|
|
||||||
1. Create account at [mapbox.com](https://mapbox.com)
|
|
||||||
2. Navigate to Account → Tokens
|
|
||||||
3. Create new token with public scopes
|
|
||||||
4. Copy access token
|
|
||||||
|
|
||||||
#### SparkPost (Email Service)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SPARKPOST_API_KEY=your-api-key
|
|
||||||
SPARKPOST_SENDER_ADDRESS=noreply@yourdomain.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**Setup Steps**:
|
|
||||||
|
|
||||||
1. Sign up at [sparkpost.com](https://sparkpost.com)
|
|
||||||
2. Verify sending domain or use sandbox
|
|
||||||
3. Create API key with "Send via SMTP" permission
|
|
||||||
4. Configure sender address (must match verified domain)
|
|
||||||
|
|
||||||
### Admin Account (Seeding)
|
### Admin Account (Seeding)
|
||||||
|
|
||||||
@@ -258,69 +206,39 @@ cp .env.example .env.dev
|
|||||||
# Edit .env.dev with your values
|
# Edit .env.dev with your values
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Legacy Frontend Variables
|
||||||
|
|
||||||
|
Variables for the archived Next.js frontend (`src/Website-v1`) have been removed from this
|
||||||
|
active reference. See [archive/legacy-website-v1.md](archive/legacy-website-v1.md) if you
|
||||||
|
need the legacy Prisma, Cloudinary, Mapbox, or SparkPost notes.
|
||||||
|
|
||||||
**Docker Compose Mapping**:
|
**Docker Compose Mapping**:
|
||||||
|
|
||||||
- `docker-compose.dev.yaml` → `.env.dev`
|
- `docker-compose.dev.yaml` → `.env.dev`
|
||||||
- `docker-compose.test.yaml` → `.env.test`
|
- `docker-compose.test.yaml` → `.env.test`
|
||||||
- `docker-compose.prod.yaml` → `.env.prod`
|
- `docker-compose.prod.yaml` → `.env.prod`
|
||||||
|
|
||||||
### Frontend (Website Directory)
|
|
||||||
|
|
||||||
```
|
|
||||||
.env.local # Local development (gitignored)
|
|
||||||
.env.production # Production (gitignored)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Setup**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd Website
|
|
||||||
touch .env.local
|
|
||||||
# Add frontend variables
|
|
||||||
```
|
|
||||||
|
|
||||||
## Variable Reference Table
|
## Variable Reference Table
|
||||||
|
|
||||||
| Variable | Backend | Frontend | Docker | Required | Notes |
|
| Variable | Backend | Frontend | Docker | Required | Notes |
|
||||||
| ----------------------------------- | :-----: | :------: | :----: | :------: | ------------------------- |
|
| ----------------------------- | :-----: | :------: | :----: | :------: | -------------------------- |
|
||||||
| **Database** |
|
|
||||||
| `DB_SERVER` | ✓ | | ✓ | Yes\* | SQL Server address |
|
| `DB_SERVER` | ✓ | | ✓ | Yes\* | SQL Server address |
|
||||||
| `DB_NAME` | ✓ | | ✓ | Yes\* | Database name |
|
| `DB_NAME` | ✓ | | ✓ | Yes\* | Database name |
|
||||||
| `DB_USER` | ✓ | | ✓ | Yes\* | SQL username |
|
| `DB_USER` | ✓ | | ✓ | Yes\* | SQL username |
|
||||||
| `DB_PASSWORD` | ✓ | | ✓ | Yes\* | SQL password |
|
| `DB_PASSWORD` | ✓ | | ✓ | Yes\* | SQL password |
|
||||||
| `DB_CONNECTION_STRING` | ✓ | | | Yes\* | Alternative to components |
|
| `DB_CONNECTION_STRING` | ✓ | | | Yes\* | Alternative to components |
|
||||||
| `DB_TRUST_SERVER_CERTIFICATE` | ✓ | | ✓ | No | Defaults to True |
|
| `DB_TRUST_SERVER_CERTIFICATE` | ✓ | | ✓ | No | Defaults to `True` |
|
||||||
| `SA_PASSWORD` | | | ✓ | Yes | SQL Server container |
|
| `ACCESS_TOKEN_SECRET` | ✓ | | ✓ | Yes | Access token signing |
|
||||||
| **Authentication (Backend - JWT)** |
|
| `REFRESH_TOKEN_SECRET` | ✓ | | ✓ | Yes | Refresh token signing |
|
||||||
| `ACCESS_TOKEN_SECRET` | ✓ | | ✓ | Yes | Access token secret |
|
| `CONFIRMATION_TOKEN_SECRET` | ✓ | | ✓ | Yes | Confirmation token signing |
|
||||||
| `REFRESH_TOKEN_SECRET` | ✓ | | ✓ | Yes | Refresh token secret |
|
|
||||||
| `CONFIRMATION_TOKEN_SECRET` | ✓ | | ✓ | Yes | Confirmation token secret |
|
|
||||||
| `WEBSITE_BASE_URL` | ✓ | | | Yes | Website URL for emails |
|
| `WEBSITE_BASE_URL` | ✓ | | | Yes | Website URL for emails |
|
||||||
| **Authentication (Frontend)** |
|
| `API_BASE_URL` | | ✓ | | Yes | Website-to-API base URL |
|
||||||
| `CONFIRMATION_TOKEN_SECRET` | | ✓ | | Yes | Email confirmation |
|
| `SESSION_SECRET` | | ✓ | | Yes | Website session signing |
|
||||||
| `RESET_PASSWORD_TOKEN_SECRET` | | ✓ | | Yes | Password reset |
|
| `NODE_ENV` | | ✓ | | No | Runtime mode |
|
||||||
| `SESSION_SECRET` | | ✓ | | Yes | Session signing |
|
| `CLEAR_DATABASE` | ✓ | | ✓ | No | Dev/test reset flag |
|
||||||
| `SESSION_TOKEN_NAME` | | ✓ | | No | Default: "biergarten" |
|
|
||||||
| `SESSION_MAX_AGE` | | ✓ | | No | Default: 604800 |
|
|
||||||
| **Base Configuration** |
|
|
||||||
| `BASE_URL` | | ✓ | | Yes | App base URL |
|
|
||||||
| `NODE_ENV` | | ✓ | | Yes | Node environment |
|
|
||||||
| `ASPNETCORE_ENVIRONMENT` | ✓ | | ✓ | Yes | ASP.NET environment |
|
| `ASPNETCORE_ENVIRONMENT` | ✓ | | ✓ | Yes | ASP.NET environment |
|
||||||
| `ASPNETCORE_URLS` | ✓ | | ✓ | Yes | API binding address |
|
| `ASPNETCORE_URLS` | ✓ | | ✓ | Yes | API binding address |
|
||||||
| **Database (Frontend - Current)** |
|
| `SA_PASSWORD` | | | ✓ | Yes | SQL Server container |
|
||||||
| `POSTGRES_PRISMA_URL` | | ✓ | | Yes | Pooled connection |
|
|
||||||
| `POSTGRES_URL_NON_POOLING` | | ✓ | | Yes | Direct connection |
|
|
||||||
| `SHADOW_DATABASE_URL` | | ✓ | | No | Prisma shadow DB |
|
|
||||||
| **External Services** |
|
|
||||||
| `NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME` | | ✓ | | Yes | Public, client-side |
|
|
||||||
| `CLOUDINARY_KEY` | | ✓ | | Yes | Server-side |
|
|
||||||
| `CLOUDINARY_SECRET` | | ✓ | | Yes | Server-side |
|
|
||||||
| `MAPBOX_ACCESS_TOKEN` | | ✓ | | Yes | Maps/geocoding |
|
|
||||||
| `SPARKPOST_API_KEY` | | ✓ | | Yes | Email service |
|
|
||||||
| `SPARKPOST_SENDER_ADDRESS` | | ✓ | | Yes | From address |
|
|
||||||
| **Other** |
|
|
||||||
| `ADMIN_PASSWORD` | | ✓ | | No | Seeding only |
|
|
||||||
| `CLEAR_DATABASE` | ✓ | | ✓ | No | Dev/test only |
|
|
||||||
| `ACCEPT_EULA` | | | ✓ | Yes | SQL Server EULA |
|
| `ACCEPT_EULA` | | | ✓ | Yes | SQL Server EULA |
|
||||||
| `MSSQL_PID` | | | ✓ | No | SQL Server edition |
|
| `MSSQL_PID` | | | ✓ | No | SQL Server edition |
|
||||||
| `DOTNET_RUNNING_IN_CONTAINER` | ✓ | | ✓ | No | Container flag |
|
| `DOTNET_RUNNING_IN_CONTAINER` | ✓ | | ✓ | No | Container flag |
|
||||||
@@ -340,13 +258,12 @@ Variables are validated at startup:
|
|||||||
|
|
||||||
### Frontend Validation
|
### Frontend Validation
|
||||||
|
|
||||||
Zod schemas validate variables at runtime:
|
The active website relies on runtime defaults for local development and the surrounding
|
||||||
|
server environment in deployed environments.
|
||||||
|
|
||||||
- Type checking (string, number, URL, etc.)
|
- `API_BASE_URL` defaults to `http://localhost:8080`
|
||||||
- Format validation (email, URL patterns)
|
- `SESSION_SECRET` falls back to a development-only local secret
|
||||||
- Required vs optional enforcement
|
- `NODE_ENV` controls secure cookie behavior
|
||||||
|
|
||||||
**Location**: `src/Website/src/config/env/index.ts`
|
|
||||||
|
|
||||||
## Example Configuration Files
|
## Example Configuration Files
|
||||||
|
|
||||||
@@ -378,28 +295,10 @@ ACCEPT_EULA=Y
|
|||||||
MSSQL_PID=Express
|
MSSQL_PID=Express
|
||||||
```
|
```
|
||||||
|
|
||||||
### `.env.local` (Frontend)
|
### Frontend local runtime example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Base
|
API_BASE_URL=http://localhost:8080
|
||||||
BASE_URL=http://localhost:3000
|
|
||||||
NODE_ENV=development
|
|
||||||
|
|
||||||
# Authentication
|
|
||||||
SESSION_SECRET=<generated-with-openssl>
|
SESSION_SECRET=<generated-with-openssl>
|
||||||
|
NODE_ENV=development
|
||||||
# Database (current Prisma setup)
|
|
||||||
POSTGRES_PRISMA_URL=postgresql://user:pass@db.neon.tech/biergarten?pgbouncer=true
|
|
||||||
POSTGRES_URL_NON_POOLING=postgresql://user:pass@db.neon.tech/biergarten
|
|
||||||
|
|
||||||
# External Services
|
|
||||||
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=my-cloud
|
|
||||||
CLOUDINARY_KEY=123456789012345
|
|
||||||
CLOUDINARY_SECRET=abcdefghijklmnopqrstuvwxyz
|
|
||||||
MAPBOX_ACCESS_TOKEN=pk.eyJ...
|
|
||||||
SPARKPOST_API_KEY=abc123...
|
|
||||||
SPARKPOST_SENDER_ADDRESS=noreply@biergarten.app
|
|
||||||
|
|
||||||
# Admin (for seeding)
|
|
||||||
ADMIN_PASSWORD=Admin_Dev_Password_123!
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
This guide will help you set up and run The Biergarten App in your development
|
This guide covers local setup for the current Biergarten stack: the .NET backend in
|
||||||
environment.
|
`src/Core` and the active React Router frontend in `src/Website`.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Before you begin, ensure you have the following installed:
|
- **.NET SDK 10+**
|
||||||
|
- **Node.js 18+**
|
||||||
|
- **Docker Desktop** or equivalent Docker Engine setup
|
||||||
|
- **Java 8+** if you want to regenerate PlantUML diagrams
|
||||||
|
|
||||||
- **.NET SDK 10+** - [Download](https://dotnet.microsoft.com/download)
|
## Recommended Path: Docker for Backend, Node for Frontend
|
||||||
- **Node.js 18+** - [Download](https://nodejs.org/)
|
|
||||||
- **Docker Desktop** - [Download](https://www.docker.com/products/docker-desktop)
|
|
||||||
(recommended)
|
|
||||||
- **Java 8+** - Required for generating diagrams from PlantUML (optional)
|
|
||||||
|
|
||||||
## Quick Start with Docker (Recommended)
|
|
||||||
|
|
||||||
### 1. Clone the Repository
|
### 1. Clone the Repository
|
||||||
|
|
||||||
@@ -22,174 +19,120 @@ git clone <repository-url>
|
|||||||
cd the-biergarten-app
|
cd the-biergarten-app
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Configure Environment Variables
|
### 2. Configure Backend Environment Variables
|
||||||
|
|
||||||
Copy the example environment file:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env.dev
|
cp .env.example .env.dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Edit `.env.dev` with your configuration:
|
At minimum, ensure `.env.dev` includes valid database and token values:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Database (component-based for Docker)
|
|
||||||
DB_SERVER=sqlserver,1433
|
DB_SERVER=sqlserver,1433
|
||||||
DB_NAME=Biergarten
|
DB_NAME=Biergarten
|
||||||
DB_USER=sa
|
DB_USER=sa
|
||||||
DB_PASSWORD=YourStrong!Passw0rd
|
DB_PASSWORD=YourStrong!Passw0rd
|
||||||
|
ACCESS_TOKEN_SECRET=<generated>
|
||||||
# JWT Authentication
|
REFRESH_TOKEN_SECRET=<generated>
|
||||||
JWT_SECRET=your-secret-key-minimum-32-characters-required
|
CONFIRMATION_TOKEN_SECRET=<generated>
|
||||||
|
WEBSITE_BASE_URL=http://localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
> For a complete list of environment variables, see
|
See [Environment Variables](environment-variables.md) for the full list.
|
||||||
> [Environment Variables](environment-variables.md).
|
|
||||||
|
|
||||||
### 3. Start the Development Environment
|
### 3. Start the Backend Stack
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.dev.yaml up -d
|
docker compose -f docker-compose.dev.yaml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will:
|
This starts SQL Server, migrations, seeding, and the API.
|
||||||
|
|
||||||
- Start SQL Server container
|
Available endpoints:
|
||||||
- Run database migrations
|
|
||||||
- Seed initial data
|
|
||||||
- Start the API on http://localhost:8080
|
|
||||||
|
|
||||||
### 4. Access the API
|
- API Swagger: http://localhost:8080/swagger
|
||||||
|
- Health Check: http://localhost:8080/health
|
||||||
|
|
||||||
- **Swagger UI**: http://localhost:8080/swagger
|
### 4. Start the Active Frontend
|
||||||
- **Health Check**: http://localhost:8080/health
|
|
||||||
|
|
||||||
### 5. View Logs
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# All services
|
cd src/Website
|
||||||
docker compose -f docker-compose.dev.yaml logs -f
|
npm install
|
||||||
|
API_BASE_URL=http://localhost:8080 SESSION_SECRET=dev-secret-change-me npm run dev
|
||||||
# Specific service
|
|
||||||
docker compose -f docker-compose.dev.yaml logs -f api.core
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Stop the Environment
|
The website will be available at the local address printed by React Router dev.
|
||||||
|
|
||||||
|
Required frontend runtime variables for local work:
|
||||||
|
|
||||||
|
- `API_BASE_URL` - Base URL for the .NET API
|
||||||
|
- `SESSION_SECRET` - Cookie session signing secret for the website server
|
||||||
|
|
||||||
|
### 5. Optional: Run Storybook
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.dev.yaml down
|
cd src/Website
|
||||||
|
npm run storybook
|
||||||
|
```
|
||||||
|
|
||||||
# Remove volumes (fresh start)
|
Storybook runs at http://localhost:6006 by default.
|
||||||
|
|
||||||
|
## Useful Commands
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.dev.yaml logs -f
|
||||||
|
docker compose -f docker-compose.dev.yaml down
|
||||||
docker compose -f docker-compose.dev.yaml down -v
|
docker compose -f docker-compose.dev.yaml down -v
|
||||||
```
|
```
|
||||||
|
|
||||||
## Manual Setup (Without Docker)
|
### Frontend
|
||||||
|
|
||||||
If you prefer to run services locally without Docker:
|
|
||||||
|
|
||||||
### Backend Setup
|
|
||||||
|
|
||||||
#### 1. Start SQL Server
|
|
||||||
|
|
||||||
You can use a local SQL Server instance or a cloud-hosted one. Ensure it's accessible and
|
|
||||||
you have the connection details.
|
|
||||||
|
|
||||||
#### 2. Set Environment Variables
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# macOS/Linux
|
cd src/Website
|
||||||
export DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
|
npm run lint
|
||||||
export JWT_SECRET="your-secret-key-minimum-32-characters-required"
|
npm run typecheck
|
||||||
|
npm run format:check
|
||||||
# Windows PowerShell
|
npm run test:storybook
|
||||||
$env:DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
|
npm run test:storybook:playwright
|
||||||
$env:JWT_SECRET="your-secret-key-minimum-32-characters-required"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3. Run Database Migrations
|
## Manual Backend Setup
|
||||||
|
|
||||||
|
If you do not want to use Docker, you can run the backend locally.
|
||||||
|
|
||||||
|
### 1. Set Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
|
||||||
|
export ACCESS_TOKEN_SECRET="<generated>"
|
||||||
|
export REFRESH_TOKEN_SECRET="<generated>"
|
||||||
|
export CONFIRMATION_TOKEN_SECRET="<generated>"
|
||||||
|
export WEBSITE_BASE_URL="http://localhost:3000"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Run Migrations and Seed
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd src/Core
|
cd src/Core
|
||||||
dotnet run --project Database/Database.Migrations/Database.Migrations.csproj
|
dotnet run --project Database/Database.Migrations/Database.Migrations.csproj
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Seed the Database
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet run --project Database/Database.Seed/Database.Seed.csproj
|
dotnet run --project Database/Database.Seed/Database.Seed.csproj
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. Start the API
|
### 3. Start the API
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet run --project API/API.Core/API.Core.csproj
|
dotnet run --project API/API.Core/API.Core.csproj
|
||||||
```
|
```
|
||||||
|
|
||||||
The API will be available at http://localhost:5000 (or the port specified in
|
## Legacy Frontend Note
|
||||||
launchSettings.json).
|
|
||||||
|
|
||||||
### Frontend Setup
|
|
||||||
|
|
||||||
> **Note**: The frontend is currently transitioning from its standalone Prisma/Postgres
|
|
||||||
> backend to the .NET API. Some features may still use the old backend.
|
|
||||||
|
|
||||||
#### 1. Navigate to Website Directory
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd Website
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. Create Environment File
|
|
||||||
|
|
||||||
Create `.env.local` with frontend variables. See
|
|
||||||
[Environment Variables - Frontend](environment-variables.md#frontend-variables) for the
|
|
||||||
complete list.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
BASE_URL=http://localhost:3000
|
|
||||||
NODE_ENV=development
|
|
||||||
|
|
||||||
# Generate secrets
|
|
||||||
CONFIRMATION_TOKEN_SECRET=$(openssl rand -base64 127)
|
|
||||||
RESET_PASSWORD_TOKEN_SECRET=$(openssl rand -base64 127)
|
|
||||||
SESSION_SECRET=$(openssl rand -base64 127)
|
|
||||||
|
|
||||||
# External services (you'll need to register for these)
|
|
||||||
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=your-cloud-name
|
|
||||||
CLOUDINARY_KEY=your-api-key
|
|
||||||
CLOUDINARY_SECRET=your-api-secret
|
|
||||||
NEXT_PUBLIC_MAPBOX_KEY=your-mapbox-token
|
|
||||||
|
|
||||||
# Database URL (current Prisma setup)
|
|
||||||
DATABASE_URL=your-postgres-connection-string
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Install Dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Run Prisma Migrations
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx prisma generate
|
|
||||||
npx prisma migrate dev
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5. Start Development Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
The frontend will be available at http://localhost:3000.
|
|
||||||
|
|
||||||
|
The previous Next.js frontend now lives in `src/Website-v1` and is not the active website.
|
||||||
|
Legacy setup details have been moved to [docs/archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
- **Test the API**: Visit http://localhost:8080/swagger and try the endpoints
|
- Review [Architecture](architecture.md)
|
||||||
- **Run Tests**: See [Testing Guide](testing.md)
|
- Run backend and frontend checks from [Testing](testing.md)
|
||||||
- **Learn the Architecture**: Read [Architecture Overview](architecture.md)
|
- Use [Docker Guide](docker.md) for container troubleshooting
|
||||||
- **Understand Docker Setup**: See [Docker Guide](docker.md)
|
|
||||||
- **Database Details**: Check [Database Schema](database.md)
|
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ This document describes the testing strategy and how to run tests for The Bierga
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The project uses a multi-layered testing approach:
|
The project uses a multi-layered testing approach across backend and frontend:
|
||||||
|
|
||||||
- **API.Specs** - BDD integration tests using Reqnroll (Gherkin)
|
- **API.Specs** - BDD integration tests using Reqnroll (Gherkin)
|
||||||
- **Infrastructure.Repository.Tests** - Unit tests for data access layer
|
- **Infrastructure.Repository.Tests** - Unit tests for data access layer
|
||||||
- **Service.Auth.Tests** - Unit tests for authentication business logic
|
- **Service.Auth.Tests** - Unit tests for authentication business logic
|
||||||
|
- **Storybook Vitest project** - Browser-based interaction tests for shared website stories
|
||||||
|
- **Storybook Playwright suite** - Browser checks against Storybook-rendered components
|
||||||
|
|
||||||
## Running Tests with Docker (Recommended)
|
## Running Tests with Docker (Recommended)
|
||||||
|
|
||||||
@@ -86,6 +88,33 @@ dotnet test Service/Service.Auth.Tests/Service.Auth.Tests.csproj
|
|||||||
|
|
||||||
- No database required (uses Moq for mocking)
|
- No database required (uses Moq for mocking)
|
||||||
|
|
||||||
|
### Frontend Storybook Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src/Website
|
||||||
|
npm install
|
||||||
|
npm run test:storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
**Purpose**:
|
||||||
|
|
||||||
|
- Verifies shared stories such as form fields, submit buttons, navbar states, toasts, and the theme gallery
|
||||||
|
- Runs in browser mode via Vitest and Storybook integration
|
||||||
|
|
||||||
|
### Frontend Playwright Storybook Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src/Website
|
||||||
|
npm install
|
||||||
|
npm run test:storybook:playwright
|
||||||
|
```
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
|
||||||
|
- Storybook dependencies installed
|
||||||
|
- Playwright browser dependencies installed
|
||||||
|
- The command will start or reuse the Storybook server defined in `playwright.storybook.config.ts`
|
||||||
|
|
||||||
## Test Coverage
|
## Test Coverage
|
||||||
|
|
||||||
### Current Coverage
|
### Current Coverage
|
||||||
@@ -112,6 +141,14 @@ dotnet test Service/Service.Auth.Tests/Service.Auth.Tests.csproj
|
|||||||
- Register service with validation
|
- Register service with validation
|
||||||
- Business logic for authentication flow
|
- Business logic for authentication flow
|
||||||
|
|
||||||
|
**Frontend UI Coverage**:
|
||||||
|
|
||||||
|
- Shared submit button states
|
||||||
|
- Form field happy path and error presentation
|
||||||
|
- Navbar guest, authenticated, and mobile behavior
|
||||||
|
- Theme gallery rendering across Biergarten themes
|
||||||
|
- Toast interactions and themed notification display
|
||||||
|
|
||||||
### Planned Coverage
|
### Planned Coverage
|
||||||
|
|
||||||
- [ ] Email verification workflow
|
- [ ] Email verification workflow
|
||||||
@@ -121,6 +158,7 @@ dotnet test Service/Service.Auth.Tests/Service.Auth.Tests.csproj
|
|||||||
- [ ] Beer post operations
|
- [ ] Beer post operations
|
||||||
- [ ] User follow/unfollow
|
- [ ] User follow/unfollow
|
||||||
- [ ] Image upload service
|
- [ ] Image upload service
|
||||||
|
- [ ] Frontend route integration coverage beyond Storybook stories
|
||||||
|
|
||||||
## Testing Frameworks & Tools
|
## Testing Frameworks & Tools
|
||||||
|
|
||||||
@@ -254,6 +292,15 @@ Exit codes:
|
|||||||
- `0` - All tests passed
|
- `0` - All tests passed
|
||||||
- Non-zero - Test failures occurred
|
- Non-zero - Test failures occurred
|
||||||
|
|
||||||
|
Frontend UI checks should also be included in CI for the active website workspace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src/Website
|
||||||
|
npm ci
|
||||||
|
npm run test:storybook
|
||||||
|
npm run test:storybook:playwright
|
||||||
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Tests Failing Due to Database Connection
|
### Tests Failing Due to Database Connection
|
||||||
|
|||||||
10881
src/Website-v1/package-lock.json
generated
Normal file
98
src/Website-v1/package.json
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
{
|
||||||
|
"name": "biergarten",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"prestart": "npm run build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"clear-db": "npx ts-node ./src/prisma/seed/clear/index.ts",
|
||||||
|
"format": "npx prettier . --write; npx prisma format;",
|
||||||
|
"format-watch": "npx onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
|
||||||
|
"seed": "npx --max-old-space-size=4096 ts-node ./src/prisma/seed/index.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@hapi/iron": "^7.0.1",
|
||||||
|
"@headlessui/react": "^1.7.15",
|
||||||
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
|
"@hookform/resolvers": "^3.3.1",
|
||||||
|
"@mapbox/mapbox-sdk": "^0.15.2",
|
||||||
|
"@mapbox/search-js-core": "^1.0.0-beta.17",
|
||||||
|
"@mapbox/search-js-react": "^1.0.0-beta.17",
|
||||||
|
"@next/bundle-analyzer": "^14.0.3",
|
||||||
|
"@prisma/client": "^5.7.0",
|
||||||
|
"@react-email/components": "^0.0.11",
|
||||||
|
"@react-email/render": "^0.0.9",
|
||||||
|
"@react-email/tailwind": "^0.0.12",
|
||||||
|
"@vercel/analytics": "^1.1.0",
|
||||||
|
"argon2": "^0.31.1",
|
||||||
|
"classnames": "^2.5.1",
|
||||||
|
"cloudinary": "^1.41.0",
|
||||||
|
"cookie": "^0.7.0",
|
||||||
|
"date-fns": "^2.30.0",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"jsonwebtoken": "^9.0.1",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"mapbox-gl": "^3.4.0",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
|
"next": "^14.2.22",
|
||||||
|
"next-cloudinary": "^5.10.0",
|
||||||
|
"next-connect": "^1.0.0-next.3",
|
||||||
|
"passport": "^0.6.0",
|
||||||
|
"passport-local": "^1.0.0",
|
||||||
|
"pino": "^10.0.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-daisyui": "^5.0.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-email": "^1.9.5",
|
||||||
|
"react-hook-form": "^7.45.2",
|
||||||
|
"react-hot-toast": "^2.4.1",
|
||||||
|
"react-icons": "^4.10.1",
|
||||||
|
"react-intersection-observer": "^9.5.2",
|
||||||
|
"react-map-gl": "^7.1.7",
|
||||||
|
"react-responsive-carousel": "^3.2.23",
|
||||||
|
"swr": "^2.2.0",
|
||||||
|
"theme-change": "^2.5.0",
|
||||||
|
"zod": "^3.21.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@faker-js/faker": "^8.3.1",
|
||||||
|
"@types/cookie": "^0.5.1",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.2",
|
||||||
|
"@types/lodash": "^4.14.195",
|
||||||
|
"@types/mapbox__mapbox-sdk": "^0.13.4",
|
||||||
|
"@types/multer": "^1.4.7",
|
||||||
|
"@types/node": "^20.4.2",
|
||||||
|
"@types/passport-local": "^1.0.35",
|
||||||
|
"@types/react": "^18.2.15",
|
||||||
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"@vercel/fetch": "^7.0.0",
|
||||||
|
"autoprefixer": "^10.4.14",
|
||||||
|
"daisyui": "^4.7.2",
|
||||||
|
"dotenv-cli": "^7.2.1",
|
||||||
|
"eslint": "^8.51.0",
|
||||||
|
"eslint-config-airbnb-base": "15.0.0",
|
||||||
|
"eslint-config-airbnb-typescript": "17.1.0",
|
||||||
|
"eslint-config-next": "^13.5.4",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-react": "^7.33.2",
|
||||||
|
"generate-password": "^1.7.1",
|
||||||
|
"onchange": "^7.1.0",
|
||||||
|
"postcss": "^8.4.26",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"prettier-plugin-jsdoc": "^1.0.2",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.5.7",
|
||||||
|
"prisma": "^5.7.0",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
|
"tailwindcss-animated": "^1.0.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.3.2"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"schema": "./src/prisma/schema.prisma",
|
||||||
|
"seed": "npm run seed"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/Website-v1/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 515 B |
|
Before Width: | Height: | Size: 961 B After Width: | Height: | Size: 961 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |