Browsing anonymously — data reads run via service_role bypassSign in
ClicknifyERP

One platform.
Every persona.
Live in Postgres.

Multi-tenant school-management SaaS for Indian K-12. Six demo schools, seven personas, every button writes to a live Supabase project with an audit trail — no click is a mock.

Tenants
6
Students
41
Attendance rows
1,240
Receipts
150
Applications
12

Try the demo

All routes read + write live Postgres

Six tenants, one codebase

Brand + font come from Postgres

What's under the hood

Next.js 15 · App Router · RSC

Server components fetch from Supabase and stream. Client islands only where needed — attendance grid, editors, forms, ⌘K palette.

Design tokens · one source of truth

F-01 tokens.json → generated Tailwind + CSS vars → semantic layer → tenant/platform scopes. Change one hex on the branding page, the whole tenant re-tunes.

Supabase · Postgres 17 · RLS

Every business table has a Row-Level-Security policy keyed on current_tenant_id()and current_user_role(). Server actions write; audit_logs capture before + after.

Multi-tenant theming · zero re-render

[data-scope="tenant"][data-tenant-slug=X] stanzas inject 7-stop OKLCH brand ramps + Google Fonts per tenant. Switching tenants swaps a <style> block. React doesn't re-render.

Auth · @supabase/ssr

/auth/sign-in → 7 seeded demo users → role-appropriate landing route. Session cookie refreshed by middleware.

Offline-first attendance

Simulate offline → tap 40 cells → reconnect → sync. Monotonic tick per row for last-write-wins on the server.