KOSH Saving App is a cooperative monthly saving management system for managing members, monthly contributions, approvals, reports, and Google-based authentication.
The app uses a Next.js frontend, FastAPI backend, Google OAuth login, Google Sheets for data storage, and Google Drive for uploaded receipt/photo storage.
- Google Sign-In authentication
- Member management
- Monthly saving submission
- Receipt/photo upload support
- Admin approval and rejection flow
- Member-wise total paid tracking
- Monthly reports
- Protected dashboard routes
- Google Sheets data storage
- Google Drive file storage
- Next.js
- React
- TypeScript
- Tailwind CSS
- TanStack React Query
- Google OAuth
- FastAPI
- Python
- uv
- Google Sheets API
- Google Drive API
- JWT authentication
- Vercel for frontend
- Render for backend
- Google Sheets as the database
- Google Drive for receipt/photo storage
coop-saving-app/
├── apps/
│ ├── api/
│ │ ├── app/
│ │ │ ├── main.py
│ │ │ ├── routes/
│ │ │ ├── services/
│ │ │ └── core/
│ │ ├── pyproject.toml
│ │ └── uv.lock
│ │
│ └── web/
│ ├── app/
│ ├── components/
│ ├── lib/
│ ├── package.json
│ └── next.config.ts
│
├── .github/
│ └── workflows/
│ └── release.yml
│
└── README.mdCreate a Google Sheet with the following tabs.
Tab name:
MembersHeaders:
Member ID | Name | Email | Phone | Role | Joined Date | Status | Total PaidExample:
uuid | name surname | abc@gmail.com | 9800000000 | admin | 2026-05-20 | Active | 0Tab name:
ContributionsHeaders:
ID | Member Name | Month | Amount | Payment | Status | URL | Submitted_At | Approved_At | Approved_By | RemarksGo to the backend folder:
cd apps/apiInstall dependencies using uv:
uv syncRun the backend:
uv run uvicorn app.main:app --reload --port 8000Backend URL:
http://localhost:8000API base URL:
http://localhost:8000/apiFastAPI docs:
http://localhost:8000/docsGo to the frontend folder:
cd apps/webInstall dependencies:
pnpm installRun the frontend:
pnpm devFrontend URL:
http://localhost:3000Create this file:
apps/api/.envFor local development, GOOGLE_SERVICE_ACCOUNT_FILE can point to a local JSON file.
Do not commit this file:
service-account.jsonCreate this file:
apps/web/.env.localExample for local development:
NEXT_PUBLIC_API_URL=http://localhost:8000/api
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.comExample for production:
NEXT_PUBLIC_API_URL=https://your-render-backend-url.onrender.com/api
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.comGo to:
Google Cloud Console → APIs & Services → CredentialsCreate or open your OAuth Client ID.
Add these to Authorized JavaScript origins:
http://localhost:3000
https://your-vercel-domain.vercel.app
https://your-custom-domain.comDo not add paths.
Correct:
https://your-custom-domain.comWrong:
https://your-custom-domain.com/login- Create a Google Cloud service account.
- Enable the Google Sheets API.
- Enable the Google Drive API.
- Download the service account JSON file.
- Share your Google Sheet with the service account email.
- Share your Google Drive folder with the service account email.
The service account email looks like this:
something@project-id.iam.gserviceaccount.comGive the service account editor access to the Google Sheet and Google Drive folder.
- Never commit
.envfiles. - Never commit
service-account.json. - Store secrets in Render environment variables.
- Store frontend public variables only in Vercel.
- Google service account JSON belongs only on the backend.
- JWT secret belongs only on the backend.
Private project for KOSH Saving members.