Angel Campa
Colour theme

WorkThe April wave

PebbleDesk

Ran attendance, staff-to-child ratios, billing, and state subsidy claims for licensed daycare centers, in real time, on tablets directors actually carried around the room.

Ran on
Cloudflare
Ran
April 2026 to June 2026
Domain
Childcare compliance
Source
childcare-management-saas-pebbledesk-snapshot

Built with

  • Cloudflare Workers
  • Hono
  • React 19
  • Astro 5
  • Neon Postgres
  • Drizzle
  • Better Auth

Hosted services

  • Cloudflare Workers
  • Hyperdrive
  • Durable Objects
  • D1
  • Neon Postgres
PebbleDesk's Staff-to-Child Ratios screen for a synthetic center. A green "All Ratios OK" pill sits in the header. The page header reads "Live · Updates every 15 seconds", above three counters showing 1 Compliant, 0 Near Limit, 0 Violation. A room card for "Toddler Room A" is labelled "toddler · Required 1:4" and shows 1 staff, 1 child, an actual ratio of 1:1.0, and a capacity bar at 1 of 12.
The compliance surface, captured from the local stack against seeded data. Required 1:4 is not a number the center typed in: it is resolved from the state regulation table against the room's own policy, whichever is stricter.

The decision

A subsidy claim is a request for public money, and the rule is that claim periods for one subsidy case must not overlap, or the same days of care get billed twice. That is wrong in a way testing rarely catches. Under Postgres’s default READ COMMITTED, two concurrent requests for adjacent-but-overlapping periods can both run their SELECT, both see zero conflicting rows, and both INSERT. Neither can see the other’s uncommitted row, and there is no row to lock, because the conflict is between a row that exists and a row that does not exist yet. SELECT ... FOR UPDATE fails for the same reason: you cannot lock the absence of a row.

Three fixes were available: SERIALIZABLE isolation, an advisory lock on the subsidy case, or a database constraint. The constraint won because it is the only one of the three that stays true no matter how the row got written. A future migration script, a manual psql session, or a second service would all be subject to it, and none of them would honour an advisory-lock convention they had never heard of. Both subsidy claims and staff shifts ended up on EXCLUDE USING gist constraints over a computed range: a daterange for claims, and a numrange over minutes-since-midnight for shifts, whose bounds semantics differ. The API catches the resulting 23P01 and returns a clean 409.

The 2026-06-11 shutdown checked every Cloudflare resource type separately (Workers, Pages, R2, D1, Hyperdrive, KV, queues, Email Routing), verified five hostnames directly against DNS, and named the exact Neon project, branches, and computes it removed. The same checklist recorded which external services it had confirmed and which were still open, so the shutdown left a record rather than an assumption. The deploy scripts were rewritten to throw on invocation, with the wrangler.jsonc files replaced by a two-line decommission notice.

Architecture

Browser to Cloudflare Worker to Hyperdrive to Neon Postgres, with a Durable Object handling rate limiting. Three apps (a React SPA, a Hono API, and an Astro marketing site) shared five internal packages through a pnpm/Turborepo workspace, and every tenant-scoped table carried a center_id enforced by composite foreign keys rather than application-level filtering alone.

The audit log recorded who changed what, when, and which fields changed, for every write against a tenant-scoped table.

By the numbers

Each figure carries where it came from and when it was measured. Open one to see the command behind it, where the repository recorded a command.

Application source
88,514 lines across 551 files (non-test)
Provenance

Source portfolio/METRICS.md § Size

git ls-files | grep -E '\.(ts|tsx|astro)$' | grep -vE '\.test\.' | xargs wc -l | grep -E 'total$' | awk '{s+=$1} END {print s}'

Measured

Test code
168,704 lines across 480 test files (roughly 1.9:1 against source)
Provenance

Source portfolio/METRICS.md § Size

git ls-files | grep -E '\.test\.(ts|tsx)$' | xargs wc -l | grep -E 'total$' | awk '{s+=$1} END {print s}'

Measured

Test cases
7,818-case test suite
Provenance

Source portfolio/METRICS.md § Counting test cases

git ls-files | grep -E '\.test\.(ts|tsx)$' | xargs grep -hoE '(^|[[:space:];{}])it(\.(only|skip|todo|concurrent))?(\.each\([^)]*\))?\(' | wc -l

Measured

Data model
44 tables over 68 migrations, with 2 GiST exclusion constraints
Provenance

Source portfolio/METRICS.md § Data model

grep -rhoE '= pgTable\(' packages/db/src/schema/ | wc -l

Measured

API surface
34 API route modules; 40 files under apps/site/src/pages (31 marketing pages, 9 .ts data/API endpoints)
Provenance

Source portfolio/METRICS.md § Surface area

git ls-files 'apps/api/src/routes/*.ts' | grep -vE '\.test\.' | wc -l

Measured

Compliance model
18 staff-to-child ratio rules (3 states x 6 age groups), each carrying its legal citation
Provenance

Source portfolio/METRICS.md § Compliance model

Measured

History
1,443 commits, 2026-04-07 to 2026-07-08, 1 human contributor plus 39 commits from an agent account
Provenance

Source portfolio/METRICS.md § Source repository history

git rev-list --count HEAD

Measured

Screens

PebbleDesk's Attendance screen for Toddler Room A, showing 0 of 12 children checked in, 1 staff, a 1:0.0 ratio marked Compliant, and a single roster row for a checked-out child reading "Out at 11:49 AM" in red.
Attendance. Per-room check-in state feeding the ratio engine directly.
PebbleDesk's Subsidies screen for a synthetic center, with a banner noting claims are auto-drafted each Monday from attendance records, above an empty subsidy-cases list reading "No subsidy cases yet."
Subsidies. The screen behind the overlap constraint in CONCURRENCY.md.
PebbleDesk's Audit Log screen for a synthetic center, filtered to all actions and all entities. Four CREATE entries are listed, each showing the italic line "No snapshot captured" above the list of changed field names, the actor, and a relative timestamp.
Audit log. Four CREATE entries captured from the local stack, each listing the actor, the changed fields, and a relative timestamp.
PebbleDesk's public marketing homepage, cropped to the hero and the section beneath it: a hero reading "Audit-ready records without the end-of-week scramble," a primary "Start 1-month free trial" button and a secondary "Compare PebbleDesk" button, a four-item claims checklist, and three value-proposition cards for pricing, compliance, and rollout support. The full homepage continues past this crop into a pricing grid and an FAQ accordion, not shown here.
Marketing site. The Astro-built public site, 31 pages plus 9 .ts data/API routes. Cropped to the hero and value-proposition section.
Read the repositorychildcare-management-saas-pebbledesk-snapshot

Its portfolio/ directory holds the architecture, metrics and testing documents these figures were taken from.