Configuration
Better Reports is configured via environment variables. Copy the .env.example file to get started:
bash
cp .env.example .envEnvironment Variables
| Variable | Default | Description |
|---|---|---|
REPORTS_PORT | 3000 | HTTP server port |
REPORTS_VERSION | 1.0.0 | App version string |
REPORTS_UI_DIR | ./ui/dist | Built UI static files path |
REPORTS_USER | � | Basic auth username (empty = disabled) |
REPORTS_PASS | � | Basic auth password (empty = disabled) |
REPORTS_CORS_ORIGIN | * | Allowed CORS origins (comma-separated) |
REPORTS_RATE_LIMIT | 100 | Max requests per 60s sliding window (compile endpoints get 1/4) |
REPORTS_TEMPLATES_DIR | ./templates | Template storage directory |
REPORTS_ASSETS_DIR | ./assets | Asset directory |
REPORTS_FONTS_DIR | � | Custom fonts directory (defaults to assets dir) |
REPORTS_MAX_BODY_SIZE | 10485760 (10 MB) | Max request body size in bytes |
REPORTS_COMPILE_TIMEOUT | 60000 (60 s) | Max Typst compilation time in milliseconds |
REPORTS_CACHE_SIZE | 100 | Max cached compiled PDFs in memory (LRU) |
REPORTS_POOL_SIZE | 2 | Number of pre-warmed compilation workers |
LOG_LEVEL | info | Logging level (info, debug, warn, error) |
Authentication
Authentication is optional and resolved in this priority order:
- Env vars: Both
REPORTS_USERandREPORTS_PASSset - Credentials file:
.credentials.jsonin the app root (created via/api/change-password) - Default credentials:
admin/password123(hardcoded fallback)
bash
# Enable auth via env vars
REPORTS_USER=admin
REPORTS_PASS=your-secure-passwordThe UI has a dedicated login page at /login and supports changing passwords via the settings menu.
Data Directory Structure
templates/ # Typst template files (.typ) and metadata (.json)
assets/ # Uploaded assets (images, fonts, documents)
.packages/ # Installed Typst community packages (auto-managed)Rate Limiting
The app uses a sliding window rate limiter per IP:
- General limit:
REPORTS_RATE_LIMITrequests per 60-second window - Compilation limit: 1/4 of the general limit (applied to
/api/reportand/api/preview) - Rate limit entries are cleaned up every 2 windows
CORS
By default, all origins are allowed. Restrict to specific origins in production:
bash
REPORTS_CORS_ORIGIN=https://reports.yourdomain.com
# Multiple origins (comma-separated)
REPORTS_CORS_ORIGIN=https://app.example.com,https://admin.example.com