A production-ready Backend-for-Frontend (BFF) server for the Fomio mobile application, providing secure authentication and GraphQL API proxying to Discourse forums.
- GraphQL API: Unified GraphQL schema that abstracts Discourse's REST API
- JWT Authentication: RS256-based access tokens with refresh token rotation
- Discourse Integration: Seamless SSO and API key management
- API Proxying: Secure read/write operations to Discourse API via GraphQL
- Rate Limiting: Configurable rate limits for different endpoint types
- Security Headers: CORS, HSTS, CSP, and other security headers
- Metrics Collection: Prometheus-compatible metrics endpoint
- Graceful Shutdown: Proper connection draining and cleanup
- Fault Injection: Testing endpoints for resilience validation
- Containerization: Docker and Docker Compose support
- Monitoring: Pre-configured Grafana dashboards
- TypeScript with strict type checking
- Fastify web framework with request logging and error handling
- Apollo Server for GraphQL API implementation
- Prisma ORM with SQLite (development) and PostgreSQL (production) support
- Zod validation for request/response schemas
- Pino structured logging with request IDs
- Vitest for testing
- ESLint for code quality
- GitHub Actions CI/CD pipeline
- Node.js: Version 20 or higher
- Docker: For containerized deployment
- PostgreSQL: For production database
- Redis: For distributed rate limiting (optional)
Copy the environment template and configure your values:
cp .env.production.example .envUpdate the required variables in .env. See .env.production.example for a full list of options.
# Install dependencies
npm install
# Generate Prisma client
npm run generate
# Run database migrations
npm run migrate
# Start development server
npm run devThe server will be available at http://localhost:8080.
The server exposes a GraphQL API at /graphql that provides:
Queries:
me- Get current authenticated user profilelatestTopics- Get latest topics feedtopic(id: ID!)- Get specific topic with postshubs- Get all hubs (categories)hub(id: ID!)- Get specific hubteret(id: ID!)- Get specific teret (subcategory)byte(id: ID!)- Get specific byte (topic)
Mutations:
createTopic(input: CreateTopicInput!)- Create new topiccreatePost(input: CreatePostInput!)- Create new post (reply)likePost(postId: ID!)- Like a postunlikePost(postId: ID!)- Unlike a postbookmarkPost(postId: ID!)- Bookmark a postunbookmarkPost(postId: ID!)- Remove bookmark
Authentication:
All queries and mutations require authentication via JWT token in the Authorization: Bearer <token> header.
Example Query:
query {
me {
id
username
name
avatarTemplate
trustLevel
}
}Example Mutation:
mutation {
createTopic(input: {
title: "My New Topic"
raw: "This is the content of my topic"
categoryId: 1
}) {
id
title
slug
}
}Using Docker Compose is the recommended method for production:
# Build and start all services in detached mode
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d
# View server logs
docker-compose logs -f bff
# Stop all services
docker-compose downSee the Deployment Guide for more detailed instructions.
- CORS Protection: Configurable origin allowlist
- Security Headers: HSTS, CSP, X-Frame-Options, etc.
- Rate Limiting: Per-user and per-IP limits
- JWT Validation: RS256 signature verification
- API Key Encryption: AES-256-GCM for stored credentials
- Prometheus: Metrics collection and alerting
- Grafana: Visualization and dashboards
- Custom Metrics: HTTP requests, Discourse API calls, auth failures
- Graceful Shutdown: 10-second timeout with connection draining
- Retry Logic: Exponential backoff for Discourse API calls
- Circuit Breaking: Automatic failure detection and recovery
Access metrics at /metrics (basic auth protected if configured):
curl -u username:password http://localhost:8080/metricsPre-configured dashboard available at http://localhost:3000:
- HTTP request rates and response times
- Discourse API performance
- Authentication failure rates
- Rate limiting statistics
- Application:
GET /health - Version Info:
GET /version - JWKS:
GET /.well-known/jwks.json
This project uses Vitest for testing. The test suite is divided into three categories:
- Unit Tests: Focused on individual functions and modules.
- Integration Tests: Verify interactions between different parts of the application.
- End-to-End (E2E) Tests: Simulate complete user journeys.
# Run all tests
npm test
# Run tests with coverage report
npm run test:coverage
# Run tests in watch mode
npm run test:watchTest coverage is enforced via CI/CD pipelines, with a target of 90% coverage.
Performance testing is done using k6.
# Run smoke tests (low load)
npm run perf:smoke
# Run load tests (moderate load)
npm run perf:load
# Run stress tests (high load)
npm run perf:stressSee the performance testing scripts for more details.
- API Documentation: Detailed information about API endpoints.
- Deployment Guide: Instructions for deploying the server to production.
- Operations Runbook: Guidance for maintaining the server and responding to incidents.
- OpenAPI Specification: Machine-readable API definition.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
MIT