Issue-1 completed. CICD not completely functional yet, so passing thing and merging despite the error in the nox step.
Online Booking Application
Cliff Hill's Coding Project
This is a full-stack application simulating an online booking system for conference rooms.
This can be run with a simple docker compose up command.
Note: For the application to completely work, you must copy the .env.example file to .env in the project root. Otherwise, the the application will fail to build.
Project Architecture Overview
Monorepo Structure
- The project is organized as a monorepo with two main subprojects:
- backend/: Python FastAPI application for API and business logic.
- frontend/: React + TypeScript application for the user interface.
- Shared configuration and orchestration files (Docker, Compose, Nox, etc.) are at the root.
Backend Architecture (FastAPI, SQLAlchemy, Pydantic)
- Entry Point:
backend/src/backend/main.pyinitializes the FastAPI app, configures CORS, and includes routers for users, rooms, and bookings. - Routers: Each resource (
users,rooms,bookings) has its own router, service, and schema module, following a clear separation of concerns. - Models: SQLAlchemy ORM models (
models.py) defineUser,Room,Booking, andInviteewith relationships and constraints. - Schemas: Pydantic models for request/response validation, separated for create/update/response.
- Service Layer: Business logic is abstracted into service modules, keeping routers thin and focused on HTTP.
- Database: Uses async SQLAlchemy with PostgreSQL, migrations managed via Alembic.
- Logging: Centralized logging setup for analytics and debugging.
- Testing: Pytest-based suite, with coverage, type checks (mypy), and pre-commit hooks for code quality.
- Configuration: Environment variables managed via
.envfiles and Docker Compose.
Frontend Architecture (React, TypeScript, MUI)
- Entry Point:
frontend/src/App.tsxsets up React Router and wraps the app in context providers for rooms, users, and bookings. - State Management: Uses React Context for global state (rooms, bookings, users), with real-time updates via SSE or polling.
- Component Design: Modular, reusable components (e.g.,
BookingForm,RoomList,CalendarView) with strong typing and JSDoc. - UI Library: Material-UI (MUI) for consistent, accessible, and responsive design.
- API Layer: API calls abstracted into helper modules.
- Testing: Jest and React Testing Library, with Storybook for UI component development.
- Styling: CSS modules and theming, with color logic based on room IDs for visual consistency.
- Error Handling: Robust validation and user-friendly error messages throughout forms and UI.
Orchestration & DevOps
- Docker: Multi-stage Dockerfiles for backend and frontend, optimized for production and development.
- Docker Compose: Orchestrates backend, frontend, and Postgres services, with healthchecks and persistent volumes.
- Nox: Unified automation for testing, linting, and building docs in both frontend and backend.
- CI/CD Ready: Structure and scripts are ready for integration into a CI/CD pipeline.
Key Design Decisions (Summary)
- Separation of Concerns: Clear boundaries between API, business logic, data models, and UI.
- Type Safety: TypeScript (frontend) and Pydantic (backend) for robust data validation.
- Modularity: Reusable components and service abstractions for maintainability and extensibility.
- Real-Time UX: Server-Sent Events (SSE) for live updates in the frontend.
- Accessibility & UX: Focus on error states, skeleton loaders, and accessible UI elements.
- Centralized Logging: Consistent logging across both backend and frontend.
- Testing & Quality: Comprehensive test suites, code coverage, and pre-commit hooks.
- Dev Experience: Automated setup, scripts, and documentation for easy onboarding and development.
In summary: The project is a modern, full-stack web application with a strong emphasis on modularity, type safety, real-time features, and developer experience. The architecture is clean and scalable, with best practices applied throughout both backend and frontend.
AI Assistance in Development
Tools Used
- GitHub Copilot: Provided code suggestions, boilerplate, and documentation directly in VS Code.
- CodeGPT (VSCode extension): Helped with generating docstrings, logging messages, and code refactoring.
- General LLMs (e.g., ChatGPT): Used for answering coding questions, debugging, and rapid prototyping, especially for frontend work.
How AI Was Utilized
- Scaffolding and Boilerplate: AI was used to quickly generate Dockerfiles, Docker Compose files, and initial test stubs for backend and frontend.
- Documentation: AI generated or improved docstrings, JSDoc comments, and some README content.
- Rapid Prototyping: AI helped set up the structure for React components, backend routers, services, and schemas.
- Refactoring and Debugging: AI suggested code improvements and helped debug failing tests.
- Frontend Support: AI was especially helpful for CSS, UI structure, and React code, where the developer had less experience.
AI-Generated or AI-Assisted Parts of the Repo
- Dockerfiles:
Dockerfile-backend,Dockerfile-frontend - Compose Files:
compose.yml,compose.dev.yml - Test Stubs: Initial tests for routers, services, and React components
- Frontend Components: Structure, documentation, and some logic in files like
BookingForm.tsx,RoomList.tsx, andCalendarView.tsx - Backend Routers/Services/Schemas: Initial structure, docstrings, and some logic in files like
users.py,rooms.py, andbookings.py - Documentation: Parts of
README.mdand code comments throughout the repo - CSS and Theming: AI helped organize and clean up frontend styles
Human Oversight
- All AI-generated code was reviewed, corrected, and adapted by the developer. No critical business logic was left to AI alone.
Documentation & Storybook
Backend API Documentation
To build and view the backend API documentation:
- Navigate to the backend directory:
cd backend
- Run the Nox docs session (live-reloading server):
nox -s docs
This will build and serve the docs with live reloading. Your browser should open automatically to the docs.
Alternative (static build):
If you want to build the static HTML docs only:
cd backend
nox -s docs-build
xdg-open docs/_build/index.html # Linux
open docs/_build/index.html # macOS
start docs/_build/index.html # Windows
Or manually open docs/_build/index.html in your browser.
OpenAPI docs
These are available when the application is running. They are found at: http://localhost:8000/docs
Frontend Storybook
To run Storybook for the frontend using Nox:
- Navigate to the frontend directory:
cd frontend
- Run the Nox storybook session:
nox -s storybook
This will start Storybook and open your browser.
Alternative (static build):
If you want to build the static Storybook docs only:
cd frontend
nox -s storybook-build
xdg-open storybook-static/index.html # Linux
open storybook-static/index.html # macOS
start storybook-static/index.html # Windows
Or manually open storybook-static/index.html in your browser.
Development Environment Setup
Local Development Setup & Running with Docker
1. Clone the Repository
git clone https://github.com/xlorepdarkhelm/numinar-coding-project.git
cd numinar-coding-project
2. Copy Environment Variables
cp .env.example .env
# Or, if present:
cp .env.sample .env
Edit .env as needed for your local environment (ports, DB credentials, etc).
3. Install Dependencies (Optional for advanced dev)
-
Backend:
cd backend poetry install pre-commit install -
Frontend:
cd ../frontend yarn installNote: For most users, you can skip manual dependency installation and just use Docker Compose for a full-stack local environment.
4. Start All Services with Docker Compose
From the project root:
docker compose -f compose.dev.yml up
- Backend: FastAPI (default port 8000, hot-reload)
- Frontend: React (default port 3000, hot-reload)
- Database: Postgres (default port 5432)
All services are networked together and use volumes for persistent data.
5. Access the Application
- Frontend: http://localhost:3000
- Backend API/docs: http://localhost:8000/docs
6. Run Tests
-
Backend:
cd backend nox # Run all tests, lint, and docs # or just unit tests: nox --session=tests -
Frontend:
cd frontend nox # Run all frontend tests and checks # or just Jest tests: nox --session=jest -
All tests from root:
nox
7. Stopping and Cleaning Up
-
To stop all services:
docker compose -f compose.dev.yml down -
To remove volumes (DB data):
docker compose -f compose.dev.yml down -v
Additional Guidelines
- Pre-commit hooks:
Run
pre-commit installinbackendto enable auto-formatting and linting on commit. - Docs & Storybook:
See README for
nox -s docs(backend API docs) andnox -s storybook(frontend UI docs). - Troubleshooting:
If you hit dependency or environment issues, delete
.venvornode_modulesand reinstall.
Summary:
- Use Docker Compose for a seamless local dev environment.
- Use Nox for running tests and code quality checks.
- All config and orchestration is at the project root for easy onboarding.
Security Concerns
Backend (Python/FastAPI)
- No Passwords or Authentication
- The
Usermodel and API do not include password fields or authentication logic. Anyone can potentially access user data or perform actions if the API is public.
- Open CORS Policy
- The backend allows all methods and headers from multiple origins, including localhost and Docker Compose service names. In production, this should be restricted to trusted domains only.
- Sensitive Data in Environment
- Default values for
DATABASE_PASSWORDand other secrets are hardcoded as"password"inenv.py. These should be set securely in production and never committed with real values.
- No CSRF Protection
- There is no mention of CSRF protection for state-changing endpoints. If the frontend and backend are on different domains, this could be a risk.
- No Rate Limiting or Brute Force Protection
- There is no evidence of rate limiting or brute force protection on any endpoints.
- No HTTPS Enforcement
- The backend defaults to
httpfor both frontend and backend protocols. In production, HTTPS should be enforced.
- No Input Validation for Dangerous Types
- While Pydantic is used for schemas, there is no evidence of additional validation or sanitization for fields that could be used in injection attacks (e.g., SQL, command, or path injection).
- Verbose Logging
- Logging user actions and errors is good, but care must be taken not to log sensitive data (such as emails or internal errors) in production logs.
Frontend (React/TypeScript)
- No Authentication or Session Handling
- There is no evidence of authentication tokens, session management, or secure storage of sensitive data in the frontend.
- Open API URLs
- The API URL is configurable via environment variables, but there is no mention of secure token handling or CORS restrictions.
- No XSS or Input Sanitization
- There is no evidence of input sanitization for user-provided data before rendering in the UI.
- No Secure Storage
- There is no mention of secure storage for any sensitive data (e.g., tokens, user info).
General
-
No Mention of Security Headers
- There is no mention of setting HTTP security headers (e.g., Content-Security-Policy, X-Frame-Options, etc.).
-
No Mention of Dependency Scanning
- There is no mention of automated dependency vulnerability scanning.
Summary: The project currently lacks authentication, authorization, and secure handling of sensitive data. CORS is open, and there is no CSRF, rate limiting, or HTTPS enforcement. These are critical for any production deployment.
Troubleshooting & FAQ
Q: Why does isort or black change files differently in Nox vs pre-commit?
A: Make sure both Nox and pre-commit are using the same pinned tool versions and config files. See .isort.cfg and .pre-commit-config.yaml for details.
Q: Why does Storybook open the browser or not exit when run in CI/Nox?
A: Use yarn build-storybook for static builds (exits automatically). For dev server, use yarn storybook dev --ci to prevent browser opening.
Q: Why do pre-commit hooks modify files after a commit or behave differently in CI?
A: Pre-commit runs in its own environment. Always run pre-commit run --all-files locally to reproduce CI behavior. Ensure your config files are up to date and tool versions are pinned.
Q: How do I run only frontend or backend tests?
A: Use Nox in the respective directory (cd frontend && nox, cd backend && nox).
Q: How do I fix environment or dependency issues?
A: Delete .venv or node_modules and reinstall dependencies (poetry install for backend, yarn install for frontend). Check for version mismatches in config files.
Q: Where are config files for formatting and type checking?
A: See .isort.cfg, .coveragerc, and mypy.ini in the project root. These are derived from backend settings for consistency.
Q: Docker Compose fails to start or containers exit immediately.
A: Check that your .env file is present and correctly configured. Make sure required ports (3000, 8000, 5432) are not in use. Run docker compose logs for more details.
Q: Database migrations are not applied or backend fails with DB errors.
A: Ensure the Postgres container is healthy and running. You may need to run migrations manually with alembic upgrade head inside the backend container.
Q: Frontend changes are not reflected in the browser. A: Make sure the frontend container is running in development mode (hot-reload enabled). Try rebuilding the frontend container or clearing your browser cache.
Q: Backend API changes are not picked up. A: The backend should auto-reload in development. If not, restart the backend container or check for syntax errors in your code.
Q: How do I reset the database to a clean state?
A: Stop all containers, then run docker compose -f compose.dev.yml down -v to remove volumes and start fresh.
Q: How do I add new environment variables?
A: Add them to your .env file and ensure they are referenced in the relevant Docker Compose and application config files. Rebuild containers if necessary.
Q: Nox or pre-commit fails due to missing Python or Node dependencies.
A: Ensure you have the correct Python and Node versions installed. Reinstall dependencies with poetry install (backend) or yarn install (frontend).
Q: How do I debug a failing test?
A: Run the test suite with verbose output (nox -- -v), or run individual tests using pytest or jest directly for more detailed error messages.
Diagrams
Docker Compose Components
%% Docker Compose Architecture (with hot-reload)
graph TD
subgraph app-network
FE[Frontend<br/>Port: 3000<br/>.env, hot-reload]
BE[Backend<br/>Port: 8000<br/>.env, hot-reload]
DB[(PostgreSQL<br/>Port: 5432<br/>Persistent Volume<br/>Healthcheck)]
BE -- "SQL: 5432" --> DB
end
Client[Browser/Client] -- "HTTP: 3000" --> FE
FE -- "REST API: 8000" --> BE
note1[.env files for config] -.-> FE
note1 -.-> BE
note2[Volume for DB data] -.-> DB
note3[Hot-reload enabled in dev mode] -.-> FE
note3 -.-> BE
Database Schema Diagram
%% Database Schema with Constraints and Notes
classDiagram
class User {
string email [PK]
string name
-- Relationships --
Invitee[*] invitees
}
class Room {
int id [PK]
string name [unique]
string location
string equipment
int capacity
-- Relationships --
Booking[*] bookings
}
class Booking {
int id [PK]
int room_id [FK]
datetime start_time
datetime end_time
string title [nullable]
-- Relationships --
Invitee[*] invitees
}
class Invitee {
int id [PK]
int booking_id [FK, ON DELETE CASCADE]
string user_email [FK, ON DELETE CASCADE]
-- Constraints --
unique(booking_id, user_email)
}
User "1" <|-- "*" Invitee : user_email [FK]
Room "1" <|-- "*" Booking : room_id [FK]
Booking "1" <|-- "*" Invitee : booking_id [FK]
Component Diagram
%% Component Relationships and Data Flow
graph TD
subgraph Frontend
F1[Pages]
F2[Components]
F3[API Helpers]
F4[Context Providers]
F1 --> F2
F2 --> F4
F4 --> F3
end
subgraph Backend
B1[FastAPI Routers]
B2[Pydantic Schemas]
B3[Service Layer]
B4[SQLAlchemy Models]
B5[PostgreSQL]
B6[Alembic Migrations]
B1 --> B2
B1 --> B3
B3 --> B4
B4 --> B5
B6 -.->|"Schema Management"| B5
end
F3 -- REST --> B1
B5 -.->|External| PG[PostgreSQL Service]
Backend Request Data Path
%% Backend Request Data Path (no auth, but placeholder shown)
sequenceDiagram
participant Frontend
participant FastAPI_Router as FastAPI Router
participant Dependency_Injector as Dependency Injector
participant API_Endpoint as API Endpoint
participant Pydantic_Schema as Pydantic Schema
participant Service_Layer as Service Layer
participant DB_Model as DB Model
participant Database
participant Logger as Logger
%% Auth is not currently set up, but shown for future extension
participant Auth as Auth (not enabled)
Frontend->>FastAPI_Router: HTTP Request (REST)
FastAPI_Router->>Dependency_Injector: Resolve Dependencies (DB, Service)
Dependency_Injector-->>API_Endpoint: Injected Dependencies
%% Auth would go here if enabled
API_Endpoint->>Auth: (Auth check placeholder)
note right of Auth: Auth is not currently set up
API_Endpoint->>Pydantic_Schema: Validate & Parse Input
alt Validation Error
Pydantic_Schema-->>Frontend: HTTP 422 Unprocessable Entity
else Validated
Pydantic_Schema-->>API_Endpoint: Validated Data
API_Endpoint->>Logger: Log Request
API_Endpoint->>Service_Layer: Pass Data
Service_Layer->>DB_Model: Business Logic
DB_Model->>Database: DB Query/Update
Database-->>DB_Model: Query Result
DB_Model-->>Service_Layer: Data
Service_Layer-->>API_Endpoint: Response Data
API_Endpoint->>Pydantic_Schema: Serialize Response
API_Endpoint->>Logger: Log Response
API_Endpoint-->>Frontend: HTTP Response (JSON)
end
alt Not Found/Error
API_Endpoint-->>Frontend: HTTP 404/500 Error
end
SSE Update Flow
%% SSE Update Flow with Triggers and Error Handling
sequenceDiagram
participant Frontend as Frontend (Client)
participant SSE_Endpoint as FastAPI SSE Endpoint
participant Event_Generator as Event Generator
participant Publisher as Publisher (Booking/Room Service)
participant DB as Database
Frontend->>SSE_Endpoint: Open EventSource /availability/stream
SSE_Endpoint->>Event_Generator: Register Subscriber
loop While Connected
Publisher->>DB: Booking/Room Create/Update/Delete
DB-->>Publisher: DB Change
Publisher-->>Event_Generator: Trigger Event (type: "availability")
Event_Generator-->>SSE_Endpoint: Send SSE Event (data: {type: "availability"})
SSE_Endpoint-->>Frontend: Push SSE Event
Note over Publisher,Frontend: Trigger: Booking created/updated/deleted
alt No Event (timeout)
Event_Generator-->>SSE_Endpoint: Send SSE Event (data: {type: "keep-alive"})
SSE_Endpoint-->>Frontend: Push SSE Event
end
alt Connection Error/Drop
Frontend-->>SSE_Endpoint: Disconnect (close EventSource)
SSE_Endpoint-->>Event_Generator: Cleanup Subscriber
end
end