A production-ready full-stack boilerplatefeaturing Next.js 16 frontend and FastAPI backend with built-in authentication, encryption, rate limiting, and dual database support.
-
Authentication System
- JWT-based authentication for user sessions
- API Key/Secret authentication for external clients
- NextAuth v5 integration with credentials provider
- Encrypted credential transmission (AES-256-CBC)
- Password hashing with bcrypt
-
Role-Based Access Control (RBAC)
- Three user roles:
admin,user,guest - Role embedded in JWT tokens for stateless authorization
- Centralized route configuration with role requirements
- Client-side route guards with automatic redirects
- Conditional UI rendering based on user role
- Default role assignment on registration (
guest)
- Three user roles:
-
Dual Database Support
- SQLite (default) - zero configuration required
- MongoDB - optional, async with Motor driver
-
Security
- End-to-end encryption for auth payloads
- Rate limiting per user type (60/min users, 100/min API clients)
- CORS middleware configured
- JWT tokens with expiration
-
API Client Management
- Create/revoke API credentials
- Separate rate limits for API clients
- Track client usage
-
Modern Stack
- Next.js 16 with App Router
- React 19
- TypeScript
- Tailwind CSS 4
- FastAPI with async support
- Pydantic v2 validation
nextapi/
├── backend/ # FastAPI backend
│ ├── main.py # FastAPI application & routes
│ ├── auth.py # JWT & API key authentication
│ ├── models.py # SQLAlchemy models
│ ├── models_mongo.py # MongoDB models
│ ├── database.py # SQLite configuration
│ ├── database_mongo.py # MongoDB configuration
│ ├── schemas.py # Pydantic schemas
│ ├── crypto_utils.py # AES decryption utilities
│ ├── config.py # Database type selection
│ ├── rate_limiter.py # Rate limiting logic
│ └── pyproject.toml # Python dependencies
├── frontend/ # Next.js frontend
│ ├── app/ # App router pages
│ │ ├── page.tsx # Landing page
│ │ ├── home/ # Dashboard (protected)
│ │ ├── admin/ # Admin panel (admin only)
│ │ ├── guest/ # Guest page (guest, admin)
│ │ ├── login/ # Login page
│ │ ├── register/ # Registration page
│ │ └── api/ # API routes & NextAuth
│ ├── config/ # Configuration
│ │ └── routes.ts # RBAC route definitions
│ ├── lib/ # Utilities
│ │ ├── crypto.ts # Client-side encryption
│ │ └── crypto-server.ts # Server-side encryption
│ ├── types/ # TypeScript definitions
│ └── auth.ts # NextAuth configuration
└── package.json # Root scripts
- Node.js 18+
- Python 3.12+
- uv (Python package manager) - Install uv
- MongoDB (optional) - only if using MongoDB instead of SQLite
git clone <your-repo-url>
cd nextapi# Install root dependencies (concurrently)
npm install
# Install frontend dependencies
cd frontend && npm install && cd ..
# Install backend dependencies
cd backend && uv sync && cd ..# Encryption key for payload encryption (32 bytes hex)
ENCRYPTION_KEY=your-32-byte-hex-key-here
# JWT Configuration
JWT_SECRET_KEY=your-jwt-secret-key-here
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
# Rate Limiting (requests per minute)
RATE_LIMIT_USER=60
RATE_LIMIT_API_CLIENT=100
# Database Configuration (optional)
DATABASE_TYPE=sqlite # or "mongo"
MONGO_URL=mongodb://localhost:27017 # if using MongoDB
MONGO_DB_NAME=your_database_name # if using MongoDB# NextAuth secret (generate with: openssl rand -base64 32)
AUTH_SECRET=your-nextauth-secret-here
# NextAuth URL
AUTH_URL=http://localhost:3000
# Encryption key (MUST match backend ENCRYPTION_KEY)
NEXT_PUBLIC_ENCRYPTION_KEY=your-32-byte-hex-key-here# Generate a 32-byte hex key for encryption
openssl rand -hex 32
# Generate a base64 secret for NextAuth
openssl rand -base64 32Important: The ENCRYPTION_KEY (backend) and NEXT_PUBLIC_ENCRYPTION_KEY (frontend) must be identical for encrypted communication to work.
# From the root directory - runs both frontend and backend
npm run devThis starts:
- Frontend: http://localhost:3000
- Backend: http://localhost:8000
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register |
Register a new user |
| POST | /auth/login |
Login and receive JWT token |
Requires JWT Bearer token OR API Key/Secret headers.
| Method | Endpoint | Description | Rate Limit |
|---|---|---|---|
| GET | /health |
Health check | 60/min (user), 100/min (API) |
| GET | /get_user_details |
Get authenticated user details | 60/min (user), 100/min (API) |
Requires JWT Bearer token.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api-clients |
Create new API client |
| GET | /api-clients |
List your API clients |
| DELETE | /api-clients/{client_id} |
Revoke an API client |
# Login to get token
curl -X POST http://localhost:8000/auth/login \
-H "Content-Type: application/json" \
-d '{"data": "<encrypted-payload>"}'
# Use token in requests
curl http://localhost:8000/health \
-H "Authorization: Bearer <your-jwt-token>"# Create API client (requires JWT)
curl -X POST http://localhost:8000/api-clients \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{"name": "My App"}'
# Use API credentials
curl http://localhost:8000/health \
-H "X-API-Key: <client-id>" \
-H "X-API-Secret: <client-secret>"No configuration needed. The database file (app.db) is created automatically.
-
Set environment variables in
backend/.env:DATABASE_TYPE=mongo MONGO_URL=mongodb://localhost:27017 MONGO_DB_NAME=your_database
-
Ensure MongoDB is running on your system.
| Variable | Required | Default | Description |
|---|---|---|---|
ENCRYPTION_KEY |
Yes | - | 32-byte hex key for AES encryption |
JWT_SECRET_KEY |
Yes | - | Secret key for JWT signing |
JWT_ALGORITHM |
No | HS256 |
JWT algorithm |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES |
No | 30 |
Token expiration time |
RATE_LIMIT_USER |
No | 60 |
User requests per minute |
RATE_LIMIT_API_CLIENT |
No | 100 |
API client requests per minute |
DATABASE_TYPE |
No | sqlite |
Database type (sqlite or mongo) |
MONGO_URL |
No | mongodb://localhost:27017 |
MongoDB connection URL |
MONGO_DB_NAME |
No | learning_scheduler |
MongoDB database name |
| Variable | Required | Description |
|---|---|---|
AUTH_SECRET |
Yes | NextAuth.js secret for session encryption |
AUTH_URL |
Yes | Base URL of your application |
NEXT_PUBLIC_ENCRYPTION_KEY |
Yes | Must match backend ENCRYPTION_KEY |
npm run dev # Run frontend + backend concurrently
npm run api # Run backend onlynpm run dev # Development server
npm run build # Production build
npm run start # Production server
npm run lint # Run ESLintuv run uvicorn main:app --reload # Development server
uv run uvicorn main:app # Production server- Next.js 16.1.4
- React 19.2.3
- NextAuth 5.0.0-beta
- TypeScript 5
- Tailwind CSS 4
- crypto-js (client-side encryption)
- FastAPI 0.128+
- SQLAlchemy 2.0+
- Motor 3.7+ (MongoDB async driver)
- Pydantic 2.0+
- python-jose (JWT)
- bcrypt (password hashing)
- PyCryptodome (AES encryption)
- slowapi (rate limiting)
| Role | Description |
|---|---|
admin |
Full access to all routes and features |
user |
Standard authenticated user access |
guest |
Limited access (default role for new users) |
| Route | Allowed Roles | Description |
|---|---|---|
/home |
admin, user, guest | Main dashboard |
/admin |
admin | Admin panel |
/guest |
admin, guest | Guest-specific page |
- Registration: New users are assigned the
guestrole by default - Authentication: User role is embedded in the JWT token
- Route Protection: Frontend checks user role before rendering protected pages
- Unauthorized Access: Users are redirected to dashboard if they lack permissions
Routes and role requirements are defined in frontend/config/routes.ts:
export const ProtectedRoutes: ProtectedRoute[] = [
{ path: '/home', label: 'Dashboard', allowedRoles: ['admin', 'guest', 'user'] },
{ path: '/admin', label: 'Admin Panel', allowedRoles: ['admin'] },
{ path: '/guest', label: 'Guest Page', allowedRoles: ['guest', 'admin'] },
];import { hasAccess, getAccessibleRoutes, canAccessPath } from '@/config/routes';
// Check if user has a specific role
hasAccess('user', ['admin', 'user']); // true
// Get all routes accessible to a user
getAccessibleRoutes('guest'); // Returns routes for guest role
// Check if user can access a specific path
canAccessPath('admin', '/admin'); // true# 1. Copy the example env file and fill in your secrets
cp .env.example .env
# Edit .env — set ENCRYPTION_KEY, JWT_SECRET_KEY, AUTH_SECRET, NEXT_PUBLIC_ENCRYPTION_KEY
# 2. Build and start everything
docker compose up --build- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
Create a .env file in the project root (next to docker-compose.yml). See .env.example for all available variables.
| Variable | Required | Description |
|---|---|---|
ENCRYPTION_KEY |
Yes | 32-byte hex key — must match NEXT_PUBLIC_ENCRYPTION_KEY in frontend |
JWT_SECRET_KEY |
Yes | Secret used to sign JWT tokens |
JWT_ALGORITHM |
No | Default: HS256 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES |
No | Default: 30 |
RATE_LIMIT_USER |
No | Default: 60 (requests/min) |
RATE_LIMIT_API_CLIENT |
No | Default: 100 (requests/min) |
DATABASE_TYPE |
No | sqlite (default) or mongo |
MONGO_URI |
Only if mongo | Full MongoDB connection URI |
Generate secrets:
openssl rand -hex 32 # ENCRYPTION_KEY / JWT_SECRET_KEYDATABASE_TYPE=mongo MONGO_URI=mongodb://user:pass@host:27017/dbname docker compose up --buildThe SQLite database (app.db) is stored in a named Docker volume (backend_data) and survives container restarts.
nginx is optional and only starts when the ssl profile is active.
-
Drop your cert and key into
nginx/certs/:nginx/certs/cert.pem nginx/certs/key.pemGenerate a self-signed cert for local use:
openssl req -x509 -newkey rsa:4096 -keyout nginx/certs/key.pem \ -out nginx/certs/cert.pem -days 365 -nodes \ -subj "/CN=localhost" -
Start with the ssl profile:
docker compose --profile ssl up --build
- HTTPS: https://localhost (proxies to frontend)
- HTTP redirects to HTTPS automatically
- Edit
nginx/nginx.confto changeserver_namefor non-localhost domains
docker compose down # stop containers
docker compose down -v # stop + delete the SQLite volume- make the template PWA ready.
MIT
For questions or feedback, please contact:
Name: Mohammed Khan.
Email: mkhan@live.co.za
GitHub: sup3rus3r
