* Add dev/demo login selector for quick user switching When AUTH_DISABLED=true, the app now shows a login selector page that lists staff members and clients from the database. Selecting a user sets a localStorage-based session and sends X-Dev-User-Id header on all API requests. A persistent bottom bar shows the active persona with a "Switch user" link. - API: /api/dev/config (public) and /api/dev/users (auth-disabled only) - API: auth middleware reads X-Dev-User-Id header when auth is disabled - Frontend: DevLoginSelector page, DevSessionIndicator bar - Frontend: fetch interceptor injects X-Dev-User-Id on /api/* calls - Tests: 7 passing (5 nav + 2 dev login) Closes #60 Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix(e2e): seed dev user in localStorage to prevent login redirect E2E tests were failing because the dev login selector redirects to /login when AUTH_DISABLED=true and no dev user is in localStorage. Added a shared Playwright fixture that pre-seeds localStorage with a default dev user before each test. Also rebased onto latest main to resolve merge conflict in App.test.tsx. Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix(e2e): mock /api/dev/config to bypass auth redirect in tests The fixture now also mocks /api/dev/config to return authDisabled: false, preventing the app from entering the redirect flow during E2E tests. Previously only seeded localStorage, but the async config fetch from the real Docker API was still triggering the redirect check. Co-Authored-By: Paperclip <noreply@paperclip.ing> --------- Co-authored-by: Groom Book CTO <cto@groombook.app> Co-authored-by: Paperclip <noreply@paperclip.ing>
Groom Book
Open source, self-hostable pet grooming business management and customer relationship platform.
Features
- Appointment scheduling — calendar management for single or multiple groomers
- Client & pet records — detailed profiles with grooming history and preferences
- Service management — pricing, duration, and service catalog
- Online booking portal — customer-facing self-service booking
- POS & invoicing — payments, tips, and receipt generation
- Automated reminders — SMS and email notifications
- Reporting dashboard — revenue, utilization, and trend analytics
- PWA — installable on mobile devices, works offline
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Hono (TypeScript, Node.js) |
| Frontend | React 19 + Vite + vite-plugin-pwa |
| Database | PostgreSQL via CNPG + Drizzle ORM |
| Auth | OIDC via Authentik |
| Infra | Kubernetes (namespace: groombook), Flux GitOps |
| CI | GitHub Actions (self-hosted groombook-runners) |
Repository Structure
groombook/
├── apps/
│ ├── api/ # Hono REST API
│ └── web/ # React PWA
├── packages/
│ ├── db/ # Drizzle schema + migrations
│ └── types/ # Shared TypeScript types
├── .github/
│ └── workflows/ # CI/CD pipelines
└── docker-compose.yml
Getting Started
Prerequisites
- Node.js >= 20
- pnpm >= 9 (
npm install -g pnpm) - Docker & Docker Compose (for local Postgres)
Local Development
# Clone the repo
git clone https://github.com/groombook/groombook.git
cd groombook
# Install dependencies
pnpm install
# Start local Postgres
docker compose up postgres -d
# Run database migrations
DATABASE_URL=postgres://groombook:groombook@localhost:5432/groombook pnpm db:migrate
# Start API and Web in parallel
pnpm dev
API will be available at http://localhost:3000 Web will be available at http://localhost:5173
Environment Variables
API (apps/api/.env)
DATABASE_URL=postgres://groombook:groombook@localhost:5432/groombook
OIDC_ISSUER=https://authentik.example.com
OIDC_AUDIENCE=groombook
CORS_ORIGIN=http://localhost:5173
PORT=3000
Running Tests
# Unit tests (vitest)
pnpm test
# E2E tests (Playwright) — requires the full Docker Compose stack to be running
docker compose up -d --wait
pnpm --filter @groombook/e2e test
# Open the Playwright UI (interactive test runner)
pnpm --filter @groombook/e2e test:ui
# View the last E2E test report
pnpm --filter @groombook/e2e test:report
E2E tests target the Docker Compose stack (http://localhost:8080). They use API route mocking where needed so happy-path tests are deterministic without requiring seed data.
Building
pnpm build
Self-Hosting
Docker Compose (recommended for single-server deployments)
The fastest way to run Groom Book is with Docker Compose. This starts PostgreSQL, runs database migrations, and serves both the API and web frontend.
git clone https://github.com/groombook/groombook.git
cd groombook
# Start everything (Postgres + migrate + API + web)
docker compose up --build
- Web UI: http://localhost:8080
- API: http://localhost:3000
The default docker-compose.yml sets AUTH_DISABLED=true so you can explore the app without configuring an OIDC provider. Disable this in any internet-facing deployment.
Production configuration
Copy .env.example to .env and configure:
cp .env.example .env
Key variables to update for production:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
AUTH_DISABLED |
Set to false in production |
OIDC_ISSUER |
Authentik issuer URL |
OIDC_AUDIENCE |
OAuth2 audience (default: groombook) |
CORS_ORIGIN |
Public URL of the web frontend |
To use your .env file with Docker Compose:
docker compose --env-file .env up --build
Kubernetes (production-grade deployments)
See the groombook/infra repository for Kubernetes manifests and Flux configuration.
Groom Book is deployed in the groombook Kubernetes namespace using:
- CNPG for PostgreSQL
- Authentik for OIDC authentication
- Flux for GitOps-managed deployments
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes
- Open a pull request
All PRs require CI to pass before merge.
License
MIT