A comprehensive backend API for managing volunteers, chapters, nonprofits, projects, and sponsors with both REST and GraphQL endpoints.
- Language - TypeScript
- Framework - Express.js
- Database - PostgreSQL (hosted on Supabase)
- ORM - Prisma
- API Types - REST & GraphQL
- Testing - Jest & Supertest
- Code Quality - ESLint, Prettier, Husky
- CI/CD - GitHub Actions
src/
├── api/
│ ├── rest/ # REST API endpoints
│ └── graphql/ # GraphQL schema and resolvers
├── core/
│ ├── services/ # Business logic
│ └── validators/ # Input validation
├── config/ # Database and server configuration
├── middleware/ # Logging, security, and errors
└── app.ts # Main application entry point
tests/
├── unit/ # Unit tests
└── integration/ # Integration tests
prisma/
├── schema.prisma # Database schema
└── migrations/ # Database migrationsnpm installCreate a .env file in the root directory and copy fields from .env.example:
# Database Configuration
DATABASE_URL=your_database_url_here
DIRECT_URL=your_direct_url_here
# Server Configuration
PORT=3000
REST_PORT=3001
GRAPHQL_PORT=3002npx prisma db pull # Sync schema with database
npx prisma generate # Generate Prisma client# Start integrated server (both REST & GraphQL)
npm run dev
# Or start servers separately
npm run dev:rest # REST API only
npm run dev:graphql # GraphQL API only
npm run dev:both # Both servers concurrentlyThe servers will be available at:
- Integrated: http://localhost:3001
- REST API: http://localhost:3002
- GraphQL API: http://localhost:3003
npm run test # Run all tests (Unit & Integration)
npm run test:coverage # Generate coverage report for Unit tests only
npm run test:integration # Integration tests only
npm run test:unit # Unit tests only
npm run test:watch # Watch mode for unit testsThe database includes the following main entities:
- chapters - Local H4I chapters
- companies - Companies associated with volunteers, sponsors, & nonprofits
- contacts - Contact information
- locations - Geographic locations
- operations_branches - H4I Branches of the Operations Board
- nonprofits - Partner nonprofit organizations
- roles - All existing roles within the organization
- projects - Development projects for nonprofits
- sponsors - Corporate sponsors
- volunteers - Student and professional volunteers
The database includes the following main relationship tables:
- nonprofit_chapter_project
- sponsor_chapter
- volunteer_assignment
- volunteer_history
- volunteer_role_project
- DO NOT edit
schema.prismadirectly in production - Use Supabase Table Editor for schema changes in production
- Always run
npx prisma db pullandnpx prisma generateafter database changes - This ensures code stays synchronized with the database
Follow the pattern: feature/issue-number-description
- Example:
feature/1-add-volunteer-endpoints - This automatically links branches to GitHub issues
GraphQL endpoint available at /api/graphql with interactive playground.
Example mutation:
mutation {
addVolunteer(
volunteer: {
first_name: "Jane"
last_name: "Doe"
email: "[email protected]"
graduation_date: "2026-06-18"
volunteer_status: STUDENT
H4I_email: "[email protected]"
volunteer_type: CHAPTER
university_id: "860b69b4-a14e-41d9-a367-2632b342e549"
}
)
}More examples available in docs/examples/graphql-examples.md
REST endpoints available at /api/rest following RESTful conventions.
See docs/api/rest-api.md and docs/api/graphql-api.md for complete API documentation.
-
Service Layer (
src/core/services/)- Create business logic functions
- Use async/await pattern
- Implement proper error handling with try/catch
- Follow existing naming conventions
- Use function declarations and not arrow functions
-
GraphQL (
src/api/graphql/)- Add schema definitions in
schemas/ - Implement resolvers in
resolvers/ - Export from respective index files
- Update
graphql/resolvers.tsandgraphql/schemas.tsafter schema and resolver implementations
- Add schema definitions in
-
REST (
src/api/rest/)- Add controllers in
controllers/ - Define routes in
routes/ - Export from respective index files
- Apply validation using Zod validators from
core/validators - Add route in
rest/routes.ts
- Add controllers in
- Mock services before importing in tests
- Use
describe()blocks for organizing related tests - Write async test functions
- Follow AAA pattern: Arrange, Act, Assert
- Integration tests should be completely self-contained - each test creates its own data and doesn't depend on other tests
- Examples available in
tests/directory