Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/lffiesco-svg/gastromovil/llms.txt

Use this file to discover all available pages before exploring further.

GastroMóvil is fully deployment-ready for Railway. The repository already includes railway.toml and railway.json, which configure the Nixpacks builder, the build command that compiles Tailwind CSS and collects static assets, and the start command that migrates the database and launches Daphne on the dynamic $PORT Railway assigns. No additional configuration files need to be created — just provision the required environment variables, connect the GitHub repository, and Railway handles the rest.
GastroMóvil cannot be served by Gunicorn or any other WSGI server in production. Django Channels’ WebSocket consumers in the pedidos and repartidores apps require a real ASGI runtime. Always use daphne -b 0.0.0.0 -p $PORT gastromovil.asgi:application as the start command. Replacing Daphne with Gunicorn will silently break all real-time order-tracking and driver-dispatch features.

What Railway Gets Out of the Box

The railway.toml at the project root drives the build and deploy lifecycle:
[build]
buildCommand = "python manage.py tailwind build && python manage.py collectstatic --noinput"

[deploy]
startCommand = "python manage.py migrate && daphne -b 0.0.0.0 -p $PORT gastromovil.asgi:application"
railway.json tells Railway to use the Nixpacks builder and sets the restart policy to ON_FAILURE:
{
  "build": {
    "builder": "NIXPACKS"
  },
  "deploy": {
    "startCommand": "daphne -b 0.0.0.0 -p $PORT gastromovil.asgi:application",
    "restartPolicyType": "ON_FAILURE"
  }
}

Static and Media Files

  • Static files — WhiteNoise serves compiled static assets directly from Django without a separate CDN. STATICFILES_STORAGE = 'whitenoise.storage.StaticFilesStorage' is already set in settings.py, and whitenoise.middleware.WhiteNoiseMiddleware is in the middleware stack. The collectstatic step in the build command writes everything to staticfiles_prod/.
  • Media files — All user-uploaded content (restaurant images, product photos) is stored in Cloudinary. DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage' is configured in settings.py, so uploads go directly to your Cloudinary account rather than the ephemeral Railway filesystem.

Environment Variables

Set the following variables in the Railway project’s Variables tab before the first deploy. Railway injects them into the container at runtime and they are read by python-decouple/python-dotenv:
# Django core
SECRET_KEY=your-long-random-secret-key-here
DEBUG=False

# MySQL — use the values Railway provides for the MySQL plugin
DB_NAME=railway
DB_USER=root
DB_PASSWORD=<railway-generated-password>
DB_HOST=<railway-mysql-host>
DB_PORT=3306

# Enable TLS for Railway's MySQL
USE_DB_SSL=True

# Email (SMTP via Gmail — password recovery)
EMAIL_HOST_PASSWORD=your_gmail_app_password

# Contact form email password
CONTACTO_EMAIL_PASSWORD=your_contact_email_password

# Resend (transactional email API)
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx

# Cloudinary (media storage)
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret

# Groq (LangChain AI chatbot)
GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxx
When USE_DB_SSL=True, settings.py passes {'ca': certifi.where(), 'check_hostname': False} as MySQL SSL options so that PyMySQL validates the Railway MySQL TLS certificate against the certifi CA bundle. Set USE_DB_SSL=False only for local development against an unencrypted MySQL instance.

CSRF Trusted Origins

settings.py already includes the domains you need for Railway and the custom production domain:
CSRF_TRUSTED_ORIGINS = [
    'http://127.0.0.1:8000',
    'http://localhost:8000',
    'https://*.onrender.com',
    'https://*.railway.app',
    'https://gastromovil.online',
    'https://www.gastromovil.online',
]
If you are deploying to a custom domain other than gastromovil.online, add it to this list before deploying. Railway’s auto-generated *.railway.app subdomain is already covered by the wildcard entry.

Deploy to Railway

1

Create a new Railway project

Log into railway.app and click New Project. Choose Empty Project — you will add the database plugin and the GitHub service separately.
2

Add the MySQL plugin

Inside your new project, click + NewDatabaseMySQL. Railway provisions a managed MySQL 8 instance and exposes the connection variables (MYSQL_URL, MYSQLHOST, MYSQLUSER, MYSQLPASSWORD, MYSQLDATABASE, MYSQLPORT) automatically.Copy those values into the manual environment variables listed above (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT). Railway does not auto-inject them with the names GastroMóvil expects, so you must map them explicitly in the Variables tab of your app service.
3

Set environment variables

Select your app service (not the MySQL service) and open the Variables tab. Add every variable from the table above. Double-check that USE_DB_SSL=True, DEBUG=False, and that all Cloudinary, Resend, and Groq credentials are present.
4

Connect your GitHub repository

In the app service, go to SettingsSource and connect your GitHub account. Select the gastromovil repository and choose the branch you want to deploy (typically main). Railway will detect railway.toml automatically.
5

Trigger the first deploy

Click Deploy. Railway’s Nixpacks builder will:
  1. Detect Python and install dependencies from requirements.txt.
  2. Run python manage.py tailwind build to compile Tailwind CSS.
  3. Run python manage.py collectstatic --noinput to gather static files into staticfiles_prod/.
  4. On container start, run python manage.py migrate to apply all database migrations.
  5. Launch daphne -b 0.0.0.0 -p $PORT gastromovil.asgi:application.
Watch the build logs for any missing environment variables or migration errors. A successful deploy ends with a Daphne startup message like 2024-01-01 00:00:00,000 INFO Starting server at tcp:port=XXXX.
6

Configure a custom domain (optional)

In the Railway service settings under Networking, click Add Custom Domain and enter your domain (e.g., gastromovil.online). Railway provides CNAME records to point your DNS to the Railway edge. Once DNS propagates, the https://gastromovil.online and https://www.gastromovil.online entries already in CSRF_TRUSTED_ORIGINS will match your production traffic.

WebSocket Support in Production

The ASGI entry point (gastromovil/asgi.py) registers two sets of WebSocket URL patterns:
application = ProtocolTypeRouter({
    'http': get_asgi_application(),
    'websocket': AuthMiddlewareStack(
        URLRouter(
            pedidos.routing.websocket_urlpatterns +
            repartidores.routing.websocket_urlpatterns
        )
    ),
})
Daphne handles the protocol upgrade from HTTP to WebSocket transparently. Railway’s reverse proxy forwards WebSocket upgrade requests without additional configuration. The InMemoryChannelLayer configured in settings.py works for single-instance deployments — if you scale to multiple replicas in the future, replace it with a Redis-backed channel layer.

Build docs developers (and LLMs) love