A full-stack restaurant management application for pupuserías, built with FastAPI (backend) and React (frontend).
- Waiter Interface: Take orders, manage tables, process payments
- Kitchen Interface: View pending orders, update status, manage workflow
- Real-time Updates: 5-second polling for order synchronization
- Order Management: Create, update, complete, and cancel orders
- Menu Management: Comprehensive menu with pupusas and beverages
- FastAPI - Modern Python web framework
- SQLAlchemy - ORM for database operations
- SQLite - Lightweight database
- Pydantic - Data validation
- Uvicorn - ASGI server
- React 19 - UI framework
- TypeScript - Type safety
- Vite - Build tool and dev server
- Tailwind CSS - Styling
- Lucide React - Icons
- Sonner - Toast notifications
- Python 3.13+
- Node.js 18+
- uv (Python package manager)
- npm or pnpm
cd backend
# Install dependencies
uv sync --extra dev
# Start server
PYTHONPATH=./src uv run uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadBackend will be available at:
- API: http://localhost:8000
- Swagger Docs: http://localhost:8000/docs
- Health Check: http://localhost:8000/health
cd frontend
# Install dependencies
npm install
# Start dev server
npm run devFrontend will be available at: http://localhost:5173
.
├── backend/ # FastAPI backend
│ ├── src/
│ │ └── backend/
│ │ ├── main.py # FastAPI app
│ │ ├── config.py # Configuration
│ │ ├── database.py # Database setup
│ │ ├── models/ # SQLAlchemy models
│ │ ├── schemas/ # Pydantic schemas
│ │ └── routes/ # API endpoints
│ ├── tests/ # Backend tests
│ ├── .env # Environment variables
│ └── pyproject.toml # Python dependencies
│
├── frontend/ # React frontend
│ ├── src/
│ │ ├── features/
│ │ │ └── pupuseria/
│ │ │ ├── WaiterView.tsx # Waiter interface
│ │ │ └── KitchenView.tsx # Kitchen interface
│ │ ├── services/
│ │ │ ├── ordersApi.ts # API client
│ │ │ └── orderTransform.ts # Data transformers
│ │ └── types/ # TypeScript types
│ ├── .env # Environment variables
│ └── package.json # Node dependencies
│
└── docs/architecture-and-integration.md # Architecture and integration
POST /api/v1/orders- Create a new orderGET /api/v1/orders/pending- Get all pending ordersPATCH /api/v1/orders/{id}/complete- Mark order as completedDELETE /api/v1/orders/{id}- Cancel an order
GET /health- Health check endpoint
For detailed API documentation, visit http://localhost:8000/docs when the backend is running.
The frontend and backend communicate via REST API. See docs/architecture-and-integration.md for details on:
- Data transformation between frontend and backend
- Order workflow and status mapping
- API endpoints and polling behavior
cd backend
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=backend --cov-report=term-missing
# Lint code
uv run ruff check .
# Format code
uv run ruff format .
# Type check
uv run mypy srccd frontend
# Run linter
npm run lint
# Build for production
npm run build
# Preview production build
npm run previewCreate a .env file in the backend/ directory (or set these in Railway):
# Application Configuration
APP_NAME=Pupas API
APP_VERSION=0.1.0
DEBUG=false
# Server Configuration
HOST=0.0.0.0
PORT=8000
# Logging
LOG_LEVEL=INFO
# CORS Configuration (add your frontend URLs)
CORS_ORIGINS=["http://localhost:5173","http://localhost:3000","https://your-frontend.railway.app"]
CORS_ALLOW_CREDENTIALS=true
# Database (SQLite by default, can be changed to PostgreSQL)
DATABASE_URL=sqlite:////app/data/restaurant.dbCreate a .env file in the frontend/ directory (or set these in Railway):
# API URL - Update this to your backend URL
VITE_API_URL=http://localhost:8000Important for Production: Set VITE_API_URL to your Railway backend URL (e.g., https://your-backend.railway.app)
- Select a table (mesa)
- Add pupusas and beverages to order
- Click "Enviar a Cocina" to send to kitchen
- Order is created in backend and appears in Kitchen View
- View all pending orders in real-time
- Drag orders between status columns (Pendiente → Preparando → Listo)
- Delete orders if needed (calls cancel endpoint)
- Orders marked as "Listo" are completed in the backend
- Waiter clicks "Pagar" on a table
- All orders for that table are marked as completed
- Table is cleared and ready for new customers
See docs/architecture-and-integration.md for integration troubleshooting tips.
Backend won't start:
- Check if port 8000 is in use:
lsof -i :8000 - Verify Python version:
python --version
Frontend can't connect:
- Verify backend is running:
curl http://localhost:8000/health - Check CORS settings in
backend/.env
Orders not appearing:
- Check backend logs for errors
- Verify API endpoint:
curl http://localhost:8000/api/v1/orders/pending - Wait 5 seconds for polling to refresh
MIT
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linters
- Submit a pull request
- Deployment and Docker: docs/deployment.md
- Architecture and Integration: docs/architecture-and-integration.md
- Docs consolidation plan: docs/documentation-consolidation.md
- Utility Scripts: scripts/README.md
For detailed deployment instructions, see docs/deployment.md.
-
Deploy Backend:
- Create new Railway project from GitHub repo
- Set root directory to
backend - Add environment variables (see below)
- Add volume mount at
/app/data - Copy backend URL
-
Deploy Frontend:
- Add new service to same project
- Set root directory to
frontend - Set
VITE_API_URLto backend URL - Copy frontend URL
-
Update CORS:
- Update backend
CORS_ORIGINSwith frontend URL - Redeploy backend
- Update backend
See docs/deployment.md for complete step-by-step guide.
Test the Docker setup locally before deploying:
# Build and run with docker-compose
docker-compose up --build
# Backend will be available at http://localhost:8000
# Frontend will be available at http://localhost# Build backend
cd backend
docker build -t pupuseria-backend .
# Build frontend
cd frontend
docker build -t pupuseria-frontend --build-arg VITE_API_URL=http://localhost:8000 .Railway is a modern platform that makes deployment simple. Follow these steps:
- Create a Railway account
- Install Railway CLI (optional):
npm i -g @railway/cli - Have your code in a Git repository (GitHub, GitLab, etc.)
-
Create a New Project in Railway
-
Add a Service → Select "Deploy from GitHub repo"
-
Configure the Backend Service:
- Root Directory:
backend - Build Command: (leave empty, Dockerfile will be used)
- Start Command: (leave empty, Dockerfile CMD will be used)
- Root Directory:
-
Set Environment Variables in Railway dashboard:
APP_NAME=Pupas API DEBUG=false PORT=${{PORT}} HOST=0.0.0.0 LOG_LEVEL=INFO CORS_ORIGINS=["https://your-frontend-url.railway.app"] DATABASE_URL=sqlite:////app/data/restaurant.dbNote: Railway automatically provides
${{PORT}}variable. The backend will use this port. -
Add Volume (Optional but Recommended):
- Go to your backend service → Variables → Add Volume
- Mount path:
/app/data - This persists your SQLite database across deployments
-
Deploy - Railway will automatically detect the Dockerfile and deploy
-
Get your Backend URL - Copy the public URL (e.g.,
https://your-backend.railway.app)
-
Add Another Service to the same Railway project
-
Configure the Frontend Service:
- Root Directory:
frontend - Build Command: (leave empty, Dockerfile will be used)
- Start Command: (leave empty, Dockerfile CMD will be used)
- Root Directory:
-
Set Environment Variables (Build-time):
VITE_API_URL=https://your-backend.railway.appImportant: Replace with your actual backend URL from step 7 above.
-
Deploy - Railway will build and deploy the frontend
-
Access your App - Use the generated frontend URL
Environment Variables:
- Backend
CORS_ORIGINSmust include your frontend URL - Frontend
VITE_API_URLmust point to your backend URL - Use Railway's
${{PORT}}variable for the backend port - Set
DEBUG=falsein production
Database Options:
- SQLite (Default): Simple, requires volume mount at
/app/data - PostgreSQL: Add Railway PostgreSQL plugin and update
DATABASE_URL
Networking:
- Railway services can communicate privately using service names
- Public URLs are automatically generated with HTTPS
- CORS must be properly configured for cross-origin requests
Monitoring:
- Use Railway's built-in logs to debug issues
- Health check endpoints:
/health(backend),/health(frontend) - Set up alerts for service downtime
Railway automatically redeploys when you push to your connected Git branch:
git add .
git commit -m "Update application"
git push origin main# Login to Railway
railway login
# Link to your project
railway link
# Deploy backend
cd backend
railway up
# Deploy frontend
cd frontend
railway up| Variable | Description | Example |
|---|---|---|
PORT |
Server port (Railway sets this) | 8000 |
CORS_ORIGINS |
Allowed frontend URLs | ["https://app.railway.app"] |
DATABASE_URL |
Database connection string | sqlite:////app/data/restaurant.db |
| Variable | Description | Example |
|---|---|---|
VITE_API_URL |
Backend API URL | https://backend.railway.app |
| Variable | Description | Default |
|---|---|---|
APP_NAME |
Application name | Pupas API |
DEBUG |
Debug mode | false |
LOG_LEVEL |
Logging level | INFO |
CORS_ALLOW_CREDENTIALS |
Allow credentials | true |
Backend won't start:
- Check Railway logs for errors
- Verify
PORTenvironment variable is set - Ensure Dockerfile is in
backend/directory - Check that
pyproject.tomlanduv.lockare present
Frontend can't connect to backend:
- Verify
VITE_API_URLis set correctly (with https://) - Check backend
CORS_ORIGINSincludes frontend URL - Test backend health:
curl https://your-backend.railway.app/health - Check browser console for CORS errors
Database not persisting:
- Add a volume mount at
/app/datain Railway - Verify
DATABASE_URLpoints to/app/data/restaurant.db
Build failures:
- Check that all dependencies are in
package.json/pyproject.toml - Verify Dockerfile syntax
- Check Railway build logs for specific errors
For issues and questions, please open an issue on GitHub.