Event Attendance Management System
CredoPass is a comprehensive attendance tracking platform designed for organizations that meet regularly and need to track who actually shows up. Unlike ticketing systems like EventBrite that manage payments and ticket scanning, CredoPass focuses on detailed attendance trackingβcapturing check-in times, check-out times, and actual attendance data that ticketing platforms don't provide.
Perfect for churches, book clubs, jazz clubs, recurring meetups, and any organization that needs to:
- Track attendance without requiring tickets
- Work alongside existing event systems (EventBrite, Meetup, etc.)
- Integrate with existing member databases
- Capture detailed check-in/check-out times
- Generate attendance analytics and insights
- Features
- Technology Stack
- Project Structure
- Quick Start
- Development
- Key Files & Directories
- Documentation
- Project Status
- Attendance Tracking - Detailed check-in/check-out times and attendance records
- Member Management - Import and manage your existing member database
- Event Management - Create and schedule recurring or one-time events
- Integration Ready - Works alongside EventBrite, Meetup, and other event platforms
- No Tickets Required - Perfect for free events or paid events managed elsewhere
- Loyalty Program - Reward frequent attendees with points and tiers
- Analytics Dashboard - Attendance trends, no-show rates, and engagement metrics
- Offline-First - Local data sync for check-ins even without internet
- Responsive Design - Mobile-friendly for on-site check-in tablets or phones
- Framework: React 19.2.1 (with React Compiler optimization)
- Build Tool: Vite 7.3.0 (Rolldown variant)
- Routing: TanStack Router v1.140.5 (file-based routing)
- State Management:
- Zustand v5.0.9 (global state)
- TanStack Query v5.90.12 (server state)
- TanStack DB v0.1.60 (offline-first local collections)
- UI Components: shadcn/ui with Base UI React v1.0.0
- Styling: TailwindCSS v4.1.18
- Data Visualization:
- AG Grid Community v35.0.0 (data tables)
- FullCalendar v6.1.19 (calendar views)
- Recharts 3.6.0 (charts & analytics)
- Icons: Lucide React v0.562.0
- Layout: React Grid Layout v2.0.0
- Runtime: Bun >= 1.3.0
- Framework: Hono v4.10.7 (lightweight web framework)
- Database: PostgreSQL 16 (production) / PGlite (development fallback)
- ORM: Drizzle ORM v0.45.1 with Drizzle Kit v0.31.0
- Validation: Zod v4.3.5 with @hono/zod-validator
- Environment: t3-env v3.10.0
- Monorepo Manager: Nx v22.3.3
- Package Manager: Bun (with workspaces)
- Linting: ESLint v9.39.2 with TypeScript ESLint
- TypeScript: v5.9.3
- Frontend: Vercel (with API proxy rewrites)
- Backend: Google Cloud Run (Docker containers)
- Database: PostgreSQL 16 (Docker Compose for local development)
credopass-monorepo/
βββ apps/
β βββ web/ # React web application (Vercel)
β βββ src/
β β βββ main.tsx # App entry point (TanStack Router)
β β βββ routes.tsx # Route tree configuration
β β βββ config.ts # App configuration
β β βββ components/ # Reusable React components
β β βββ containers/ # Feature containers (EventForm, TopNavBar, etc.)
β β βββ Pages/ # Page components (Home, Members, Events, Analytics)
β β βββ routes/ # Route definitions
β β βββ stores/ # Zustand stores (useAppStore, useLauncherStore)
β β βββ lib/
β β β βββ utils.ts # Utility functions
β β β βββ tanstack-db/ # TanStack DB collections (users, events, etc.)
β β βββ hooks/ # Custom React hooks
β βββ public/ # Static assets
β βββ index.html # HTML template
β βββ vite.config.ts # Vite configuration (proxy, build)
β βββ vercel.json # Vercel deployment config
β βββ tsconfig.json # TypeScript config
β βββ project.json # Nx project configuration
β
βββ services/
β βββ core/ # Hono API server (Google Cloud Run)
β βββ src/
β β βββ index.ts # Server entry (Hono + middleware)
β β βββ routes/ # API route handlers
β β β βββ users.ts # User CRUD endpoints
β β β βββ events.ts # Event management endpoints
β β β βββ attendance.ts # Attendance tracking endpoints
β β β βββ loyalty.ts # Loyalty program endpoints
β β βββ api/ # API client (type-safe fetch wrapper)
β β β βββ client.ts # Base API client
β β β βββ endpoints/ # Endpoint definitions
β β βββ db/ # Database layer
β β βββ client.ts # DB client (PostgreSQL auto-detect)
β β βββ index.ts # DB exports
β β βββ seed.ts # Database seeding script
β βββ drizzle/ # Database migrations
β βββ Dockerfile # Multi-stage Docker build
β βββ drizzle.config.ts # Drizzle Kit configuration (points to @credopass/lib schemas)
β βββ tsconfig.json # TypeScript config
β βββ project.json # Nx project configuration
β
βββ packages/
β βββ lib/ # Shared utilities & validation (@credopass/lib)
β β βββ src/
β β β βββ schemas/ # Single source of truth for schemas
β β β β βββ tables/ # Drizzle table definitions
β β β β β βββ users.ts # Users table schema
β β β β β βββ events.ts # Events table schema
β β β β β βββ attendance.ts # Attendance table schema
β β β β β βββ loyalty.ts # Loyalty table schema
β β β β β βββ index.ts # Table exports with relations
β β β β βββ user.schema.ts # Zod schemas generated from Drizzle (Create, Update, Insert)
β β β β βββ event.schema.ts # Event validation schemas (drizzle-zod)
β β β β βββ attendance.schema.ts # Attendance validation schemas
β β β β βββ loyalty.schema.ts # Loyalty validation schemas
β β β β βββ enums.ts # Shared Zod enums
β β β β βββ index.ts # Barrel exports (tables + schemas)
β β β βββ hooks/ # Shared React hooks
β β β β βββ use-cookies.ts
β β β βββ util/ # Utility functions
β β β βββ grid-layout.tsx # React Grid Layout wrapper (shared component)
β β β βββ constants.ts # App constants
β β β βββ index.ts # Package exports
β β βββ tsconfig.json
β β βββ project.json
β β
β βββ ui/ # Shared UI components (@credopass/ui)
β βββ src/
β β βββ components/ # shadcn/ui components
β β β βββ button.tsx
β β β βββ card.tsx
β β β βββ dialog.tsx
β β β βββ input.tsx
β β β βββ select.tsx
β β β βββ chart.tsx # Recharts integration
β β β βββ sidebar.tsx
β β β βββ index.ts # Component exports
β β βββ hooks/ # UI-specific hooks
β β β βββ use-mobile.ts
β β βββ lib/
β β β βββ utils.ts # cn() helper, etc.
β β βββ styles/
β β βββ globals.css # Global styles
β βββ components.json # shadcn/ui config
β βββ tailwind.config.ts # Tailwind configuration
β βββ tsconfig.json
β βββ project.json
β
βββ docker/
β βββ docker-compose.yml # PostgreSQL 16 container setup
β
βββ tools/ # DevOps scripts
β βββ nm-reset.sh # Node modules cleanup
β βββ setup-gcp.sh # Google Cloud Platform setup
β βββ setup-vercel.sh # Vercel setup
β
βββ nx.json # Nx workspace configuration
βββ package.json # Root dependencies & scripts
βββ tsconfig.base.json # Base TypeScript configuration
βββ eslint.config.js # ESLint configuration
βββ ARCHITECTURE.md # Legacy architecture docs
βββ REFACTORING_SUMMARY.md # Consolidation notes
βββ README.md # This file
- Bun >= 1.3.0 (Install Bun)
- Docker (for PostgreSQL)
- Google Cloud SDK (for deployment)
# Clone repository
git clone <repository-url>
cd credopass
# Install dependencies
bun install
# Start PostgreSQL database
bun run postgres:up
# Run database migrations
nx run coreservice:migrate
# Start development servers (in separate terminals)
# Terminal 1: Frontend (http://localhost:5173)
nx run web:serve
# Terminal 2: Backend (http://localhost:3000)
nx run coreservice:startCreate a .env file in the root:
# Database
DATABASE_URL=postgresql://postgres:Ax!rtrysoph123@localhost:5432/credopass_db
# API Configuration
API_BASE_URL=http://localhost:3000
NODE_ENV=development
# Optional: Enable throttle middleware for testing
THROTTLE=falseSee docs/SETUP.md for detailed setup instructions
# Frontend Development
nx run web:serve # Start dev server (localhost:5173)
nx run web:build # Production build
nx run web:preview # Preview production build
# Backend Development
nx run coreservice:start # Start API server (localhost:3000)
nx run coreservice:build # Bundle with Bun
nx run coreservice:docker:build # Build Docker image
# Database
bun run postgres:up # Start PostgreSQL container
bun run postgres:down # Stop and remove PostgreSQL
nx run coreservice:generate # Generate migration from schema changes
nx run coreservice:migrate # Run pending migrations
nx run coreservice:studio # Open Drizzle Studio (DB UI)
# Monorepo
nx graph # View dependency graph
nx affected:test # Test affected projects
nx format:write # Format code- Frontend Changes: Edit files in
apps/web/src/β Hot reload on save - Backend Changes: Edit files in
services/core/src/β Auto-restart with--watch - Schema Changes: Edit
packages/lib/src/schemas/tables/β Runnx run coreservice:generateβ Runnx run coreservice:migrate - UI Components: Edit
packages/ui/src/components/β Changes reflect in web app - Validation Schemas: Edit
packages/lib/src/schemas/*.schema.tsβ Available in both frontend & backend (auto-generated from Drizzle tables)
Development Mode:
Frontend (localhost:5173) β Vite Proxy β Backend (localhost:3000)
- Configured in
apps/web/vite.config.ts - All
/api/*requests proxied tohttp://localhost:3000
Production Mode:
Frontend (vercel.app) β Vercel Rewrite β https://api.credopass.com/api/*
- Configured in
apps/web/vercel.json - API domain set via environment variables
| File/Directory | Purpose |
|---|---|
| Frontend | |
apps/web/src/main.tsx |
React app entry point with TanStack Router setup |
apps/web/src/routes.tsx |
Explicit route tree configuration |
apps/web/src/stores/store.ts |
Zustand stores (useAppStore, useLauncherStore) |
apps/web/src/lib/tanstack-db/ |
TanStack DB collections for offline-first data |
apps/web/src/Pages/ |
Page components (Home, Members, Events, Analytics, Tables) |
apps/web/src/containers/ |
Feature containers (EventForm, TopNavBar, SignInModal, etc.) |
apps/web/vite.config.ts |
Vite build config with proxy and code-splitting |
apps/web/vercel.json |
Vercel deployment with API rewrites & security headers |
| Backend | |
services/core/src/index.ts |
Hono server with CORS, logger, throttle middleware |
services/core/src/routes/ |
API route handlers (users, events, attendance, loyalty) |
services/core/src/db/client.ts |
Database client factory (PostgreSQL auto-detect) |
services/core/Dockerfile |
Multi-stage Docker build for Cloud Run |
services/core/drizzle.config.ts |
Drizzle migration configuration (points to lib schemas) |
| Shared Packages | |
packages/lib/src/schemas/tables/ |
Drizzle table definitions (single source of truth) |
packages/lib/src/schemas/*.schema.ts |
Zod validation schemas (auto-generated via drizzle-zod) |
packages/lib/src/constants.ts |
Application constants |
packages/ui/src/components/ |
shadcn/ui component library |
packages/ui/components.json |
shadcn/ui configuration |
| Infrastructure | |
docker/docker-compose.yml |
PostgreSQL 16 container definition |
nx.json |
Nx workspace configuration & task pipelines |
tsconfig.base.json |
Base TypeScript config with path mappings |
package.json |
Root workspace dependencies & scripts |
Comprehensive documentation is available in the /docs directory:
- Architecture Guide - Detailed architectural patterns, routing, state management, API patterns, validation layer
- Setup Guide - Complete setup instructions, environment variables, database configuration, troubleshooting
- Database Guide - Schema definitions, relationships, migrations, seeding data
- API Reference - Endpoint documentation, request/response examples
- Deployment Guide - Build processes, Vercel deployment, Docker & Cloud Run, production migrations
Current Phase: Post-Refactoring Development
The Gap: EventBrite and similar platforms handle ticket sales and scanning, but don't provide:
- Detailed attendance data (who actually showed up vs. who bought tickets)
- Check-in and check-out timestamps
- Attendance tracking for free/non-ticketed events
- Integration with your existing member database
The Solution: CredoPass fills this gap by focusing exclusively on attendance tracking. Use EventBrite for ticketing, use CredoPass for knowing who attended and when.
The project recently underwent schema consolidation to eliminate duplication and establish a single source of truth:
β Completed:
- Moved Drizzle table definitions from
services/core/src/db/schema/topackages/lib/src/schemas/tables/ - Integrated
drizzle-zodto auto-generate Zod validation schemas from Drizzle tables - Eliminated manual schema duplication (was maintaining 2 separate definitions per entity)
- Updated Zod version from v4.1.13 to v4.3.5 across all packages
- All routes now import schemas directly from
@credopass/lib/schemas - Drizzle config updated to use shared schema location
Benefits:
- No More Drift: Schema changes in one place automatically propagate to validation
- Less Code: Removed ~400 lines of duplicate schema definitions
- Type Safety: Drizzle tables generate both Zod schemas and TypeScript types
- Better DX: Add a field once, get DB schema + validation + types automatically
- Simpler Structure: Fewer packages = easier navigation
- Type Safety: End-to-end TypeScript with Zod validation
- Modern Stack: React 19, Hono, Drizzle, Bun, TanStack ecosystem
- Developer Experience: Fast builds (Bun), hot reload (Vite), excellent tooling (Nx, Drizzle Studio)
- Offline-First: TanStack DB collections for local data persistence
- Clean Separation: Clear boundaries between apps, services, and packages
-
Global UI State (Zustand):
useAppStore: Sidebar state, action eventsuseLauncherStore: Modal launcher state
-
Server State (TanStack Query):
- Automatic caching and invalidation
- Used implicitly by TanStack DB collections
-
Local-First Data (TanStack DB):
- Collections: users, events, attendance, loyalty
- Syncs with backend API via collections
- Enables offline functionality
User Interaction
β
React Component
β
TanStack Query/DB β API Client β Hono Server
β
Zod Validation
β
Drizzle ORM
β
PostgreSQL
Architecture:
- Drizzle Tables (
packages/lib/src/schemas/tables/): Database schema definitions (PostgreSQL) - Zod Schemas (
packages/lib/src/schemas/*.schema.ts): Auto-generated viadrizzle-zodwith custom refinements - Both exported from
@credopass/lib/schemasfor use across frontend and backend
Workflow:
- Edit Drizzle table definition in
packages/lib/src/schemas/tables/users.ts - Zod schemas in
packages/lib/src/schemas/user.schema.tsauto-update viadrizzle-zod - Generate migration:
nx run coreservice:generate - Apply migration:
nx run coreservice:migrate - TypeScript types and validation automatically available everywhere
Example:
// packages/lib/src/schemas/tables/users.ts (Source of Truth)
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull().unique(),
firstName: text('firstName').notNull(),
// ...
});
// packages/lib/src/schemas/user.schema.ts (Auto-generated + Refinements)
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
import { users } from './tables/users';
export const UserSchema = createSelectSchema(users);
export const CreateUserSchema = createInsertSchema(users, {
email: z.string().email(), // Custom refinement
firstName: z.string().min(1, 'Required'),
}).omit({ id: true, createdAt: true, updatedAt: true });The backend automatically detects the environment:
- Production: Uses PostgreSQL via
DATABASE_URL - Development Fallback: Uses PGlite if PostgreSQL unavailable
# Automatic deployment on push to main branch
# Or manual deployment:
vercel deployConfiguration: apps/web/vercel.json
# Deploy to Cloud Run
nx run coreservice:deploy
# Or manually:
cd services/core
gcloud run deploy credopass-api \
--source . \
--region us-central1 \
--allow-unauthenticatedSee docs/DEPLOYMENT.md for complete deployment instructions
See LICENSE file for details.
This is a private project. For questions or issues, contact the development team.
Built with β€οΈ for organizations that value attendance insights