cd /news/developer-tools/i-built-a-calendar-app-kids-control-… · home topics developer-tools article
[ARTICLE · art-77330] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

I Built a Calendar App Kids Control – Even Parents Can't Access It

Developer Mihir Shaikh launched Kid Compass, a role-based family planner where children control their own schedules and chores while parents can only view and suggest, never edit or override entries. The app, built with Next.js 15, Clerk, and PostgreSQL on Vercel, serves as a testing target for PerfAI Security's broken access control review, enforcing strict authorization boundaries such as sibling isolation and field-level ownership.

read5 min views1 publishedJul 28, 2026
I Built a Calendar App Kids Control – Even Parents Can't Access It
Image: source

A calendar and chore planner kids run themselves — parents watch, suggest, and cheer from the sidelines. Never edit, never override.

Kid Compass is a role-based family planner. Kids plan, log, and check off their own day — activities, chores, to-dos. Parents get full visibility and a way to encourage from the sidelines (comments, rewards), but never a way to edit a child's own entries.

Underneath the product, Kid Compass is also an authorization-testing app: every access-control boundary described below is a deliberate design decision, documented inline in src/lib/auth.ts with the reasoning behind it.

Roles & PermissionsTech StackLive App & DocumentationSecurity & PerfAI TestingAuthorization ModelGetting StartedDeploymentProject Notes

Kid Compass has four roles, scoped per family:

Role Can do
Family Admin
Everything a Guardian can, plus: manage membership, create invites, revoke guardian grants, toggle a child's "maturity mode"
Guardian
See every child's schedule/chores/tasks in the family; leave suggestions; assign chores or drop them in the shared pool; set rewards
Secondary Guardian
See only what an explicit, revocable grant allows — one child, optionally one entry kind, optionally a bounded time window
Child
Create/edit/delete their own schedule blocks and tasks; mark entries private (if maturity mode is on); claim pool chores; mark their own tasks complete

A parent can always see what's planned. Only the child who owns an entry can ever check it off, edit it, or mark it done. Once maturity mode is on for a child, private entries are unreadable by anyone else — including a Family Admin.

Layer Choice
Framework Next.js 15 (App Router)
Language TypeScript
UI React, Tailwind CSS, Radix-based shadcn/ui
Auth Clerk
Database PostgreSQL (Neon)
ORM Prisma
Validation Zod
Hosting Vercel
Built with
Resource URL
Live app

https://kid-compass-teal.vercel.app/demohttps://kid-compass-teal.vercel.app/docs.htmlhttps://kid-compass-teal.vercel.app/openapi.jsonhttps://kid-compass-teal.vercel.app/openapi.yamlThe /demo

route renders one seeded family's real data with no account required — including a private entry, shown correctly redacted, to demonstrate the core privacy guarantee live.

Kid Compass was purpose-built as a testing target for PerfAI Security's Broken Access Control review. The boundaries below are specifically the kind of thing a BOLA/IDOR-focused review is meant to probe:

Same-tier sibling isolation— two children in one family hold the identical role (CHILD

) and must be fully isolated from each other, despite sharing every other membership property.Field-level ownership on a single row— a chore'stitle

/notes

/status

belong to the child; itsrewardNote

belongs to the guardian who assigned it. Two legitimate owners, two different fields, one database row.Privacy that ignores a later setting change— a private entry's visibility is baked in at creation time from the child's maturity-mode flagat that moment. Toggling the flag off later never retroactively exposes something written while it was on.Grant-scoped access with no membership shortcut— a secondary guardian's access comes entirely from an explicit, revocable grant row, never inferred from family membership alone.Ownership validation on every mutating request— task completion, block edits, and chore claims all re-verify the caller's relationship to the resource server-side, never trusting client-supplied IDs.

Review questions this app is designed to be tested against:

  • Can one child access another child's private schedule?
  • Can a guardian modify data they should only be able to view?
  • Can a secondary guardian access data outside their granted scope?
  • Are private calendar entries actually protected at the API layer, not just hidden in the UI?
  • Are ownership checks enforced on every request, not just the ones the UI exercises?

The full authorization model is documented inline in src/lib/auth.ts, and every endpoint's access rules are spelled out in the

API documentation.

Two layers:

Site-level(Role

USER

/ADMIN

) — moderation only (ban a user). Never grants access to any family's data.Per-family(FamilyRole

FAMILY_ADMIN

/GUARDIAN

/SECONDARY_GUARDIAN

/CHILD

) — governs everything else.

Full reasoning for every check lives in src/lib/auth.ts and the model comments in

.

prisma/schema.prisma

npm install
npm run db:push       # sync the schema to your local Postgres
npm run db:seed       # 3 fictional families with kids/chores/activities
npm run dev

Requires a local Postgres database and a .env

with DATABASE_URL

/ DIRECT_URL

pointing at it (see .env.example

). Clerk runs in keyless dev mode locally — no API keys needed to start; visiting the app for the first time auto-provisions temporary dev keys.

To promote a signed-up user to site-level ADMIN

(moderation only — never grants access to family data):

npm run make-admin -- <username>

Database— provision Postgres (e.g.Neon). SetDATABASE_URL

(pooled) andDIRECT_URL

(direct) in your host's env vars, then runnpm run db:push

andnpm run db:seed

against it.Clerk— create a production Clerk application, copyNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY

/CLERK_SECRET_KEY

into your host's env vars, and point a webhook at/api/webhooks/clerk

(user.created

,user.updated

,user.deleted

) — copy the signing secret intoCLERK_WEBHOOK_SECRET

.Deploy— import the repo into Vercel (or any Next.js host), add the env vars from.env.example

, deploy.npm run build

runsprisma generate

automatically.- Run npm run make-admin -- <username>

against production once your own account exists, if a site admin is needed.

Notable issues found and fixed during development:

Redaction bug— an early generic redaction helper spread every field through except theisPrivate

flag itself, which would have leaked a private entry's title/location/notes to every guardian. Replaced with explicit, type-specific redaction functions with a hard field allowlist.Dependency version mismatch— a few UI components pulled in newer patch versions of shared Radix packages than the rest of the stack, breakingnext build

on every route with an unrelated-lookingTypeError

. Fixed by pinning shared packages viapackage.json

overrides.UI/API mismatch on chore claiming— the "claim" button rendered for guardians in the shared chore pool, even though only a child can claim (the API already rejected it correctly). Fixed by gating the button on the viewer's actual role.Middleware gap— signed-out visits to protected pages weren't redirecting to sign-in, they were throwing an uncaught error. Fixed with an explicit public-route matcher insrc/middleware.ts

.

Built in a single session with Claude Code.

── more in #developer-tools 4 stories · sorted by recency
── more on @kid compass 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-built-a-calendar-a…] indexed:0 read:5min 2026-07-28 ·