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.md
Create a Google Sheet with the following tabs.
Tab name:
Members
Headers:
Member ID | Name | Email | Phone | Role | Joined Date | Status | Total Paid
Example:
uuid | name surname | abc@gmail.com | 9800000000 | admin | 2026年05月20日 | Active | 0
Tab name:
Contributions
Headers:
ID | Member Name | Month | Amount | Payment | Status | URL | Submitted_At | Approved_At | Approved_By | Remarks
Go to the backend folder:
cd apps/apiInstall dependencies using uv:
uv sync
Run the backend:
uv run uvicorn app.main:app --reload --port 8000
Backend URL:
http://localhost:8000
API base URL:
http://localhost:8000/api
FastAPI docs:
http://localhost:8000/docs
Go to the frontend folder:
cd apps/webInstall dependencies:
pnpm install
Run the frontend:
pnpm dev
Frontend URL:
http://localhost:3000
Create this file:
apps/api/.env
For local development, GOOGLE_SERVICE_ACCOUNT_FILE can point to a local JSON file.
Do not commit this file:
service-account.json
Create this file:
apps/web/.env.local
Example for local development:
NEXT_PUBLIC_API_URL=http://localhost:8000/api NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.com
Example 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.com
Go to:
Google Cloud Console → APIs & Services → Credentials
Create 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.com
Do not add paths.
Correct:
https://your-custom-domain.com
Wrong:
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.com
Give 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.