Documentation Index
Fetch the complete documentation index at: https://mintlify.com/sdurutr436/stay-sidekick/llms.txt
Use this file to discover all available pages before exploring further.
Stay Sidekick is configured via three .env files — the root .env for PostgreSQL credentials and Docker Compose settings, backend/.env for the Flask API, and web/.env for the public static site. All three are versioned as .env.example files in the repository. The root and backend files must be copied and populated with real values; web/.env ships with a Cloudflare Turnstile test key that works in development without any edits.
SECRET_KEY, JWT_SECRET_KEY, and FERNET_KEY must all be set to unique, randomly generated values in production. The placeholder strings shipped in .env.example are for illustrative purposes only — using them in production leaves the application completely insecure.
Root .env — PostgreSQL and Docker Compose
This file is read by Docker Compose to configure the postgres service and inject DATABASE_URL into the backend service. Copy it with:
| Variable | Required | Default | Description |
|---|
POSTGRES_DB | Yes | stay_sidekick | Name of the PostgreSQL database |
POSTGRES_USER | Yes | postgres | PostgreSQL username |
POSTGRES_PASSWORD | Yes | postgres | PostgreSQL password — must be changed for production |
DATABASE_URL | Yes | postgresql://postgres:postgres@postgres:5432/stay_sidekick | Full connection URI. Host postgres is the Docker Compose service name. Update to match any changes to POSTGRES_USER or POSTGRES_PASSWORD. |
TURNSTILE_SITE_KEY | No | 1x00000000000000000000AA (Cloudflare test key) | Cloudflare Turnstile site key, passed as a build argument to the web service. The default test key is always valid in development but should be replaced with a real site key from the Cloudflare dashboard before going to production. |
.env files do not interpolate variables. DATABASE_URL must be a fully literal string — you cannot write postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@... inside the file itself.
backend/.env — Flask API
This file is loaded exclusively by the backend service. Copy it with:
cp backend/.env.example backend/.env
Flask core
| Variable | Required | Default | Description |
|---|
FLASK_ENV | Yes | development | Set to production on Railway |
SECRET_KEY | Yes | placeholder | Primary Flask secret key, used for session signing and CSRF. Must be ≥ 32 random characters. |
PORT | No | 5000 | Port Gunicorn listens on. Railway injects this automatically; Docker Compose ignores it. |
CORS
| Variable | Required | Default | Description |
|---|
ALLOWED_ORIGINS | Yes | http://localhost:4200 | Comma-separated list of allowed origins (no spaces). Docker Compose overrides this to http://localhost automatically. On Railway, set this to the public HTTPS URL of your nginx service. |
JWT
| Variable | Required | Default | Description |
|---|
JWT_SECRET_KEY | Yes | placeholder | Secret key for signing HS256 JWT access tokens issued by the panel |
JWT_ACCESS_TOKEN_HOURS | No | 1 | Access token lifetime in hours |
Encryption
| Variable | Required | Default | Description |
|---|
FERNET_KEY | Yes | (empty) | Fernet symmetric key used to encrypt PMS and AI API keys stored in PostgreSQL (common/crypto.py). Must be generated fresh for every environment — see below. |
Cloudflare Turnstile
| Variable | Required | Default | Description |
|---|
TURNSTILE_SECRET_KEY | No | placeholder | Server-side secret key for verifying Turnstile challenge tokens. Obtained from the Cloudflare dashboard alongside the site key. |
TURNSTILE_VERIFY_URL | No | https://challenges.cloudflare.com/turnstile/v0/siteverify | Turnstile verification endpoint. No need to change this unless Cloudflare updates the URL. |
Google OAuth
| Variable | Required | Default | Description |
|---|
GOOGLE_CLIENT_ID | No | placeholder | OAuth 2.0 client ID from Google Cloud Console. Required only if using the Google Contacts sync feature. |
GOOGLE_CLIENT_SECRET | No | placeholder | OAuth 2.0 client secret from Google Cloud Console |
GOOGLE_REDIRECT_URI | No | http://localhost/api/contactos/google/callback | Callback URI registered in Google Cloud Console. Use https://your-domain/api/contactos/google/callback on Railway. |
Frontend redirect
| Variable | Required | Default | Description |
|---|
FRONTEND_BASE_URL | No | http://localhost | Base URL of the Angular SPA, used to construct post-OAuth redirect URLs. Set to the public HTTPS nginx URL on Railway. |
Mailgun
| Variable | Required | Default | Description |
|---|
MAIL_GUN_API_KEY | No | placeholder | Mailgun private API key. Found under Account → Security → API Keys. |
MAIL_GUN_DOMAIN | No | placeholder | Verified Mailgun sending domain (e.g. mg.yourdomain.com) |
MAIL_GUN_API_URL | No | https://api.eu.mailgun.net | Mailgun API base URL. Use https://api.mailgun.net for US region accounts. |
MAIL_FROM | No | placeholder | From: address on outgoing emails and recipient of public contact form submissions. Falls back to noreply@<MAIL_GUN_DOMAIN> if left empty. |
Discord webhooks
| Variable | Required | Default | Description |
|---|
DISCORD_WEBHOOK_URL | No | placeholder | Webhook for the company sign-up request channel (/solicitud form) |
DISCORD_WEBHOOK_CONTACT_URL | No | placeholder | Webhook for the general contact channel (/empresa/contacto form) |
DISCORD_WEBHOOK_OPERATIONS_URL | No | placeholder | Webhook for the operations/alerts channel |
Rate limiting
| Variable | Required | Default | Description |
|---|
RATE_LIMIT_CONTACT | No | 5/hour | Rate limit applied per IP on the public contact and sign-up form endpoints. Uses Flask-Limiter notation (e.g. 10/minute, 100/day). |
| Variable | Required | Default | Description |
|---|
AI_DEFAULT_PROVIDER | No | gemini | Default AI provider for the Communications Vault assistant. Accepted values: gemini, openai, claude. |
AI_DEFAULT_MODEL | No | gemini/gemini-2.0-flash | LiteLLM model string for the default provider (e.g. gpt-4o-mini, claude-haiku-3) |
AI_DEFAULT_API_KEY | No | placeholder | API key for the default provider. Used for companies that have not configured their own BYOK key. |
AI_FREE_LIMIT_DAILY | No | 100 | Maximum AI requests per company per day on the shared free tier |
AI_FREE_LIMIT_WEEKLY | No | 500 | Maximum AI requests per company per week on the shared free tier |
AI_PROMPT_ADMIN_IPS | No | 127.0.0.1 | Comma-separated list of IPs authorised to manage system prompts via the admin endpoint |
Smoobu integration
| Variable | Required | Default | Description |
|---|
SMOOBU_API_KEY | No | placeholder | Smoobu REST API key for the property management system integration. Generated in Smoobu under Settings → API. |
Database
| Variable | Required | Default | Description |
|---|
DATABASE_URL | Yes | postgresql://postgres:postgres@postgres:5432/stay_sidekick | PostgreSQL connection URI. In Docker Compose this is injected automatically from the root .env. On Railway, set this as a variable reference — see below. |
On Railway, always set DATABASE_URL as a variable reference rather than a hardcoded string:DATABASE_URL=${{ Postgres.DATABASE_URL }}
Railway resolves this to the live connection string from the managed PostgreSQL plugin and updates it automatically if credentials are rotated.
web/.env — Public static site (11ty)
This file is loaded by the web service at container startup. It is versioned as web/.env.example in the repository. Unlike the other two .env files, it ships pre-populated with a Cloudflare Turnstile test site key that is always valid in development, so no edits are needed for local use. Copy it with:
cp web/.env.example web/.env
| Variable | Required | Default | Description |
|---|
TURNSTILE_SITE_KEY | No | 1x00000000000000000000AA (Cloudflare test key) | Public Cloudflare Turnstile site key embedded in the contact form HTML. The default test key always passes in development. Replace with a real site key from the Cloudflare Turnstile dashboard before going to production. |
TURNSTILE_SITE_KEY is also passed as a Docker build argument to the web service via docker-compose.yml. The value in web/.env is used at runtime; the build argument value (TURNSTILE_SITE_KEY from the root .env) is baked into the static HTML at build time. For local development both default to the same Cloudflare test key.
Generating required secrets
Three variables must be set to freshly generated cryptographic values in every environment. You can generate all three with the Python standard library and the cryptography package (already a backend dependency).
SECRET_KEY and JWT_SECRET_KEY — random URL-safe token, 32+ bytes:
python -c "import secrets; print(secrets.token_urlsafe(32))"
FERNET_KEY — 32-byte base64-encoded key required by the cryptography library:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Run each command separately and paste the output as the variable value. Never reuse keys across environments, and never commit real keys to version control.