Full conversion of the Flask/Jinja app into a React frontend + Flask REST API architecture deployable on Netlify (frontend) and Render/Railway (backend API).
civil-registrar/
├── netlify.toml ← Netlify build config
│
├── frontend/ ← React app (deploy to Netlify)
│ ├── index.html
│ ├── vite.config.js
│ ├── package.json
│ ├── .env.example
│ ├── public/
│ │ └── _redirects ← SPA routing for Netlify
│ └── src/
│ ├── main.jsx
│ ├── App.jsx ← Routes
│ ├── index.css ← Global styles
│ ├── context/
│ │ └── AuthContext.jsx ← Login state
│ ├── utils/
│ │ └── api.js ← Axios instance
│ ├── components/
│ │ ├── AdminLayout.jsx ← Sidebar shell
│ │ └── AdminLayout.css
│ └── pages/
│ ├── Landing.jsx ← Public home page
│ ├── Landing.css
│ ├── AnnouncementView.jsx
│ ├── Login.jsx
│ ├── Login.css
│ ├── Dashboard.jsx ← Charts + KPIs
│ ├── Dashboard.css
│ ├── Transactions.jsx
│ ├── TransactionForm.jsx
│ ├── Services.jsx
│ ├── ServiceForm.jsx
│ ├── Achievements.jsx
│ ├── AchievementForm.jsx
│ ├── Announcements.jsx
│ ├── AnnouncementForm.jsx
│ └── Reports.jsx
│
└── api/ ← Flask REST API (deploy to Render/Railway)
├── app.py
├── requirements.txt
└── render.yaml
cd api
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python app.py
# API runs at http://localhost:5000
Default admin credentials: admin / admin123
cd frontend
cp .env.example .env.local
# .env.local already points to http://localhost:5000/api
npm install
npm run dev
# Frontend runs at http://localhost:5173
Open http://localhost:5173 in your browser.
apipip install -r requirements.txtgunicorn app:appSECRET_KEY → any random stringFRONTEND_URL → your Netlify URL (set after step 2)https://your-app.onrender.comnetlify.toml. Build settings:
frontendnpm install && npm run buildfrontend/distVITE_API_URL → https://your-app.onrender.com/apiGo back to Render → your API service → Environment:
FRONTEND_URL to your actual Netlify URL (e.g. https://civil-registrar.netlify.app)frontend/.env.local)| Variable | Description | Example |
|—|—|—|
| VITE_API_URL | Full URL to Flask API /api | https://your-app.onrender.com/api |
| Variable | Description |
|—|—|
| SECRET_KEY | Flask secret key (random string) |
| FRONTEND_URL | Your Netlify site URL (for CORS) |
| DATABASE_URL | Optional — defaults to SQLite. Use PostgreSQL URL for production. |
| Path | Page |
|—|—|
| / | Landing page (services, announcements, achievements, contact) |
| /announcement/:id | Single announcement view |
| Path | Page |
|—|—|
| /admin/login | Login |
| /admin/dashboard | Dashboard with 5 charts + KPIs |
| /admin/transactions | Transaction list with filters |
| /admin/transactions/new | Create transaction |
| /admin/transactions/:id/edit | Edit transaction |
| /admin/services | Services list |
| /admin/services/new | Create service |
| /admin/services/:id/edit | Edit service |
| /admin/achievements | Achievements list |
| /admin/achievements/new | Create achievement |
| /admin/achievements/:id/edit | Edit achievement |
| /admin/announcements | Announcements list |
| /admin/announcements/new | Create announcement |
| /admin/announcements/:id/edit | Edit announcement |
| /admin/reports | Reports + CSV/PDF export |
POST /api/auth/login — { username, password }POST /api/auth/logoutGET /api/auth/meGET /api/transactions — supports ?q=&service_id=&status=&start_date=&end_date=POST /api/transactionsPUT /api/transactions/:idDELETE /api/transactions/:idGET /api/transactions/:id/qr — returns QR code PNGGET /api/servicesPOST /api/services (auth)PUT /api/services/:id (auth)DELETE /api/services/:id (auth)GET /api/announcements — supports ?active=1GET /api/announcements/:idPOST /api/announcements (auth, multipart)PUT /api/announcements/:id (auth, multipart)DELETE /api/announcements/:id (auth)GET /api/achievements — supports ?active=1POST /api/achievements (auth)PUT /api/achievements/:id (auth)DELETE /api/achievements/:id (auth)GET /api/reports/transactions — supports ?start=&end=GET /api/reports/transactions.csvGET /api/reports/transactions.pdfGET /api/reports/top-services.csv