Commit Graph

40 Commits

Author SHA1 Message Date
Groom Book CTO eb4ae11ce4 fix(packages): reorder exports conditions to prevent Node.js .ts resolution
Node.js v20.20.1 is matching the `types` export condition before `default`,
causing ERR_UNKNOWN_FILE_EXTENSION when it tries to load .ts source files
at runtime. Moving `default` before `types` ensures Node.js resolves to
the compiled .js output first. TypeScript explicitly seeks the `types`
condition regardless of key order, so TS resolution is unaffected.

Fixes the API container CrashLoopBackOff in the groombook namespace.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 19:44:24 +00:00
groombook-paperclip[bot] 21c0a7b59c fix(reports): fix churn query crash and improve error reporting (#51)
The /api/reports/clients endpoint was crashing with a 500 on every request
because a raw JavaScript Date passed into a sql template literal in .having()
cannot be serialized by postgres-js. The fix serializes it as an ISO string
with an explicit ::timestamptz cast.

Also adds reportsRouter.onError() and improves the frontend error message
to surface which specific endpoint failed and why.

Fixes #49
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 13:36:31 +00:00
groombook-paperclip[bot] 639429d73d Fix reports crash: serialize Date as ISO string in churn risk query (#50)
The /api/reports/clients endpoint crashes with a 500 because
Drizzle's sql template literal in a HAVING clause cannot serialize
a JavaScript Date object — the postgres driver expects a string.

Convert the Date to an ISO string and add an explicit ::timestamptz
cast so PostgreSQL handles the comparison correctly.

Closes groombook/groombook#49

Co-authored-by: Groom Book CEO <ceo@groombook.dev>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 13:26:25 +00:00
groombook-paperclip[bot] e546a73496 Add Renovate configuration for automated dependency updates (#48)
Co-authored-by: groombook-paperclip[bot] <268890960+groombook-paperclip[bot]@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-18 11:47:32 +00:00
groombook-paperclip[bot] 37da0b7490 Fix Dockerfile layer order: copy dist before pnpm install (#45)
pnpm install --prod creates workspace symlinks (node_modules/@groombook/db
→ packages/db/), but dist/ files didn't exist yet, causing Node.js to fall
back to resolving .ts source files at runtime (ERR_UNKNOWN_FILE_EXTENSION).

Copy compiled dist files and updated package.json from the builder stage
before running pnpm install so symlinks point to existing dist output.

Co-authored-by: Groom Book CEO <ceo@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-18 03:44:39 +00:00
groombook-paperclip[bot] 4cf94678d4 fix(e2e): mock reports endpoints with shaped responses in navigation tests (#47)
The Reports page expects structured objects from the API (e.g. summary
with nested revenue/appointments fields, revenue with byPeriod/byGroomer,
etc.). Returning a bare [] caused runtime errors when the component
accessed properties like apptData.byPeriod, crashing the React tree and
making "Groom Book" disappear from the DOM on retries.

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-18 03:26:53 +00:00
groombook-paperclip[bot] 01c0e480ac Fix API crash: add exports field and clean runtime image (#44)
The API Docker image was crashing because Node.js ESM resolution
was finding TypeScript source files instead of compiled JS output.
Added explicit exports fields to workspace packages for deterministic
resolution and a cleanup step in the Dockerfile runner stage.

Co-authored-by: Groom Book CEO <ceo@groombook.dev>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-18 03:13:47 +00:00
groombook-paperclip[bot] d0e10b4cfe Merge pull request #43 from groombook/feat/playwright-e2e
Add Playwright E2E testing
2026-03-18 02:52:59 +00:00
Groom Book CTO c957ee2504 fix(e2e): fix strict mode violation in clients detail test
After clicking a client, their email appears in both the list row and
the detail panel — causing a strict-mode violation with toBeVisible().
Use toHaveCount(2) instead to assert the detail panel is open.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 02:50:17 +00:00
Groom Book CTO aa3b080c05 fix: exclude e2e workspace from root pnpm test command
The root `pnpm test` runs across all workspaces. The apps/e2e workspace
requires Playwright browsers to be installed before tests can run, but
the unit-test CI job does not install them. Exclude @groombook/e2e from
the root test command so E2E tests only run in the dedicated e2e CI job.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 02:44:04 +00:00
groombook-cto[bot] 6e087cc16b Fix pets API mock route in clients E2E test
The pets endpoint is /api/pets?clientId=... not /api/clients/*/pets.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 02:41:24 +00:00
groombook-cto[bot] a045749673 Add Playwright E2E testing infrastructure
- New apps/e2e workspace with @playwright/test
- playwright.config.ts targeting Docker Compose stack (http://localhost:8080)
- navigation.spec.ts: smoke tests for all pages
- book.spec.ts: full booking wizard happy-path with API mocking
- clients.spec.ts: client list and detail panel tests
- CI job: spins up docker compose, installs Playwright chromium, runs tests
- Playwright report uploaded as artifact on failure
- README docs for running E2E tests locally

Closes #40

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 02:41:24 +00:00
groombook-paperclip[bot] cba502e35f Set up unit testing infrastructure
Extract slot generation from book.ts into pure utility for unit testing.
Add 8 API unit tests and 4 web component tests with coverage thresholds.

Closes #39

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 01:55:02 +00:00
groombook-paperclip[bot] d718821515 Fix tsconfig rootDir for correct dist output paths
The db package's tsconfig included both src/ and drizzle.config.ts, causing
tsc to compute rootDir as the package root. Output went to dist/src/index.js
instead of dist/index.js, mismatching the main field. Set explicit rootDir
in both db and types tsconfigs and remove drizzle.config.ts from build include.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 01:52:26 +00:00
groombook-paperclip[bot] 817a76f8d5 Fix Docker build: compile TS packages for runtime
Fixes ERR_UNKNOWN_FILE_EXTENSION at container startup by compiling @groombook/types and @groombook/db to dist/ before the runtime stage, and copying only compiled JS instead of raw TypeScript source.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 01:34:26 +00:00
groombook-paperclip[bot] 227a687e97 Add seed Docker stage and push migrate/seed images in CI (#37)
- Add seed stage to API Dockerfile (FROM builder, runs pnpm db:seed)
- Add explicit target: runner to API image build (prevents building wrong stage)
- Add CI steps to push ghcr.io/groombook/migrate and ghcr.io/groombook/seed images

Co-authored-by: Groom Book CEO <ceo@groombook.dev>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 23:47:56 +00:00
groombook-paperclip[bot] 20fa4698be Add test data seed script with 500 clients, 6 staff, and appointments (#36)
Creates packages/db/src/seed.ts that generates realistic development data:
- 3 groomers + 3 bathers (staff)
- 10 grooming services
- 500 clients with 1-3 dogs each
- ~2500 appointments across 12 months with varied statuses
- Invoices with line items and tip splits for completed appointments
- Grooming visit logs

Run via: pnpm db:seed (requires DATABASE_URL)

Co-authored-by: Groom Book CEO <ceo@groombook.dev>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 23:37:18 +00:00
groombook-paperclip[bot] 1c54c4264d Update CI to push Docker images to ghcr.io (#35)
Enable image pushing to GitHub Container Registry on main branch
merges. Tags images with both commit SHA and latest.

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 22:23:33 +00:00
groombook-paperclip[bot] 4ab5597fd5 feat: tip and payment splitting between staff roles (#34)
* feat: multi-groomer calendar view with per-groomer filtering

Add groomer view mode to the appointments calendar:
- Toggle between "Status" (existing) and "Groomer" color coding
- Per-groomer visibility toggles with color-coded buttons
- Appointments colored by assigned groomer in groomer view
- Groomer name shown on appointment blocks in groomer view
- Unassigned appointments shown in neutral gray

Satisfies groombook/groombook#11 requirements for side-by-side/unified
groomer schedule visibility and per-groomer filter/toggle.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* feat: tip and payment splitting between staff roles

Implements groombook/groombook#12 — track which staff worked on each
pet and calculate tip distribution based on who was involved.

Changes:
- DB: Add bather_staff_id to appointments (optional secondary staff)
- DB: Add invoice_tip_splits table (per-staff tip share ledger)
- API: appointments POST/PATCH accept batherStaffId
- API: GET /invoices/:id now includes tipSplits[]
- API: POST /invoices/:id/tip-splits — saves tip distribution
- API: GET /reports/tip-splits — payroll summary of tip earnings
- Frontend: Bather/Assistant select on New Appointment form
- Frontend: Tip Distribution section in Invoice Detail modal
  - Auto-populates 70%/30% split when bather is assigned
  - Editable percentages before payment; saved on Mark as Paid
  - Displays recorded splits on paid invoices

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: remove unused staff import from invoices route

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 22:03:46 +00:00
groombook-paperclip[bot] 1b3a23bd52 feat: multi-groomer calendar view with per-groomer filtering (#33)
Add groomer view mode to the appointments calendar:
- Toggle between "Status" (existing) and "Groomer" color coding
- Per-groomer visibility toggles with color-coded buttons
- Appointments colored by assigned groomer in groomer view
- Groomer name shown on appointment blocks in groomer view
- Unassigned appointments shown in neutral gray

Satisfies groombook/groombook#11 requirements for side-by-side/unified
groomer schedule visibility and per-groomer filter/toggle.

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 21:55:07 +00:00
groombook-paperclip[bot] 14ed19497f feat: detailed pet profile attributes and grooming visit history (closes #13)
- Add cut_style, shampoo_preference, special_care_notes, custom_fields columns to pets table
- Add grooming_visit_logs table to track per-visit grooming details (cut, products, notes)
- Extend pets API to accept and return new profile fields
- Add /api/grooming-logs endpoint (GET by petId, POST, DELETE)
- Update Pet type with new fields; add GroomingVisitLog type
- Update Clients page: grooming preferences section in pet card, "Log visit" button,
  visit history panel showing last 3 visits, expanded pet form with grooming preferences

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 21:46:40 +00:00
groombook-paperclip[bot] f47717dfd8 feat: multi-pet client group booking (closes #10) (#31)
* feat: multi-pet client group booking (closes groombook/groombook#10) (GRO-27)

- Add appointment_groups table: links multiple appointments from one client visit
- Add group_id FK on appointments (nullable, backward-compatible)
- Add GET/POST/PATCH/DELETE /api/appointment-groups endpoints
  - POST creates group record + one appointment per pet atomically (with conflict checks)
  - DELETE soft-cancels all appointments in the group
- Add GroupBooking.tsx page at /group-bookings with:
  - Dynamic pet-slot form (min 2 pets, each with their own groomer/service/end time)
  - Auto-calculates end time from service duration
  - Group card list showing all pets, groomers, and statuses side-by-side
  - Client filter and cancel-all action
- Wire into nav and routing in App.tsx
- Export AppointmentGroup type; add groupId field to Appointment type

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: remove eslint-disable for uninstalled react-hooks plugin; remove unused clientMap (GRO-27)

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 21:36:03 +00:00
groombook-paperclip[bot] e63ce83400 feat: reporting dashboard (closes #6) (#30)
* feat: reporting dashboard (closes groombook/groombook#6) (GRO-24)

- Add GET /api/reports/summary — KPI cards (revenue, appointments, clients)
- Add GET /api/reports/revenue — revenue by day/week/month and by groomer
- Add GET /api/reports/appointments — appointment trends with status breakdown
- Add GET /api/reports/services — service popularity and revenue by service
- Add GET /api/reports/clients — new clients, active count, churn risk list
- Add GET /api/reports/export.csv — CSV export for revenue, appointments, services
- Add Reports page at /reports with date range picker and group-by control
- Wire Reports into nav and routing in App.tsx

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: remove eslint-disable comment for uninstalled react-hooks plugin (GRO-24)

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 21:33:33 +00:00
groombook-paperclip[bot] addcefe70b feat: automated appointment reminders via email (GRO-23) (#29)
Implements Phase 1 of groombook/groombook#4 — automated email reminders
for upcoming appointments, with booking confirmations sent immediately
on creation.

- **DB**: new `reminder_logs` table tracks sent reminders per appointment
  (unique on appointmentId+type prevents duplicates); `clients` gains
  `email_opt_out` boolean (migration 0004_reminder_logs)
- **Email service**: `apps/api/src/services/email.ts` — nodemailer SMTP
  transport (disabled when SMTP_HOST is unset, so self-hosted installs
  without email config are unaffected); confirmation and reminder email
  templates included
- **Reminder scheduler**: `apps/api/src/services/reminders.ts` — node-cron
  job runs every minute, checks for appointments in the upcoming reminder
  windows (default: 24 h and 2 h), sends emails for opted-in clients,
  and records sends in reminder_logs (idempotent via ON CONFLICT DO NOTHING)
- **Confirmation email**: sent fire-and-forget after successful appointment
  creation (both single and recurring); never blocks the API response
- **Config**: SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASS,
  SMTP_FROM, REMINDER_HOURS_EARLY, REMINDER_HOURS_LATE env vars documented
  in .env.example; all optional — feature is silently disabled without them
- **Types**: Client.emailOptOut field added to shared types package

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 20:46:49 +00:00
groombook-paperclip[bot] e7cf185d8c feat: recurring appointments with cascading change propagation (#28)
* feat: recurring appointments with cascading change propagation

Implements GitHub issue #9 — recurring appointment scheduling with
configurable frequency and cascade edit/cancel options.

Changes:
- DB: add `recurring_series` table (frequency_weeks) and series_id /
  series_index columns on appointments (migration 0003)
- API POST /appointments: accepts optional `recurrence` object
  (frequencyWeeks + count) that creates a full series in one transaction
- API PATCH /appointments/🆔 new `cascadeMode` field
  (this_only | this_and_future | all) applies time-delta shifts and
  field updates across the series
- API DELETE /appointments/🆔 new `?cascade=` query param cancels
  this_only / this_and_future / all series members
- Frontend: booking form gains a "Recurring appointment" checkbox with
  frequency and count pickers; calendar chips show a ↻ recurring label;
  detail modal shows "Recurring series" badge and a cascade-delete radio
  picker for series appointments

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: resolve TypeScript errors in recurring appointments route

Guard against possibly-undefined results from Drizzle .returning()
destructuring — use indexed access + explicit null checks instead of
array destructuring for the recurring_series insert, and add an early
throw when the series or first appointment row is missing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 20:37:33 +00:00
groombook-paperclip[bot] e524099214 feat: online booking portal (closes groombook/groombook#3) (#27)
Add customer-facing booking flow with three public API endpoints
(/api/book/services, /api/book/availability, /api/book/appointments)
and a four-step React wizard (service → date/time → contact info → confirm).

Availability is computed from real groomer schedules with slot-level
conflict detection. Booking auto-creates or matches clients by email
and uses a transaction to guard against race conditions.

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 20:16:12 +00:00
groombook-paperclip[bot] b767a00b5f feat: basic POS & invoicing (closes groombook/groombook#5) (#26)
- Add invoice_status and payment_method enums to schema
- Add invoices table: appointmentId, clientId, subtotal/tax/tip/total cents,
  status (draft/pending/paid/void), paymentMethod, paidAt, notes
- Add invoice_line_items table: invoiceId, description, qty, unitPrice, total
- Migration 0002_invoices.sql with FK constraints and journal entry
- POST /api/invoices — create invoice with line items
- POST /api/invoices/from-appointment/:id — one-click invoice from appointment,
  pre-populated with service name and price; returns 409 if already invoiced
- GET /api/invoices — list with optional ?status/clientId/appointmentId filters
- GET /api/invoices/:id — invoice with line items
- PATCH /api/invoices/:id — update status, payment method, tip, notes; auto-sets
  paidAt when marking paid; blocks edits on voided invoices
- Add Invoice/InvoiceLineItem types to @groombook/types
- InvoicesPage: list view with status filter, create from appointment modal,
  detail modal with tip input, payment method selector, Mark as Paid/Void actions
- Add Invoices nav link in App.tsx

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 20:02:04 +00:00
groombook-paperclip[bot] eb9255eee0 feat: add health alerts field and delete actions for pets and clients (#25)
- Add health_alerts column to pets table (migration 0001)
- Update DB schema, shared types, and API Zod validation
- Show health alerts prominently (red badge) in pet cards
- Add health alerts field to pet form with allergy/condition placeholder
- Add delete button per pet with confirmation dialog
- Add delete client button with cascade warning

Closes groombook/groombook#2

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 19:40:29 +00:00
groombook-paperclip[bot] 43e50255ec fix: appointment conflict detection, soft-delete, and auth guardrail (#18-22)
Fixes five bugs flagged in CEO code review (GitHub issues #18–22):

- #18: Wrap conflict check + insert/update in a DB transaction to
  prevent double-booking race conditions under concurrent load.

- #19: PATCH conflict detection now falls back to the existing
  appointment's staffId when staffId is omitted from the request body,
  so rescheduling always checks for conflicts.

- #20: DELETE endpoint now soft-deletes (status = 'cancelled') instead
  of hard-deleting, preserving audit trail and financial records.

- #21: Staff DELETE checks for existing non-cancelled appointments
  before deleting and returns 409 if any are found, preventing orphaned
  references.

- #22: AUTH_DISABLED=true now logs a startup warning in development and
  calls process.exit(1) in production, preventing accidental auth
  bypass in deployed environments.

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 19:32:24 +00:00
groombook-paperclip[bot] 0ebc199aea Merge pull request #23 from groombook/fix/ci-restore-pnpm-cache
fix(ci): restore pnpm cache now that lockfile is on main
2026-03-17 19:03:17 +00:00
groombook-paperclip[bot] 49e6d8136d fix(ci): restore pnpm cache now that lockfile is on main
pnpm-lock.yaml landed with PR #15, so setup-node can cache pnpm deps
again. This speeds up CI by avoiding full re-installs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-17 19:01:49 +00:00
groombook-paperclip[bot] 820a5240d1 feat: Docker self-hosting setup
- Fix Dockerfiles to copy pnpm-lock.yaml (frozen-lockfile compliance)
- Add migrate target to API Dockerfile using builder stage
- Add migrate service to docker-compose that runs before API starts
- Add AUTH_DISABLED env var bypass to auth middleware for dev/Docker
- Proxy /api/ from nginx to API container (no CORS needed)
- Include initial Drizzle migration (0000_colossal_colossus.sql)
- Add .env.example with all configurable variables
- Update README with Docker self-hosting instructions

Closes #7

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 18:50:07 +00:00
groombook-paperclip[bot] 4f92b8bffb feat: appointment scheduling, client/pet/service/staff CRUD UI
* feat: appointment scheduling, client/pet/service/staff CRUD UI

- Weekly calendar view with navigation, color-coded by status
- Booking form with client→pet→service→staff→date/time flow
- Double-booking conflict detection on POST/PATCH appointments
- DELETE /api/appointments endpoint
- Staff API route (/api/staff) with full CRUD
- Clients page: searchable list, create/edit clients, add/edit pets
- Services page: table with create/edit/toggle-active
- Staff page: table with create/edit/toggle-active
- Nav bar with active-link highlighting, Staff link added

Resolves GitHub groombook/groombook#1, #2, #8

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: remove unused import, fix useCallback deps

- Remove unused `or` import from drizzle-orm in appointments route
- Compute week end directly in loadAppointments callback to avoid
  exhaustive-deps lint warning (weekEnd derived from weekStart)

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* chore: add pnpm lockfile

Required for CI --frozen-lockfile installs.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: resolve all typecheck, lint, and test failures

- Add @types/node to packages/db devDependencies (typecheck was missing process)
- Re-export drizzle-orm helpers (eq, gte, etc.) from @groombook/db to avoid
  duplicate-instance type conflicts; remove drizzle-orm direct dep from API
- Add @hono/zod-validator and jose as direct API dependencies
- Merge duplicate @groombook/db imports in all route files
- Fix noUncheckedIndexedAccess errors: appointments PATCH, web calendar grid
- Fix weightKg/dateOfBirth type conversion in pets route (numeric→string, string→Date)
- Add eslint.config.js for API and web (ESLint 9 flat config format)
- Add vitest.config.ts with passWithNoTests for API and web

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-03-17 18:45:28 +00:00
groombook-paperclip[bot] f4101982bb Merge pull request #17 from groombook/fix/ci-use-github-hosted-runners
Merging with admin override — CI fails because main has no pnpm-lock.yaml yet (coming in PR #15). The runner and pnpm-setup fixes in this PR are verified correct from the CI logs.
2026-03-17 18:41:12 +00:00
groombook-paperclip[bot] fd65679ca1 fix(ci): remove pnpm cache — no lockfile on main yet
setup-node's cache: pnpm requires pnpm-lock.yaml to exist. The lockfile
is coming in PR #15 but isn't on main yet. Remove caching for now —
it'll be re-enabled once the lockfile lands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:40:08 +00:00
groombook-paperclip[bot] dfc2076320 fix(ci): remove pnpm version conflict in action-setup
pnpm/action-setup@v4 now errors when both the action's `version` input
and package.json's `packageManager` field specify a version. Remove the
action input — package.json's `pnpm@9.15.4` is authoritative.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:38:30 +00:00
groombook-paperclip[bot] a9adc4e430 fix(ci): use GitHub-hosted runners until self-hosted are deployed
All CI runs are stuck in queued — zero self-hosted runners are registered
for the groombook-runners label. Switch to ubuntu-latest to unblock PRs.

Tracked in groombook/infra#2 — will revert once self-hosted runners are
deployed to the cluster.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:37:21 +00:00
Chris Farhood 2bff3a2d82 Merge pull request #14 from groombook/bootstrap/initial-scaffold
Bootstrap monorepo: Hono API, React PWA, Drizzle DB, CI/CD
2026-03-17 13:26:31 -04:00
Groom Book CTO a36436d128 Bootstrap monorepo: Hono API, React PWA, Drizzle DB, CI/CD
Sets up the initial project structure for groombook/groombook:

- pnpm monorepo with apps/api (Hono + TypeScript), apps/web (React + Vite + PWA), packages/db (Drizzle ORM), packages/types (shared types)
- Core DB schema: clients, pets, services, appointments, staff with CNPG-compatible Postgres
- REST API routes for clients, pets, services, appointments with Zod validation
- OIDC auth middleware for Authentik integration
- React PWA with vite-plugin-pwa, service worker, offline caching, installable manifest
- GitHub Actions CI: lint, typecheck, test, build, Docker image build (groombook-runners)
- Dockerfiles for API (Node.js) and Web (nginx)
- docker-compose.yml for local development

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-17 16:11:04 +00:00
Groom Book CTO 00876d13af Initial commit — repository created
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-17 16:10:35 +00:00