Welcome to the String Bingo development guide! This document provides comprehensive information for developers working on the String-sg/bingo-string project.
- Project Overview
- Architecture
- Prerequisites
- Initial Setup
- Frontend Development
- Backend Development
- Database Management
- Environment Configuration
- Development Workflow
- Building and Deployment
- Testing
- Contributing Guidelines
- Common Issues and Troubleshooting
- Project Structure
String Bingo is an interactive web-based bingo game developed for the String community. Users can play pre-configured bingo games or create their own custom bingo boards with personalized challenges.
Key Features:
- Interactive 3x3 and 5x5 bingo grids with customizable challenges
- Google OAuth authentication for game creation and saving
- Mobile-responsive design with touch support
- Camera integration for photo challenges
- Image download functionality
- Public and private game modes
- Session tracking and progress saving
Tech Stack:
- Frontend: Vanilla JavaScript, Vite, HTML5, CSS3
- Backend: Express.js, TypeScript, Prisma ORM
- Database: PostgreSQL (NeonDB)
- Authentication: Google OAuth 2.0
- Deployment: Vercel (Frontend + Serverless Functions), GitHub Pages (Static Assets)
The project follows a client-server architecture:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Frontend │────────▶│ Backend API │────────▶│ Database │
│ (Vite) │◀────────│ (Express + TS) │◀────────│ (PostgreSQL)│
└─────────────────┘ └──────────────────┘ └─────────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Static Assets │ │ Serverless API │
│ (GitHub Pages) │ │ (Vercel) │
└─────────────────┘ └──────────────────┘
- app.js: Main application controller
- bingoGrid.js: Bingo grid rendering and state management
- authManager.js: Google OAuth authentication handling
- challengeLoader.js: Challenge data loading and management
- cameraManager.js: Camera integration for photo challenges
- modalManager.js: Modal dialog management
- touchManager.js: Mobile touch and zoom interactions
- game-creation.js: Custom game creation interface
- API Routes: RESTful endpoints for games, authentication, and sessions
- Middleware: Authentication, CORS, security headers, error handling
- Prisma ORM: Database schema and query management
- Google OAuth: Token validation and user authentication
Before you begin, ensure you have the following installed:
- Node.js: v18.x or higher
- npm: v9.x or higher
- Git: Latest version
- PostgreSQL: v15.x or higher (or NeonDB account)
- Google Cloud Console Access: For OAuth credentials
git clone https://github.com/String-sg/bingo-string.git
cd bingo-string# Install root dependencies
npm install
# Install backend dependencies
cd backend
npm install
cd ..- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Google Identity Services API
- Create OAuth 2.0 credentials:
- Application type: Web application
- Authorized JavaScript origins:
http://localhost:5173,https://bingo.string.sg - Authorized redirect URIs:
http://localhost:5173,https://bingo.string.sg
- Copy the Client ID for environment configuration
Create .env files based on the examples:
Root .env (Frontend):
cp .env.example .envEdit .env:
VITE_GOOGLE_CLIENT_ID=your_google_client_id_here
VITE_API_BASE_URL=http://localhost:3000/apiBackend .env:
cd backend
cp .env.example .envEdit backend/.env:
DATABASE_URL="postgresql://username:password@localhost:5432/bingo_db?sslmode=require"
GOOGLE_CLIENT_ID=your_google_client_id_here
PORT=3000
NODE_ENV=development
CORS_ORIGINS="http://localhost:5173,https://bingo.string.sg"Note: For local PostgreSQL development, you may need to adjust the sslmode parameter. Use sslmode=disable or omit it entirely if your local PostgreSQL instance doesn't have SSL configured.
cd backend
# Generate Prisma client
npm run prisma:generate
# Run database migrations
npm run prisma:migrate
# (Optional) Open Prisma Studio to view your database
npm run prisma:studio# From the project root
npm run devThis starts the Vite development server at http://localhost:5173 with:
- Hot Module Replacement (HMR)
- API proxy to backend at
/api/* - Fast builds and updates
├── index.html # Main game page
├── new.html # Game creation page
├── js/ # JavaScript modules
│ ├── app.js # Main app controller
│ ├── bingoGrid.js # Grid management
│ ├── authManager.js # Authentication
│ └── ...
├── styles/ # CSS stylesheets
└── public/ # Static assets
├── challenges.csv # Default challenges
└── config-*.json # Environment configs
- Create or modify JavaScript modules in
js/ - Update HTML templates if needed
- Add CSS styles in
styles/ - Test in browser at
http://localhost:5173
The bingo grid is managed by bingoGrid.js and coordinated by app.js:
- Grid completion state is held in memory, while captured images are stored in
localStorage - Capturing an image marks a cell complete and posts progress to the backend
- Clicking an incomplete cell opens the camera/upload flow; removing its image marks it incomplete
- Win detection checks rows, columns, and diagonals for bingo patterns
Based on issue #58, the app includes:
- Touch support for mobile devices
- Pinch-to-zoom functionality
- Scroll and pan capabilities
- Future Enhancement: Re-center button to return to original layout after zooming/panning
npm run buildThis creates an optimized production build in the dist/ directory.
cd backend
npm run devThis starts the Express server at http://localhost:3000 with:
- Auto-reload on file changes (via tsx watch)
- CORS enabled for frontend origin
- Morgan logging for requests
backend/
├── src/
│ ├── index.ts # Main server entry point
│ ├── routes/ # API route handlers
│ │ ├── auth.ts # Authentication endpoints
│ │ ├── games.ts # Game and custom-session operations
│ │ └── defaultSessions.ts # Default-game session operations
│ ├── middleware/
│ │ └── auth.ts # Google token validation
│ └── lib/
│ └── prisma.ts # Prisma client
├── prisma/
│ ├── schema.prisma # Database schema
│ └── migrations/ # Migration files
└── package.json
POST /api/auth/login- Login with Google ID tokenGET /api/auth/me- Get current user infoPOST /api/auth/logout- Logout (for analytics)
GET /api/games- List user's games (authenticated)POST /api/games- Create new game (authenticated)GET /api/games/:id- Get specific gamePUT /api/games/:id- Update game (owner only)DELETE /api/games/:id- Delete game (owner only)GET /api/games/:id/play- Get game for playing (public)
POST /api/games/:id/join- Create or resume a custom-game sessionPOST /api/games/:id/progress- Update custom-game session progressGET /api/games/:id/results- Get game results (authenticated owner only)
POST /api/default-sessions- Create or resume a default-game sessionPOST /api/default-sessions/:sessionId/progress- Update default-game progressGET /api/default-sessions/:sessionId- Get a default-game session
GET /health- Server health status
- Create or modify route files in
src/routes/ - Add middleware if needed in
src/middleware/ - Update type definitions in TypeScript files
- Test endpoints using curl or Postman
- Update API documentation in
backend/README.md
cd backend
npm run buildThis compiles TypeScript to JavaScript in dist/.
The database includes four main tables:
- Stores user information from Google OAuth
- Unique constraints on email and googleId
- Stores custom bingo games created by users
- Stores challenges as JSON together with the selected grid size
- Has a public/private visibility flag
- Tracks custom-game sessions by game, session ID, and player name
- Stores progress as JSON
- Tracks anonymous sessions for pre-configured challenge sets
- Stores grid size and progress as JSON
cd backend
npm run prisma:studiocd backend
# Make changes to prisma/schema.prisma first
npm run prisma:migratecd backend
npx prisma migrate resetcd backend
npx prisma db seed- Root
.env: Frontend environment variables (prefixed withVITE_) backend/.env: Backend environment variables.env.example: Template with all required variables
public/config-production.json: Production frontend configpublic/config-staging.json: Staging frontend configvite.config.js: Vite build configurationvercel.json: Vercel deployment configuration
For local development:
VITE_API_BASE_URL=http://localhost:3000/apiFor staging and production, update the runtime configuration files rather than a Vite environment variable:
- Set
apiBaseUrlinpublic/config-staging.jsonto the deployed staging API URL. - Set
apiBaseUrlinpublic/config-production.jsonto the deployed production API URL (currently/api).
VITE_API_BASE_URL is used only for local development.
-
Start Services
# Terminal 1: Frontend npm run dev # Terminal 2: Backend cd backend && npm run dev
-
Make Changes
- Edit code in your preferred editor
- Changes auto-reload in browser (frontend)
- Server auto-restarts (backend)
-
Test Changes
- Test in browser at
http://localhost:5173 - Verify API calls work correctly
- Check mobile responsiveness
- Test in browser at
-
Commit Changes
git add . git commit -m "Description of changes" git push origin your-branch-name
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make commits with clear messages:
git commit -m "feat: add re-center button for mobile zoom (fixes #58)" -
Push and create a pull request:
git push origin feature/your-feature-name
- JavaScript: Use ES6+ features and consistent indentation (4 spaces)
- TypeScript: Use strict mode, define types for parameters and return values
- CSS: Use BEM naming convention where applicable
- Commits: Use conventional commit messages (feat:, fix:, docs:, etc.)
The frontend is automatically deployed to GitHub Pages when pushing to main or staging branches.
Workflow: .github/workflows/deploy.yml
- Builds the project with Vite
- Deploys to GitHub Pages
- Sets up custom domain (bingo.string.sg or staging.bingo.string.sg)
Manual Deployment:
npm run build
npm run deployThe backend API is deployed as Vercel serverless functions.
Requirements:
- Set environment variables in Vercel dashboard
- Ensure DATABASE_URL points to production database
- Configure CORS_ORIGINS for production domains
Files:
vercel.json: Vercel configurationapi/index.ts: Serverless function entry point
The GitHub Pages workflow deploys pushes from both main and staging to the same gh-pages target with force_orphan: true, so only the most recently deployed branch is active.
stagingdeployments publish the frontend with thestaging.bingo.string.sgCNAMEmaindeployments publish the frontend with thebingo.string.sgCNAME- Each new deployment replaces the previously published branch content and domain mapping
Since the project doesn't have automated tests currently, focus on manual testing:
-
Authentication Flow
- Test Google login
- Verify user session persistence
- Test logout functionality
-
Game Creation
- Create a new custom game
- Verify challenges are saved correctly
- Test public/private visibility
-
Game Playing
- Load default game
- Load custom game
- Click cells to mark completion
- Verify bingo detection
- Test image upload for challenges
-
Mobile Testing
- Test on various device sizes
- Verify touch interactions
- Test pinch-to-zoom (issue #58)
- Verify button layouts (issue #59)
-
Cross-Browser Testing
- Chrome/Edge
- Firefox
- Safari
- Mobile browsers
Consider adding:
- Unit tests with Vitest (recommended for Vite projects due to shared configuration and faster test execution) or Jest
- Integration tests for API endpoints
- E2E tests with Playwright (already in dependencies)
- Automated visual regression tests
- Check existing issues for similar features/bugs
- Create an issue to discuss significant changes
- Fork the repository and create a feature branch
- Follow the code style guidelines
-
Ensure your code works:
- Test locally with both frontend and backend
- Verify mobile responsiveness
- Check browser compatibility
-
Update documentation:
- Update this file if adding new features
- Update README.md if changing setup process
- Add JSDoc comments to new functions
-
Create the PR:
- Write a clear title and description
- Reference related issues (e.g., "Fixes #58")
- Add screenshots for UI changes
- Request review from maintainers
-
Address feedback:
- Respond to review comments
- Make requested changes
- Push updates to the same branch
When working on issues, use these formats:
Fixes #58- Closes the issue when PR is mergedRelates to #59- References without closingPart of #56- Indicates partial implementation
Example from current issues:
- Issue #58: Add re-center button for mobile zoom functionality
- Issue #59: Improve button layout (all buttons in same row)
- Issue #56: Enhanced analytics and tracking
- Issue #53: Better error monitoring and logging
Problem: Vite dev server won't start
# Solution: Clear cache and reinstall
rm -rf node_modules .vite
npm install
npm run devProblem: Google OAuth not working
- Verify
VITE_GOOGLE_CLIENT_IDis set correctly - Check authorized origins in Google Cloud Console
- Ensure you're using HTTPS in production
Problem: API calls failing
- Verify backend is running on port 3000
- Check
VITE_API_BASE_URLin.env - Inspect network tab for error details
Problem: Backend won't start
# Solution: Check for port conflicts and env vars
lsof -i :3000 # Check if port 3000 is in use
cd backend && cat .env # Verify env vars are setProblem: Database connection failed
- Verify
DATABASE_URLis correct - Check database server is running
- Test connection with
npx prisma studio
Problem: Prisma errors
# Solution: Regenerate Prisma client
cd backend
npm run prisma:generateProblem: CORS errors
- Check
CORS_ORIGINSin backend.env - Verify frontend URL matches allowed origin
- Clear browser cache
Problem: Migrations out of sync
cd backend
npx prisma migrate reset # WARNING: Deletes all data
npm run prisma:migrateProblem: Prisma Client outdated
cd backend
npm run prisma:generateProblem: Build fails with TypeScript errors
cd backend
npm run build # Check for type errors
# Fix type errors in source filesProblem: Vite build fails
# Check for missing dependencies or import errors
npm run build
# Review error output and fix issuesProblem: Vercel deployment fails
- Check build logs in Vercel dashboard
- Verify all environment variables are set
- Ensure
vercel.jsonis properly configured
Problem: GitHub Pages shows 404
- Verify GitHub Pages is enabled for the branch
- Check CNAME file is present in
dist/ - Ensure base path in
vite.config.jsis correct
bingo-string/
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions deployment
├── api/
│ └── index.ts # Vercel serverless API entry
├── backend/
│ ├── src/
│ │ ├── index.ts # Backend server entry
│ │ ├── routes/ # API routes
│ │ ├── middleware/ # Express middleware
│ │ └── lib/ # Utilities
│ ├── prisma/
│ │ ├── schema.prisma # Database schema
│ │ └── migrations/ # Database migrations
│ ├── package.json
│ └── tsconfig.json
├── js/
│ ├── app.js # Main app logic
│ ├── bingoGrid.js # Grid management
│ ├── authManager.js # Authentication
│ ├── challengeLoader.js # Challenge loading
│ ├── cameraManager.js # Camera integration
│ ├── modalManager.js # Modal dialogs
│ ├── touchManager.js # Touch handling
│ └── game-creation.js # Game creation UI
├── styles/ # CSS stylesheets
├── public/ # Static assets
│ ├── challenges.csv # Default challenges
│ ├── config-*.json # Config files
│ └── *.csv # Sample challenge files
├── index.html # Main game page
├── new.html # Game creation page
├── package.json # Root package config
├── vite.config.js # Vite configuration
├── vercel.json # Vercel configuration
├── .env.example # Environment template
├── .gitignore
├── README.md # Project overview
└── development.md # This file
- Report bugs and request features via GitHub Issues
- Contact maintainers: @KOKHC, @physicstjc
- Issue #58: Re-center button for mobile zoom
- Issue #59: Button layout improvements
- Issue #56: Enhanced analytics
- Issue #53: Better monitoring
Happy coding! 🎉
If you have questions or need help, don't hesitate to open an issue or reach out to the maintainers.