A full-stack application for managing corporate calendar activities, built with NestJS (backend) and React (frontend) in a monorepo structure.
This application provides a comprehensive system for managing calendar activities, including event scheduling, approvals, communications, and reporting. The system supports multiple organizations, government representatives, and various activity types with rich metadata and workflow management.
This is a monorepo workspace containing:
- calendar-service: NestJS backend API service
- calendar-ui: React frontend application (Vite)
- packages/database: Drizzle ORM schemas and database client
- packages/shared: Shared types, schemas, DTOs, and utilities
The workspace uses npm workspaces to manage dependencies across packages. Internal packages (@corpcal/database and @corpcal/shared) are referenced as workspace dependencies.
- Node.js: >= 24.0.0
- npm: >= 11.0.0
- PostgreSQL: Database server (version 12+)
- Docker (optional): For containerized development
From the project root:
npm installThis installs dependencies for all workspaces (root, calendar-service, calendar-ui, and packages).
Create a .env file in the project root (copy from .env.example if available) and set:
DATABASE_URL- PostgreSQL connection string
Ensure PostgreSQL is running and DATABASE_URL is configured in your .env file:
# Format: postgresql://user:password@host:port/database
DATABASE_URL="postgresql://postgres:password@localhost:5432/corpcal"Initial Setup (fresh database):
# Apply the schema to your database
npm run db:push --workspace=packages/database
# Seed lookup tables and sample data
npm run seed --workspace=calendar-serviceAlternative (manual SQL execution):
If you prefer to run SQL manually, the migration and seed files are located at:
- Schema:
packages/database/migrations/*.sql - Seed data:
packages/database/seeds/*.sql
See Database Package Documentation for detailed setup and schema change workflows.
npm startThis runs:
- Backend API at
http://localhost:3001 - Frontend UI at
http://localhost:3000
Run services individually:
npm run start:dev --workspace=calendar-service # Backend only
npm run dev --workspace=calendar-ui # Frontend only| Variable | Description | Required | Default |
|---|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Yes | - |
API_KEY |
API authentication key (optional in dev) | No | - |
PORT |
Backend service port | No | 3001 |
VITE_API_BASE_URL |
Frontend API base URL | No | http://localhost:3001 |
DB_MAX_CONNECTIONS |
Database connection pool size | No | 10 |
DB_IDLE_TIMEOUT |
Database idle timeout (seconds) | No | 20 |
DB_CONNECT_TIMEOUT |
Database connection timeout (seconds) | No | 10 |
AUTH_STRATEGY |
Authentication strategy: mock, ad, or azure |
No | mock |
AZURE_TENANT_ID |
Azure AD tenant ID (required when AUTH_STRATEGY=azure) |
No | - |
AZURE_CLIENT_ID |
Azure AD application client ID (required when AUTH_STRATEGY=azure) |
No | - |
AZURE_CLIENT_SECRET |
Azure AD application client secret (required when AUTH_STRATEGY=azure) |
No | - |
AZURE_REDIRECT_URI |
Optional explicit callback URL override for Azure OIDC | No | auto-derived |
JWT_SECRET |
Secret key for JWT signing (required in production) | No | dev-secret |
JWT_EXPIRES_IN |
JWT token expiration in seconds | No | 3600 |
Authentication: The API uses JWT-based authentication. In development, use AUTH_STRATEGY=mock to authenticate with any seeded username. Azure sign-in is available at /auth/azure (or /api/auth/azure from the UI) when Azure environment variables are configured. See AUTH_AND_RBAC.md for details.
bcs-marzipan/
├── calendar-service/ # NestJS backend API
│ ├── src/
│ │ ├── activities/ # Activities module (CRUD operations)
│ │ ├── auth/ # Authentication module (JWT, login/logout)
│ │ │ ├── decorators/ # @CurrentUser, @Public decorators
│ │ │ ├── guards/ # JwtAuthGuard
│ │ │ ├── strategies/ # Mock and AD auth strategies
│ │ │ └── dto/ # Login and auth response DTOs
│ │ ├── policy/ # Authorization/RBAC module
│ │ │ ├── decorators/ # @RequirePermission, @RequireRole
│ │ │ ├── guards/ # PermissionsGuard, RolesGuard
│ │ │ └── interceptors/ # DataScopeInterceptor
│ │ ├── drafts/ # Form drafts module
│ │ ├── reports/ # Reports module
│ │ ├── lookups/ # Lookup data endpoints
│ │ ├── database/ # Database module (Drizzle integration)
│ │ ├── commands/ # CLI commands (seed, etc.)
│ │ └── common/ # Shared utilities, pipes, interceptors
│ └── package.json
├── calendar-ui/ # React frontend (Vite)
│ ├── src/
│ │ ├── api/ # API client functions
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── hooks/ # Custom React hooks
│ │ └── schemas/ # Form validation schemas
│ └── package.json
├── packages/
│ ├── database/ # Database package
│ │ ├── src/
│ │ │ ├── schema/ # Drizzle ORM schema definitions
│ │ │ │ ├── rbac.ts # Roles, permissions, role_permissions
│ │ │ │ ├── sessions.ts # Session management
│ │ │ │ └── user.ts # Users with roleId FK
│ │ │ └── client.ts # Database client setup
│ │ ├── migrations/ # Database migration files
│ │ └── seeds/ # Seed data (users, roles, permissions)
│ └── shared/ # Shared package
│ ├── src/
│ │ ├── auth/ # Auth types, constants, schemas
│ │ ├── schemas/ # Zod validation schemas
│ │ ├── api/ # API type definitions
│ │ └── utils/ # Utility functions
│ └── package.json
├── docs/ # Additional documentation
│ ├── AUTH_AND_RBAC.md # Authentication and RBAC documentation
│ ├── ERROR_HANDLING.md # Error handling (backend, frontend, database)
│ ├── TESTING.md # Testing strategy and standards
│ ├── SCHEMA_README.md # Schema and type safety documentation
│ ├── DOCKER_DEPLOYMENT.md # Docker deployment guide
│ └── PRE_COMMIT_HOOKS.md # Git hooks documentation
└── package.json # Root workspace configuration
npm run build # Build all services and packages
npm run build:packages # Build packages onlynpm run typecheck # Check all workspaces
npm run typecheck:packages # Check packages onlynpm run db:generate --workspace=packages/database -- <name> # Generate migration (requires name)
npm run db:push --workspace=packages/database # Apply schema directly (dev)
npm run db:studio --workspace=packages/database # Open Drizzle Studio
npm run seed --workspace=calendar-service # Seed lookup tablesSee Database Package Documentation for the complete schema change workflow.
npm run test # Run all unit tests (calendar-service, calendar-ui, packages/shared)See Testing Documentation for strategy, naming conventions (*.spec.ts / *.spec.tsx), what to test, and when tests run (pre-commit, pre-push).
The API includes Swagger/OpenAPI documentation. When the backend is running, access the interactive API documentation at:
http://localhost:3001/api
The API provides endpoints for:
- Auth: Login, logout, current user (
/auth/login,/auth/me,/auth/logout) - Activities: CRUD operations for calendar activities
- Drafts: Form draft save/restore functionality
- Reports: Report configuration and listing
- Lookups: Reference data (categories, organizations, users, tags, etc.)
- Health: Health check and readiness probes
Database package containing Drizzle ORM schemas and database client.
import { db } from '@corpcal/database';
import { activities } from '@corpcal/database/schema';See packages/database/README.md for details.
Shared package containing types, schemas, and utilities.
import type { ActivityResponse } from '@corpcal/shared/api/types';
import { createActivityRequestSchema } from '@corpcal/shared/schemas';- API DTOs and Swagger: How DTOs, Zod schemas, and Swagger are implemented for the API; use this when adding or changing endpoints
- Authentication and RBAC: JWT authentication, roles, permissions, and authorization
- Error Handling: How errors are handled (backend, frontend, database), global handling, and how to add or extend error handling
- Testing: Testing strategy, standards, naming conventions (
*.spec.ts/*.spec.tsx), and what to test - Schema Documentation: Detailed information about schema flow, type safety, and how to update schemas
- Schema Mapping: Legacy to new schema field mappings
- Docker Deployment: Guide for Docker and docker-compose usage
- Database Module: Database module usage in NestJS services
- Database Package: Database package setup and usage
npm run build:packages # Rebuild packagesrm -rf node_modules package-lock.json
rm -rf calendar-service/node_modules calendar-ui/node_modules
rm -rf packages/*/node_modules
npm cache clean --force
npm install- Build packages:
npm run build:packages - Run type checking:
npm run typecheck - Validate types:
npm run validate-types --workspace=packages/shared
# Format all code
npm run format
# Check formatting
npm run format:check
# Lint and auto-fix
npm run lint
# Check linting
npm run lintThis project uses Husky to enforce code quality. See Pre-Commit Hooks Documentation for details.
Pre-commit hook (blocking):
- Runs ESLint with auto-fix on staged files
- Runs Prettier on non-code files
- Runs tests for affected files
Pre-push hook (blocking):
- Validates full project build
- Runs all test suites
- Validates schema types are in sync
- Validates branch naming convention
Commit-msg hook (non-blocking):
- Validates commit message format (Conventional Commits)
Follow Conventional Commits: <type>(<scope>): <subject>
- type:
feat,fix,docs,style,refactor,test,build,chore - scope: Optional (e.g.,
activities,database) - subject: Short description (max 100 characters)
Examples: feat(activities): add filtering, fix(database): resolve connection issue
Use npm run commit for an interactive prompt.
Format: <type>/CORPCAL-<number>-<short-description>
- type:
feat,fix,docs,style,refactor,test,build,chore - Jira key:
CORPCAL-<number>(uppercase) - description: Lowercase, hyphens only
Example: feat/CORPCAL-123-add-user-authentication
Protected branches (main, master, develop) skip validation.
For detailed hook documentation see Pre-Commit Hooks Documentation.