Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Imjuanisss/proyecto-melika/llms.txt

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

Railway is the recommended hosting platform for MELIKA. Its project model maps cleanly to the monorepo’s three concerns — a Node.js/Express API, a React/Vite static site, and a managed PostgreSQL database — each running as an isolated service with its own environment, resource limits, and URL. This guide walks through every step from creating the Railway project to verifying a live health-check endpoint, including the critical ordering of environment variables that Vite requires at build time.

Architecture overview

MELIKA runs as three Railway services within a single project. Keeping them separate gives you independent deploy pipelines, isolated restart behaviour, and per-service environment variable scopes.

server

Node.js ≥ 20 + Express 5. Reads DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, JWT_SECRET, FRONTEND_URL, and the Gmail OAuth2 variables. Start command: node src/server.js.

client

React 19 + Vite 8 static build. Needs VITE_API_URL set before the build runs. Served with the serve package. Start command: npm start.

postgres

Railway-managed PostgreSQL. Exposes PGHOST, PGPORT, PGUSER, PGPASSWORD, and PGDATABASE — wire these into the server service as DB_* variables using Railway variable references.

Deployment steps

1

Create a Railway project

Log in to railway.app and click New Project. Choose Empty project — you will add each service manually so you have full control over the configuration order.Give the project a name (e.g. melika) and note the project URL. All three services will live under this project.
2

Add the PostgreSQL database service

Inside the project, click NewDatabaseAdd PostgreSQL. Railway provisions a managed Postgres instance and immediately makes the following variables available:
PGHOST / PGPORT / PGUSER / PGPASSWORD / PGDATABASE
Railway exposes individual PG* variables for the Postgres service. You will wire these into the server service as DB_HOST, DB_PORT, DB_NAME, DB_USER, and DB_PASSWORD using Railway variable references in the next step.
3

Deploy the backend service

Click NewGitHub Repo and select your MELIKA repository. Railway will detect the monorepo. Configure the service as follows:
SettingValue
Root directory/server
Build commandnpm install
Start commandnode src/server.js
Service nameserver
Click Deploy. Watch the build logs — the server starts when you see output like:
Servidor MELIKA listo y escuchando en el puerto 3000
4

Apply the database schema

The schema must be applied once to the Railway Postgres instance before the API can serve requests.After the command completes, verify the tables exist:
\dt
-- Expected: usuarios, codigos_verificacion, tokens_invitacion,
--           especialidades, medicamentos, medicos, franjas_horarias,
--           citas, historias_clinicas, logs_citas,
--           documentos_clinicos, recetas_medicas, ordenes_examenes
5

Create the first admin user

Still in the server service Shell on Railway, run the admin-creation script:
node scripts/crearAdmin.js
The script does not prompt for input — admin credentials are hardcoded inside the script. On success it prints the email, role, and initial plaintext password. Change the password immediately after the first login.
This step must be performed after the schema is applied. The script will fail with a relation-not-found error if the usuarios table does not exist yet. The shell opens at /server (the service root directory), so the path is scripts/crearAdmin.js, not server/scripts/crearAdmin.js.
6

Deploy the frontend service

Back in the Railway project, click NewGitHub Repo → same MELIKA repository. Configure the service:
SettingValue
Root directory/client
Build commandnpm run build
Start commandnpm start
Service nameclient
Do not deploy yet. VITE_API_URL must be set before the build runs because Vite embeds it into the JavaScript bundle at compile time. A build without this variable will produce a client that cannot reach the API.
7

Set VITE_API_URL on the frontend service

In the client service Settings → Variables, add:
VITE_API_URL=https://<your-server-service>.up.railway.app
Copy the exact public URL of your server service from its Settings → Networking section (no trailing slash).Now trigger the build by clicking Deploy or pushing a commit. Vite will embed VITE_API_URL during the build step.
8

Set FRONTEND_URL on the backend service

Once the client service has deployed successfully, copy its public URL from Settings → Networking. Go back to the server service variables and set:
FRONTEND_URL=https://<your-client-service>.up.railway.app
Railway will automatically redeploy the server with the updated CORS configuration.
The value of FRONTEND_URL must match the client’s URL exactly — same scheme (https://), same hostname, no trailing slash. A mismatch will cause browsers to block all cross-origin API requests with a CORS error.

client/railway.json

The /client directory includes a railway.json configuration file that Railway reads automatically when deploying the client service. It codifies the builder, build command, start command, and restart policy so you do not need to re-enter them manually in the dashboard. If you need to change build behaviour, edit client/railway.json rather than the dashboard setting so the configuration stays in version control.
client/railway.json
{
  "$schema": "https://railway.app/railway.schema.json",
  "build": {
    "builder": "NIXPACKS",
    "buildCommand": "npm run build"
  },
  "deploy": {
    "startCommand": "npm start",
    "restartPolicyType": "ON_FAILURE"
  }
}

Verifying the deployment

Once all three services are running, confirm the backend is healthy with a GET request to the root endpoint:
curl https://<your-server-service>.up.railway.app/
A healthy server returns:
{
  "status": "ok",
  "message": "Servidor MELIKA funcionando correctamente"
}
Then open the frontend URL in a browser, log in with the admin credentials you created in step 5, and confirm that the dashboard loads and API calls succeed.

Environment variable reference summary

# Injected automatically by Railway
PORT                  # assigned by Railway

# Wired from the Postgres service via variable references
DB_HOST               # ${{Postgres.PGHOST}}
DB_PORT               # ${{Postgres.PGPORT}}
DB_NAME               # ${{Postgres.PGDATABASE}}
DB_USER               # ${{Postgres.PGUSER}}
DB_PASSWORD           # ${{Postgres.PGPASSWORD}}

# Set manually
JWT_SECRET            # long random string — never share
FRONTEND_URL          # exact URL of the client service (no trailing slash)
EMAIL_USER            # sender Gmail address
GMAIL_CLIENT_ID       # Google Cloud OAuth2 client ID
GMAIL_CLIENT_SECRET   # Google Cloud OAuth2 client secret
GMAIL_REFRESH_TOKEN   # OAuth2 refresh token

Common issues

The most common cause is a mismatch between FRONTEND_URL on the server and the actual client URL. Check for a trailing slash, an http:// vs https:// difference, or a stale Railway-generated subdomain. Copy the URL directly from the Railway dashboard and update the variable, then redeploy the server service.
This usually means VITE_API_URL was not set when the frontend was built. The compiled bundle is calling undefined as the base URL. Set the correct VITE_API_URL value and trigger a fresh build by redeploying the client service.
Make sure all five DB_* variables are set on the server service and point to the Railway Postgres instance. Use Railway variable references (${{Postgres.PGHOST}} etc.) to ensure the values stay in sync if the Postgres service is reprovisioned.
The schema has not been applied yet. Run the psql command with melika_db.sql in the Railway shell first, then retry node scripts/crearAdmin.js.

Build docs developers (and LLMs) love