An open-source formulation data system for agrochemical R&D.
AmplusLog is a Next.js + Supabase web app that gives a chemistry team a single canonical record of every formulation experiment, raw-material lot, recipe iteration, lab test, field trial, and commercial batch they produce. It is designed to replace the spreadsheets-and-memory pattern that most small to mid-sized formulation groups still rely on.
The schema is the source of truth — see architecture.md
for the full ERD, design rationale, and the audit / RLS / confidentiality rules
the application enforces.
- Materials, lots, suppliers, instruments — full CRUD with audit trail, soft delete, search & filter, and pricing/QC history per lot.
- Experiments as the primary entry surface — chemists log a day's bench work in one transactional submit; the app fans it out into recipe + components + process + lot decrement in a single RPC.
- Recipe lineage — every iteration tracks its parent; family trees are computed by a recursive view and visualised on the recipe detail page.
- Inline test logging — log a stability or release panel against an experiment in one form; per-test result fields are rendered dynamically.
- Role-based access control — 5-role matrix (admin / manager / formulator / qc / read-only) enforced at the Postgres RLS layer; confidentiality toggle for recipes and projects.
- Admin surface — invite users, set roles, generate password reset links, browse the audit log with old/new diffs.
- Tutorial system — built-in product tours for new users (driver.js).
- Auto-generated REST + TypeScript types — Supabase generates a typed PostgREST API and a
Databasetype that the app consumes end-to-end.
| Framework | Next.js 16 (App Router, TypeScript strict, Turbopack) |
| Backend | Supabase (Postgres + Auth + Storage + auto REST) |
| UI | shadcn/ui (Radix primitives) + Tailwind v4 |
| Forms / validation | react-hook-form + zod |
| Tables | @tanstack/react-table |
| Package manager | pnpm 10 |
# Prerequisites: Node 20+, pnpm 10+, Docker, Supabase CLI
git clone <your-fork-url> amplus-log
cd amplus-log
pnpm install
cp .env.local.example .env.local # local Supabase keys
supabase start # Postgres + Auth + Storage in Docker
supabase db reset # apply migrations + seed reference data
pnpm db:types # generate src/types/db.ts from local schema
pnpm dev # http://localhost:3000Local Supabase Studio: http://127.0.0.1:54323 Local mailbox (Mailpit) for auth emails: http://127.0.0.1:54324
The .env.local.example values match the keys printed by supabase status for
a fresh local stack.
AmplusLog is a standard Next.js + Supabase app — any combination that supports both works. The reference deploy is:
- Supabase Cloud — create a project, then from this repo run
supabase link --project-ref <ref>andsupabase db pushto apply migrations. - Vercel — connect the repo; set
NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, andSUPABASE_SERVICE_ROLE_KEYfrom the Supabase project's API settings. - Disable public signup in Supabase → Auth → Providers → Email. New
accounts go through the in-app
/admin/users/inviteflow. - Enable backups (Pro tier) before real data goes in.
- Configure custom SMTP so auth emails come from your domain, not Supabase's shared sender.
| Command | What it does |
|---|---|
pnpm dev |
Next dev server (Turbopack) |
pnpm build |
Production build |
pnpm typecheck |
tsc --noEmit |
pnpm lint |
ESLint |
pnpm db:reset |
Re-apply all migrations and seed reference data |
pnpm db:types |
Regenerate src/types/db.ts from the local DB |
supabase start / stop |
Bring local Postgres + Auth + Storage up/down |
- Create
supabase/migrations/000N_<name>.sql(zero-padded, monotonic). pnpm db:reset— re-apply all migrations from scratch (do not edit applied migrations in place).pnpm db:types— regenerate TypeScript types.supabase db pushto apply to cloud (if linked).- Commit migration + regenerated types together.
If the migration adds a new entity that needs a UI, follow the audit-coverage
rule in CLAUDE.md and the entity template described there.
architecture.md schema + design rationale (source of truth)
supabase/migrations/ numbered SQL migrations (0001 = initial schema)
src/
├── app/
│ ├── (auth)/ login, signup, reset password
│ ├── (app)/ authenticated app (dashboard + every entity)
│ └── layout.tsx root: providers, fonts, theme
├── components/
│ ├── layout/ nav, topbar, shell
│ ├── tables/ generic data-table
│ ├── tutorial/ driver.js-based product tours
│ └── ui/ shadcn primitives
├── lib/
│ ├── supabase/ client.ts (browser), server.ts, admin.ts (service-role wrapper), middleware.ts (cookie refresh)
│ ├── schemas/ zod schemas (mirror DB row types)
│ ├── queries/ typed Supabase query functions
│ └── utils.ts
├── types/db.ts generated by `supabase gen types`
└── proxy.ts Next 16 proxy: auth gate (replaces middleware.ts)
AmplusLog is functional but pre-1.0. Materials, suppliers, instruments, lots, experiments, recipes, tests, projects, and admin surfaces are all implemented. Production batches, SKUs, field trials, registrations, and complaints have DB schemas but no UI yet — they are scaffolded and follow the same pattern as the shipped entities.
See CLAUDE.md for the engineering context (conventions,
patterns, RBAC matrix, hard gates) that contributors should read before adding
features.
PRs welcome. Please:
- Open an issue describing the change before non-trivial work.
- Follow the conventions in
CLAUDE.md(Server Components + Server ActionsrevalidatePath; nouseQuery/useMutationwithout prior discussion).
- Mirror the audit-coverage rule for any new entity (rule + checklist live
in
CLAUDE.md). - Keep migrations append-only and monotonic.
MIT — see LICENSE.