A modern, secure project and task management system built with Next.js, featuring role-based access control, comprehensive activity logging, and enterprise-grade security features.
- Project Management: Create, organize, and manage projects with descriptions and status tracking (ACTIVE, ARCHIVED)
- Task Management: Create tasks, assign them to team members, track status (TODO, IN_PROGRESS, DONE), and set due dates
- User Management: Role-based access control (USER, ADMIN) with secure invite system
- Activity Logging: Comprehensive audit trail of all user actions with metadata tracking
- Dashboard: Real-time statistics and activity overview for users and admins
- Admin Panel: Complete user management, invite system, and activity monitoring
- Enterprise Security:
- Nonce-based Content Security Policy (CSP)
- Rate limiting on all API endpoints
- Error sanitization to prevent information leakage
- Security headers (HSTS, X-Frame-Options, CSP, etc.)
- Security scanner support (OWASP ZAP compatible)
- Secure session management with NextAuth
- Health Monitoring: Health check endpoint for monitoring systems and load balancers
- SEO: Automatic sitemap generation and robots.txt configuration
- Dark Mode: System-aware theme support
- Docker Support: Production-ready Docker images with multi-stage builds
- Framework: Next.js 14.2 (App Router) with standalone output
- Language: TypeScript (strict mode)
- Database: PostgreSQL 16 with Prisma ORM 5.x
- Authentication: NextAuth.js v4 with JWT sessions
- Styling: Tailwind CSS with Radix UI components
- Validation: Zod for runtime type validation
- Testing: Jest with React Testing Library
- Containerization: Docker with multi-stage builds
- Deployment: Docker Compose for production orchestration
- Node.js: 18+ (20+ recommended)
- npm: 9+ or compatible package manager
- PostgreSQL: 16+ database server
- Docker: 20+ (optional, for containerized deployment)
- Docker Compose: 2+ (optional, for local development with Docker)
git clone <repository-url>
cd sentineldesknpm installCreate a .env file in the root directory based on .env.example:
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/sentineldesk"
# NextAuth
NEXTAUTH_SECRET="your-secret-key-at-least-32-characters-long"
NEXTAUTH_URL="http://localhost:3000" # Required in production
# Node Environment
NODE_ENV="development"
# Optional: Security Scanner Configuration (for OWASP ZAP, etc.)
SCAN_TOKEN="optional-token-for-security-scanners-min-32-chars"
SCAN_IP_WHITELIST="optional-comma-separated-ip-addresses"
# Optional: Logging and SEO
LOG_LEVEL="info" # debug, info, warn, error
NEXT_PUBLIC_BASE_URL="http://localhost:3000" # For sitemap generationImportant:
NEXTAUTH_SECRETmust be at least 32 characters longNEXTAUTH_URLis required in production environments- Generate a secure
NEXTAUTH_SECRETusing:openssl rand -base64 32 - Environment variables are validated at startup with helpful error messages
# Generate Prisma Client
npm run db:generate
# Run migrations
npm run db:migrate
# (Optional) Seed the database with sample data
npm run db:seednpm run devOr use the provided script:
./run.shThe application will be available at http://localhost:3000
npm run dev- Start development servernpm run build- Build for productionnpm start- Start production servernpm run lint- Run ESLintnpm test- Run testsnpm run test:watch- Run tests in watch modenpm run db:generate- Generate Prisma Clientnpm run db:push- Push schema changes to database (dev only)npm run db:migrate- Run database migrationsnpm run db:studio- Open Prisma Studionpm run db:seed- Seed the databasenpm run clean:whitespace- Clean whitespace in files (utility script)
The project includes a convenient run.sh script for managing the development/production server:
# Start development server
./run.sh
# Start production server (builds if needed)
./run.sh --prod
# Stop running server
./run.sh --kill
# Clear all caches
./run.sh --clear-cache
# Combine options
./run.sh --prod --clear-cachesentineldesk/
├── app/ # Next.js App Router pages and API routes
│ ├── api/ # API endpoints
│ │ ├── health/ # Health check endpoint
│ │ ├── auth/ # NextAuth authentication
│ │ ├── dashboard/ # Dashboard statistics
│ │ ├── projects/ # Project CRUD operations
│ │ ├── tasks/ # Task CRUD operations
│ │ ├── users/ # User management
│ │ ├── admin/ # Admin-only endpoints
│ │ ├── activity-logs/ # Activity log endpoints
│ │ └── __tests__/ # API route tests
│ ├── admin/ # Admin pages (protected)
│ │ ├── activity/ # Activity log viewer
│ │ ├── invites/ # Invite management
│ │ ├── users/ # User management
│ │ └── page.tsx # Admin dashboard
│ ├── projects/ # Project pages
│ │ ├── [id]/ # Project detail pages
│ │ ├── new/ # Create project
│ │ └── page.tsx # Projects list
│ ├── login/ # Authentication pages
│ ├── register/
│ ├── forgot-password/
│ ├── reset-password/
│ ├── activity/ # Activity log page
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Homepage/dashboard
│ └── sitemap.ts # Sitemap generation
├── components/ # React components
│ ├── ui/ # Reusable UI components (Radix UI)
│ │ ├── toast.tsx
│ │ ├── skeleton.tsx
│ │ └── ...
│ ├── navigation.tsx # Navigation component
│ ├── sidebar.tsx # Sidebar component
│ ├── breadcrumbs.tsx # Breadcrumb navigation
│ └── ...
├── lib/ # Utility functions and configurations
│ ├── auth.config.ts # NextAuth configuration
│ ├── auth-utils.ts # Authentication utilities
│ ├── env-validation.ts # Environment variable validation
│ ├── error-utils.ts # Error handling utilities
│ ├── logger.ts # Structured logging utility
│ ├── rate-limit.ts # Rate limiting implementation
│ ├── api-rate-limit.ts # API-specific rate limiting
│ ├── security-headers.js # Security headers configuration
│ ├── scan-utils.ts # Security scanner utilities
│ ├── activity-log.ts # Activity logging functions
│ ├── admin-utils.ts # Admin utility functions
│ ├── invite-utils.ts # Invite system utilities
│ ├── prisma.ts # Prisma client instance
│ └── __tests__/ # Utility tests
├── server/ # Server actions (Next.js Server Actions)
│ └── actions/ # Business logic actions
│ ├── auth.ts # Authentication actions
│ ├── projects.ts # Project actions
│ ├── tasks.ts # Task actions
│ ├── users.ts # User actions
│ ├── invites.ts # Invite actions
│ ├── dashboard.ts # Dashboard actions
│ ├── activity-logs.ts # Activity log actions
│ └── __tests__/ # Server action tests
├── prisma/ # Database schema and migrations
│ ├── schema.prisma # Prisma schema definition
│ ├── seed.ts # Database seeding script
│ └── migrations/ # Database migrations
├── public/ # Static assets
│ └── robots.txt # Search engine crawler rules
├── scripts/ # Utility scripts
│ └── clean-whitespace.sh # Code formatting utility
├── hooks/ # React hooks
│ └── use-toast.ts # Toast notification hook
├── types/ # TypeScript type definitions
│ └── next-auth.d.ts # NextAuth type extensions
├── middleware.ts # Next.js middleware (auth, security headers)
├── next.config.js # Next.js configuration
├── Dockerfile # Production Docker image definition
├── docker-compose.yml # Development Docker Compose
├── docker-compose.prod.yml # Production Docker Compose
├── build-prod.sh # Production Docker build script
├── start-prod.sh # Production startup script
├── run.sh # Development/production server script
├── DEPLOY.md # Detailed deployment guide
├── PRODUCTION.md # Production deployment guide
└── package.json # Dependencies and scripts
All environment variables are validated at application startup with helpful error messages if missing or invalid.
DATABASE_URL- PostgreSQL connection string (e.g.,postgresql://user:password@host:5432/database)NEXTAUTH_SECRET- Secret key for NextAuth session encryption (minimum 32 characters)NODE_ENV- Environment:development,production, ortest
NEXTAUTH_URL- Base URL of your application (required in production, e.g.,https://your-domain.com)
SCAN_TOKEN- Token for security scanners like OWASP ZAP (minimum 32 characters)SCAN_IP_WHITELIST- Comma-separated IP addresses or CIDR ranges for scanner accessNEXT_PUBLIC_BASE_URL- Public base URL for sitemap generation (defaults tohttp://localhost:3000)LOG_LEVEL- Log verbosity level:debug,info,warn,error(defaults toinfoin production)
ADMIN_EMAIL- Email address for the admin user created during database seedingADMIN_PASSWORD- Password for the admin user created during database seedingFORCE_RESeed- Set totrueto force re-seeding of demo data (keeps admin user, removes and recreates demo users/projects/tasks)
Demo User Passwords in Docker:
- Passwords are randomly generated and displayed in the seed output
- Credentials are saved to
./demo-credentials/demo-credentials.txt(created automatically) - View credentials:
cat ./demo-credentials/demo-credentials.txt - Or check Docker logs:
docker logs sentineldesk_seed
CLEANUP_TOKEN- Optional secret token for unauthenticated cleanup API access (for external cron jobs). If set, allows calling/api/admin/cleanup?token=TOKENwithout authentication.
The application validates all environment variables at startup:
- Missing required variables are reported with clear error messages
- Invalid values (wrong format, too short, etc.) are caught and explained
- Production-specific requirements (like
NEXTAUTH_URL) are enforced - Validation errors prevent the application from starting in production
SentinelDesk implements enterprise-grade security measures:
- Content Security Policy (CSP): Nonce-based CSP with strict directives
- HTTP Strict Transport Security (HSTS): Forces HTTPS connections
- X-Frame-Options: Prevents clickjacking attacks
- X-Content-Type-Options: Prevents MIME type sniffing
- Referrer-Policy: Controls referrer information
- Permissions-Policy: Restricts browser features
- X-Powered-By: Removed to prevent information disclosure
- NextAuth.js: Secure session management with JWT tokens
- Password Hashing: bcryptjs with secure salt rounds
- Role-Based Access Control (RBAC): USER and ADMIN roles
- Session Management: 30-day session expiration with secure cookies
- Failed Login Tracking: Security event logging for authentication attempts
- Rate Limiting: Configurable rate limits on all API endpoints
- Error Sanitization: Sensitive information never exposed to clients
- Input Validation: Zod schemas for all inputs and environment variables
- Security Scanner Support: Whitelisted IPs and tokens for automated security testing
- Environment Validation: Startup validation of all required environment variables
- Activity Logging: Comprehensive audit trail of all user actions
- Secure Cookies: HTTPS-only cookies in production
- Cache Control: No-cache headers for sensitive pages (login, admin, etc.)
The application uses structured logging for production environments:
- Development: Human-readable log format for easier debugging
- Production: JSON format for log aggregation tools (CloudWatch, Datadog, etc.)
- Error Logging: Automatic error sanitization to prevent information leakage
- Log Levels: debug, info, warn, error
Logs are automatically formatted based on NODE_ENV:
- Development:
[ERROR] [context] message - Production:
{"timestamp":"...","level":"error","message":"...","context":"..."}
You can control log verbosity with the LOG_LEVEL environment variable (defaults to info in production).
The application includes a health check endpoint at /api/health that can be used by monitoring systems and load balancers:
- Endpoint:
GET /api/health - Authentication: Not required
- Response Codes:
200 OK- Service is healthy503 Service Unavailable- Service is unhealthy (e.g., database connection failed)
Example Response (Healthy):
{
"status": "healthy",
"timestamp": "2024-01-01T12:00:00.000Z",
"uptime": 3600,
"checks": {
"database": "ok",
"databaseLatency": 5
}
}- Sitemap: Automatically generated at
/sitemap.xml(configureNEXT_PUBLIC_BASE_URLfor production) - robots.txt: Configured to disallow crawling of admin and API routes while allowing public pages
GET /api/health- Health check endpoint (no authentication required)
POST /api/auth/[...nextauth]- NextAuth authentication endpoints
GET /api/users- List users (admin only)GET /api/dashboard/stats- Get dashboard statisticsGET /api/activity-logs- Get activity logs with filtering and pagination
GET /api/projects- List projects (user's own projects, or all for admin)POST /api/projects- Create a new projectGET /api/projects/[projectId]- Get project detailsPATCH /api/projects/[projectId]- Update projectDELETE /api/projects/[projectId]- Delete projectGET /api/projects/[projectId]/tasks- Get tasks for a project
POST /api/tasks- Create a new taskGET /api/tasks/[id]- Get task detailsPATCH /api/tasks/[id]- Update taskDELETE /api/tasks/[id]- Delete task
GET /api/admin/stats- Get admin statisticsGET /api/admin/users- List all usersGET /api/admin/users/[userId]- Get user detailsPATCH /api/admin/users/[userId]- Update user (e.g., change role)GET /api/admin/users/[userId]/activity- Get user activity logsGET /api/admin/invites- List all invitesPOST /api/admin/invites- Create an invite
All API endpoints (except /api/health) require authentication and are rate-limited.
The application uses the following main models:
- User: User accounts with roles (USER, ADMIN)
- Project: Projects owned by users with status (ACTIVE, ARCHIVED)
- Task: Tasks within projects with assignees and status (TODO, IN_PROGRESS, DONE)
- ActivityLog: Audit trail of user actions
- Invite: User invitation system with expiration and revocation support
Run the test suite:
npm testTests are located in:
app/api/__tests__/- API route testslib/__tests__/- Utility function testsserver/actions/__tests__/- Server action tests
- Set environment variables for production
- Build the application:
npm run build
- Start the production server:
npm start
Or use the provided script:
./run.sh --prodBuild a production Docker image:
./build-prod.sh sentineldesk latestThis creates a multi-stage optimized Docker image with:
- Standalone Next.js output
- Non-root user for security
- Minimal image size
- Production-ready configuration
┌────────────────────────────── Deployment Architecture ──────────────────────────────┐
│ │
│ Internet │
│ │ │
│ ▼ │
│ Cloudflare Tunnel │
│ │ (exposes a single public subdomain) │
│ ▼ │
│ Nginx (VM :8081 – front router) │
│ │ │
│ ├── / → Next.js app (Docker container on :3000) │
│ │ • Dynamic app │
│ │ • Auth, API routes │
│ │ │
│ └── /docs/ → Docusaurus (static site) │
│ • Built locally with `npm run build` │
│ • Deployed via rsync to /var/www/docusaurus │
│ • Served directly by Nginx │
│ │
│ Key points │
│ - Cloudflare Tunnel always points to Nginx (never directly to app containers) │
│ - Nginx is the single entry point and path router │
│ - Docusaurus uses `baseUrl: '/docs/'` │
│ - No special asset rules: one clean `location /docs/ {}` │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
- Set
NODE_ENV=production - Set
NEXTAUTH_URLto your production domain (required) - Generate a secure
NEXTAUTH_SECRET(32+ characters) - Configure production database connection string
- Set up SSL/TLS certificates (HTTPS required for production)
- Configure reverse proxy (nginx/traefik) if needed
- Set up monitoring and logging (structured logging is already implemented)
- Review security scanner configuration (if using automated scanners)
SentinelDesk includes comprehensive Docker support for production deployment.
-
Build the production image:
./build-prod.sh sentineldesk latest
-
Create
.env.prodfile with your production environment variables:POSTGRES_USER=sentineldesk POSTGRES_PASSWORD=your-secure-password POSTGRES_DB=sentineldesk POSTGRES_PORT=5432 NEXTAUTH_URL=https://your-domain.com NEXTAUTH_SECRET=your-secret-key-minimum-32-characters APP_PORT=3000 SCAN_TOKEN=optional-scanner-token SCAN_IP_WHITELIST=optional-ip-whitelist
-
Start services:
./start-prod.sh
This script will:
- Create
.env.prodtemplate if it doesn't exist - Start PostgreSQL database container
- Wait for database to be healthy
- Run database migrations automatically
- Seed admin user (if needed)
- Start the web application
See DEPLOY.md for detailed deployment instructions including:
- Building and transferring Docker images
- Using Docker registries
- Server setup and configuration
See PRODUCTION.md for production-specific guidance including:
- HTTPS setup
- Database connection troubleshooting
- Production environment configuration
The application can be deployed to any platform that supports Next.js:
- Vercel (recommended for Next.js, zero-config)
- AWS (EC2, ECS, Lambda, App Runner)
- Google Cloud Platform (Cloud Run, App Engine)
- Azure (App Service, Container Instances)
- DigitalOcean (App Platform, Droplets)
- Traditional VPS (with Node.js runtime and PM2)
Migrations are automatically run when using Docker Compose. For manual deployments:
npm run db:migrateImportant: Always backup your database before running migrations in production.
- Environment variables: Ensure all required environment variables are set correctly
- Prisma Client: Run
npm run db:generateif Prisma Client is missing - Cache issues: Clear
.nextdirectory and rebuild:rm -rf .next && npm run build - TypeScript errors: Run
npm run lintto check for type errors
- Connection string: Verify
DATABASE_URLformat is correct (postgresql://user:password@host:port/database) - Database server: Check that PostgreSQL is running and accessible
- Permissions: Ensure database user has proper permissions
- Docker: If using Docker, verify network connectivity between containers
- Migration errors: Run
npm run db:migrateto ensure schema is up to date
- NEXTAUTH_SECRET: Verify it's set and at least 32 characters long
- NEXTAUTH_URL: In production, ensure it matches your domain exactly (including protocol)
- Cookies: Check browser console for cookie-related errors
- HTTPS: Ensure HTTPS is properly configured in production (required for secure cookies)
- Session: Clear browser cookies and try logging in again
- Image not found: Build the image first:
./build-prod.sh sentineldesk latest - Database connection: Verify
DATABASE_URLuses the correct container name (dbin docker-compose) - Port conflicts: Check if port 3000 (or configured
APP_PORT) is already in use - Migrations: Check migration logs:
docker-compose -f docker-compose.prod.yml logs migrate - Container logs: View application logs:
docker-compose -f docker-compose.prod.yml logs -f web
- Database queries: Use Prisma Studio (
npm run db:studio) to inspect queries - Rate limiting: Check if you're hitting rate limits (check logs)
- Memory: Monitor container memory usage if running in Docker
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm test -- --coverage# Run linting
npm run lint
# Clean whitespace (utility script)
npm run clean:whitespace# Generate Prisma Client
npm run db:generate
# Create a new migration
npm run db:migrate
# Push schema changes (dev only, not for production)
npm run db:push
# Open Prisma Studio (database GUI)
npm run db:studio
# Seed the database
npm run db:seed
# Update demo data (creates, modifies, and deletes projects/tasks)
npm run demo:updateThe project includes a demo data update script that can be run periodically to simulate a "living" platform. This script:
- Creates new projects (20-25% chance per run)
- Deletes some projects (10-12% chance, protects initial seeded projects)
- Modifies existing projects:
- Adds new tasks
- Removes some tasks
- Updates task statuses
- Reassigns tasks
- Changes project status
To run the demo update script automatically, you can set up a cron job. The recommended interval is every 4-6 hours.
For local development or Docker:
# Edit crontab
crontab -e
# Add this line to run every 4 hours (adjust path as needed)
0 */4 * * * cd /path/to/sentineldesk && npm run demo:update >> /tmp/sentineldesk-demo-update.log 2>&1For Docker Compose:
You can add a cron service to your docker-compose.yml:
services:
demo-updater:
build: .
command: >
sh -c "while true; do
sleep 14400 && # 4 hours in seconds
npm run demo:update
done"
environment:
- DATABASE_URL=${DATABASE_URL}
depends_on:
- db
restart: unless-stoppedFor production deployments:
Use your system's cron daemon or a process manager like systemd timers:
# Create a systemd timer (example)
# /etc/systemd/system/sentineldesk-demo-update.service
[Unit]
Description=SentinelDesk Demo Data Update
After=network.target
[Service]
Type=oneshot
User=your-user
WorkingDirectory=/path/to/sentineldesk
Environment="DATABASE_URL=postgresql://..."
ExecStart=/usr/bin/npm run demo:update
# /etc/systemd/system/sentineldesk-demo-update.timer
[Unit]
Description=Run SentinelDesk Demo Update every 4 hours
[Timer]
OnBootSec=1h
OnUnitActiveSec=4h
[Install]
WantedBy=timers.targetThen enable and start the timer:
sudo systemctl enable sentineldesk-demo-update.timer
sudo systemctl start sentineldesk-demo-update.timerNote: The script protects initial seeded projects (those created by the seed script) from deletion. Only dynamically created projects can be removed.
For local development with Docker:
# Start database and run migrations
docker-compose up -d db migrate
# Start web application (requires local Node.js)
npm run devOr run everything in Docker:
# Build and start all services
docker-compose up --build- Create a feature branch from
main - Make your changes
- Write/update tests for new functionality
- Run tests and linting:
npm test && npm run lint - Ensure all tests pass
- Update documentation if needed
- Submit a pull request with a clear description
- Follow TypeScript best practices
- Use strict mode (already configured)
- Write tests for new features
- Follow existing code patterns
- Use meaningful variable and function names
[Add your license here]
For issues and questions:
- Check the Troubleshooting section
- Review DEPLOY.md for deployment issues
- Review PRODUCTION.md for production-specific guidance
- Create an issue for bugs or feature requests