- TypeScript 55%
- Python 42.2%
- Shell 1.9%
- HTML 0.4%
- CSS 0.2%
- Other 0.2%
Use self and managed employee endpoints in leave request flows so employees can access their request pages without admin employee read access. |
||
|---|---|---|
| .agents/skills | ||
| .beads | ||
| .github/workflows | ||
| .opencode/agents | ||
| .pkm | ||
| .specify | ||
| backend | ||
| docs | ||
| frontend | ||
| scripts | ||
| .envrc | ||
| .gitignore | ||
| AGENTS.md | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| LICENSE.txt | ||
| opencode.json | ||
| README.md | ||
| recreate_admin_permissions.py | ||
| skills-lock.json | ||
| THIRD_PARTY_LICENSES.txt | ||
Flux
Flux is a modern full-stack application built with FastAPI and React, utilizing Refine for the frontend and Shadcn UI for components. It leverages devenv for a reproducible development environment.
Tech Stack
Backend
- Framework: FastAPI
- Database ORM: SQLAlchemy
- Migrations: Alembic
- Authentication: OAuth2 with JWT (python-jose, passlib)
- Linting & Formatting: Ruff
- Type Checking: ty
- Testing: Pytest
Frontend
- Framework: React 19
- Build Tool: Vite
- Data Framework: Refine
- UI Components: Shadcn UI, Radix UI
- Styling: Tailwind CSS
- Form Handling: React Hook Form
- Validation: Zod
Prerequisites
Getting Started
This project uses devenv to manage dependencies and services.
-
Clone the repository:
git clone <repository-url> cd fluxapp -
Start the development environment:
devenv upThis command will start all necessary services, including the backend API and frontend development server.
Runtime Configuration
Configuration is loaded from environment variables (backend/.env, frontend/.env) with examples in:
backend/.env.examplefrontend/.env.example
Backend variables
| Variable | Local development | Production | Notes |
|---|---|---|---|
ENVIRONMENT |
Optional (development default) |
Required (production) |
Controls strict config guards |
DATABASE_URL |
Required (can use local DB URL) | Required (must not use local default) | Backend startup fails outside development if left at local default |
SECRET_KEY |
Optional | Required | Backend startup fails outside development if missing or placeholder |
FRONTEND_URL |
Required | Required | Used in auth email links |
SENTRY_DSN |
Optional | Optional | If set, must not be a placeholder |
SMTP_*, EMAILS_*, DB_* |
Optional | Optional/recommended | Email + pool tuning |
Frontend variables
| Variable | Local development | Production | Notes |
|---|---|---|---|
VITE_API_URL |
Required | Required | Frontend boot fails if missing/placeholder/invalid |
VITE_APP_ENVIRONMENT |
Optional (development) |
Required (production) |
Used for strict runtime checks |
VITE_SENTRY_DSN |
Optional | Required | Frontend boot fails outside development if missing/placeholder |
Deployment
This repo is deployed as two services:
- Backend API on Fly.io, built from the
apidevenv container - Frontend SPA on Netlify
- Database on Neon and media storage on S3
Fly API flow
- Log in to Fly once with
flyctl auth login. - Build the backend image from devenv:
devenv container build api - Push that image to Fly's registry:
devenv container copy api \ --registry docker://registry.fly.io/ \ --copy-args="--dest-creds x:$(flyctl auth token)" - Create the Fly app without deploying yet, and make sure the service port is
8000:fly launch --image registry.fly.io/flux-api:<tag> \ --name flux-api \ --no-db \ --no-object-storage \ --no-deploy \ --internal-port 8000 - Set the runtime secrets on Fly:
Addfly secrets set \ DATABASE_URL='postgresql://...' \ SECRET_KEY='...' \ FRONTEND_URL='https://your-frontend-domain' \ MEDIA_S3_ENDPOINT_URL='...' \ MEDIA_S3_BUCKET='...' \ MEDIA_S3_ACCESS_KEY_ID='...' \ MEDIA_S3_SECRET_ACCESS_KEY='...'SENTRY_DSN,SMTP_*, orDB_*as needed. SetMEDIA_S3_REGIONandMEDIA_S3_FORCE_PATH_STYLEonly if your S3 provider needs them. - Deploy the same image:
fly deploy --image registry.fly.io/flux-api:<tag>
The container starts by running alembic upgrade head and then uvicorn.
Netlify Frontend flow
- Create a new Netlify site from the same repo.
- Set the base directory to
frontend. - Netlify reads
frontend/netlify.toml, runsbun run build, and publishesdist. Bun is detected fromfrontend/bun.lock. - Set the Netlify environment variables for production:
VITE_API_URL=https://<your-fly-api>.fly.dev VITE_APP_ENVIRONMENT=production VITE_SENTRY_DSN=... - Deploy the site, then copy the Netlify URL into Fly as
FRONTEND_URL.
If you use a custom domain on Netlify, point FRONTEND_URL at that domain instead.
Project Structure
fluxapp/
├── backend/ # FastAPI application
│ ├── app/ # Application source code
│ ├── alembic/ # Database migrations
│ └── tests/ # Backend tests
├── frontend/ # React application
│ ├── src/ # Frontend source code
│ └── public/ # Static assets
├── devenv.yaml # Development environment configuration
└── README.md # Project documentation
Documentation
- Backend Development Guide
- Adding Models
- Creating Endpoints
- Migrations
- Frontend Development Guide
- Generating API Client
- Adding Views & Columns
- Form Validation
Development
Pull Request Quality Gates
Every pull request runs CI quality gates for backend and frontend checks. A PR is merge-ready only when all jobs pass.
Required checks:
generated-client-sync: runs./scripts/generate-client.shand fails ifbackend/openapi.jsonorfrontend/src/lib/api-client/changes.backend-quality: runsuv run ruff check .,uv run ty check ., anduv run pytestinbackend/.frontend-quality: runsbun run lint,bunx tsc --noEmit,bun run test, andbun run buildinfrontend/.
Expected pass criteria before merge:
- Every command exits with status
0. - No generated API/client drift remains after
./scripts/generate-client.sh.
Backend
Navigate to the backend directory:
cd backend
- Run Tests:
pytest - Linting:
ruff check . - Type Checking:
ty check .
Frontend
Navigate to the frontend directory:
cd frontend
- Start Dev Server:
bun run dev # or refine dev - Build for Production:
bun run build - Linting:
bun run lint
Canonical Feature + API Sync Workflow
- Update backend models/schemas/endpoints in
backend/. - Regenerate the frontend API client from the repo root:
(or use the helper command./scripts/generate-client.shapi-generateinsidedevenv) - Wire generated client methods in
frontend/src/providers/generated-provider.tsand register routes/resources infrontend/src/App.tsx. - Use generated validation schemas from
frontend/src/lib/api-client/zod.gen.tsas the form validation source of truth.