Full-stack hello-world boilerplate proving out the entire stack end-to-end.
| Layer | Technology |
|---|---|
| Frontend | Vue 3 + Vite + Tailwind CSS |
| Backend | FastAPI (Python 3.12, uv) |
| Database | PostgreSQL (Docker locally, Supabase in prod) |
| Hosting | Vercel (frontend + backend serverless) |
| CI/CD | GitHub Actions |
- Docker + Docker Compose
- uv (Python package manager)
- Node 20+
cp .env.example .env
docker compose up --build| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Backend API | http://localhost:8000 |
| Postgres | localhost:5432 |
The frontend Vite dev server proxies /api/* requests to the backend, so the
Vue app fetches /api/ and receives {"message": "Hello World"} from FastAPI.
docker compose exec backend uv run alembic upgrade headBackend:
cd backend
uv sync --dev
cp .env.example .env # edit DATABASE_URL to point at your local Postgres
uv run alembic upgrade head
uv run uvicorn app.main:app --reloadFrontend:
cd frontend
npm install
npm run devBackend:
cd backend
uv run pytestFrontend:
cd frontend
npm testLinting:
# Python
cd backend && uv run ruff check .
# JavaScript
cd frontend && npm run lintSee DEPLOYMENT.md for the full step-by-step guide covering:
- Supabase project setup and connection strings
- Vercel backend (Python serverless) and frontend (static) setup
- Running Alembic migrations against Supabase
- GitHub Actions secrets configuration
- End-to-end verification and troubleshooting
.
├── .github/workflows/
│ ├── pr-checks.yml # lint + test on every PR
│ └── deploy.yml # deploy to Vercel on merge to main
├── backend/
│ ├── alembic/ # database migrations
│ ├── api/
│ │ └── index.py # Vercel serverless entry point
│ ├── app/
│ │ ├── config.py # pydantic-settings (reads .env)
│ │ ├── database.py # SQLAlchemy async engine + session
│ │ ├── main.py # FastAPI app (GET /, GET /health)
│ │ └── models/
│ │ └── message.py # example Message table
│ ├── tests/
│ ├── Dockerfile
│ ├── pyproject.toml # uv-managed dependencies
│ ├── requirements.txt # for Vercel Python runtime
│ └── vercel.json
├── frontend/
│ ├── src/
│ │ ├── App.vue # fetches from backend, displays response
│ │ └── main.js
│ ├── Dockerfile
│ ├── package.json
│ └── vite.config.js # dev proxy: /api/* → backend
├── docker-compose.yml
└── README.md
| Variable | Used by | Description |
|---|---|---|
DATABASE_URL |
Backend | Async Postgres URL (postgresql+asyncpg://...) |
BACKEND_URL |
Vite dev server (Docker) | Internal Docker hostname for the proxy |
VITE_API_BASE_URL |
Frontend (production) | Backend Vercel URL; leave empty in dev |