Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
Translation pending
Track your label printing order status with NOVELTY LABELS.
BusinessTypeScript · JavaScriptGitHub @mrpal5aOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Label Print Tracker — Production Job Tracker
Production tracking for a label printing business. One system covers the whole
journey of an order: from the purchase order landing on a desk, through
prepress, the presses, slitting, QC and packing, to the labels leaving the
building — plus a public portal where the customer can follow their own order
without phoning anyone.
Built for the floor, not for a boardroom. Every screen answers "what is the
status of this job, and who is holding it up".Read the full README ↗Production tracking for a label printing business. One system covers the whole journey of an order: from the purchase order landing on a desk, through prepress, the presses, slitting, QC and packing, to the labels leaving the building — plus a public portal where the customer can follow their own order without phoning anyone.
Built for the floor, not for a boardroom. Every screen answers "what is the status of this job, and who is holding it up".
Stack: Next.js 14 (App Router) · TypeScript · Supabase (Postgres + Auth + RLS) · Tailwind CSS v3 · GSAP · deployed on Vercel
The same job data is presented twice, in two different vocabularies.
Staff — /admin (authenticated)
The control room. Every job, every stage, every internal note, machine queues,
shelf stock, analytics and CSV export. Department login decides what can be
changed.
Customers — /track (public, no login)
A customer types their PO number and sees a clean pipeline of where their order
is. Internal notes, machine assignments, other customers' work and anything
commercially sensitive never cross into this view — it reads from dedicated
Postgres views (client_job_view, client_status_log_view), not from the
jobs table directly.
Shop floor — /display (authenticated)
Wall-mounted screens for the production rooms, showing the live queue per
machine. Auto-refreshing and designed to be readable across a room.
New, Repeat and Artwork Changed. Repeat orders
automatically skip the sample and shade-card stages, which a repeat has
already been through.AUG26-1, AUG26-2),
allocated by a Postgres counter table so two people adding jobs at the same
moment cannot collide.Printed labels that physically exist on a shelf, in three kinds:
| Kind | Meaning |
|---|---|
Remaining | Unshipped balance of a partially dispatched order — already promised to that job |
Extra | Surplus beyond the order: press over-run, or spares from a reprint |
Manual | Stock someone found that the system never knew about |
Stock rows outlive the jobs they came from (ON DELETE SET NULL, with job
identity snapshotted onto the row) — closing a PO a year later must not erase
the record of 40,000 labels sitting on a rack.
Remaining stock is reported separately and excluded
from the usable figure, since it belongs to an open order.Sixteen stages. Fourteen are sequential; On Hold and PO Closed sit outside
the sequence.
| # | Stage | Owner |
|---|---|---|
| 1 | PO Received | Prepress |
| 2 | Artwork Pending | Prepress |
| 3 | Plate Status | Prepress |
| 4 | Job Card Done | Prepress |
| 5 | Sample Printing | QC |
| 6 | Shade Card Sent | QC |
| 7 | Shade Card Approved | QC |
| 8 | In Printing | Production |
| 9 | Slitting | Postpress |
| 10 | Quality Check | QC |
| 11 | Packing | Dispatch |
| 12 | Ready to Dispatch | Dispatch |
| 13 | Partial Dispatch | Dispatch |
| 14 | Dispatched | Dispatch |
| — | On Hold | Production / Postpress |
| — | PO Closed | Admin only |
Stages 5–7 are skipped for Repeat jobs, whose prerequisite for In Printing
becomes Job Card Done.
The stage list lives in src/lib/constants/stages.ts and is the single source
of truth — stage names are never hardcoded anywhere else.
Five operational departments plus Admin. A user's department comes from their
Supabase user_metadata.department claim.
| Department | Can set stages | Other permissions |
|---|---|---|
| Prepress | PO Received, Artwork Pending, Plate Status, Job Card Done | Edit job details; set printing unit |
| QC | Sample Printing, Shade Card Sent, Shade Card Approved, Quality Check | — |
| Production | In Printing, On Hold | Set printing unit — and nothing else |
| Postpress | Slitting, On Hold | — |
| Dispatch | Packing, Ready to Dispatch, Partial Dispatch, Dispatched | Edit delivery date; manage label stock |
| Admin | All | Delete jobs; close POs; manage machines and units |
Permissions are enforced in the API route handlers, not only in the UI. The UI control is a hint; the endpoint is the boundary. Every restriction in the table above is re-checked server-side against the caller's department claim.
src/
├── app/
│ ├── (auth)/login/ Sign-in
│ ├── admin/ Authenticated staff area
│ │ ├── page.tsx Dashboard — jobs table, summary, machine board
│ │ ├── jobs/[id]/ Job detail: timeline, notes, print runs
│ │ ├── machines/ Machine registry + utilisation
│ │ ├── printing-units/ Unit management
│ │ └── stock/ Label stock on the shelf
│ ├── track/ Public customer portal
│ │ ├── page.tsx PO lookup
│ │ └── [po]/ Read-only pipeline for one order
│ ├── display/ Production-room wall displays
│ │ ├── [id]/ One machine
│ │ └── rotate/ Cycles through machines
│ └── api/ Route handlers (see API reference)
├── middleware.ts Auth guard
├── components/
│ ├── admin/ Staff UI
│ ├── track/ Customer UI
│ └── ui/ Shared primitives
├── lib/
│ ├── constants/ stages.ts, departments.ts — access-control truth
│ ├── supabase/ server.ts (RLS) + admin.ts (service role)
│ ├── types.ts Shared TypeScript types
│ └── utils.ts Formatting helpers
└── supabase/migrations/ 18 numbered SQL migrations, applied in order
createServerSupabaseClient() — respects Row Level Security. Used for all
reads on behalf of a user. This is the default.createAdminClient() — service role, bypasses RLS. Used only for writes
after the route handler has already verified the caller's identity and
department.Picking the wrong one is the easiest way to introduce a security hole here, so the choice is stated explicitly at each call site.
src/middleware.ts guards /admin/* and /display/* behind a Supabase
session, leaves /track/* public, and validates /api/cron/* against a
CRON_SECRET header. All other /api/* routes skip middleware and authenticate
themselves inside the handler.
| Table | Purpose |
|---|---|
jobs | The order. PO, party, PM code, quantities, dates, status, printing unit, Postpress's slitting confirmation |
job_stage_timestamps | When each stage was completed, per job |
job_status_logs | Every status change, with the department that made it |
stage_comments | Internal notes, attributed to author email + department |
dispatch_schedules | Planned releases for scheduled-release orders |
on_time_dispatch_log | Feeds the on-time delivery rate |
print_runs | Partial-dispatch cycles, each with its own quantity and stage |
print_run_stage_logs | Stage history per run |
printing_units | Unit-1 (Offset), Unit-2 (Flexo) |
machines | Presses and finishing machines, with run speed |
machine_queue_items | Jobs queued against a machine |
job_card_counters | Per-month sequence for job card numbers |
label_stock | Printed labels physically on the shelf |
party_contacts | Customer email / WhatsApp for notifications |
note_reads | Per-user, per-note read state for the internal notes feed |
Plus two views used exclusively by the public portal: client_job_view and
client_status_log_view.
Migrations are numbered 001–018 and must be applied in order.
All routes require an authenticated Supabase session unless noted.
| Method | Route | Notes |
|---|---|---|
GET | /api/jobs | List; filters: status, urgent, search, closed |
POST | /api/jobs | Create. Derives printing method from the chosen unit |
GET | /api/jobs/[id] | Detail with timestamps, logs, notes, schedules |
PATCH | /api/jobs/[id] | Update whitelisted fields; department-checked |
DELETE | /api/jobs/[id] | Admin only |
POST | /api/jobs/[id]/status | Stage change, prerequisite-enforced |
POST | /api/jobs/[id]/confirm-slitting | Postpress/Admin confirm slitting done — unblocks Quality Check |
GET·POST | /api/jobs/[id]/comments | Internal notes |
GET·POST | /api/jobs/[id]/print-runs | Partial dispatch cycles |
PATCH | /api/jobs/[id]/print-runs/[runId]/stage | Advance one run |
GET·POST | /api/jobs/[id]/schedules | Scheduled releases |
GET | /api/jobs/pm-lookup?code= | PM code typeahead for repeat orders |
| Method | Route | Notes |
|---|---|---|
GET·POST | /api/stock | Live shelf stock; POST is Dispatch/Admin |
PATCH | /api/stock/[id] | Mark dispatched (soft removal — no hard delete) |
GET | /api/stock/match?pm_code= | Existing stock for a PM code |
GET·POST | /api/machines | Machine registry |
GET·PATCH·DELETE | /api/machines/[id] | One machine |
GET·POST | /api/machines/[id]/queue | Machine queue |
PATCH·DELETE | /api/machines/[id]/queue/[itemId] | Queue item |
GET | /api/machines/[id]/display | Wall display payload |
GET | /api/machines/display-all | All machines, for the rotating display |
GET | /api/machines/analytics | Utilisation |
GET·POST | /api/printing-units | Units |
GET·PATCH·DELETE | /api/printing-units/[id] | One unit |
| Method | Route | Notes |
|---|---|---|
GET | /api/analytics?month=YYYY-MM | On-time rate + dashboard counts |
GET | /api/notes/feed?since=&limit= | Global note feed + unread count |
GET | /api/export | CSV of jobs, releases and runs |
PATCH | /api/dispatch-schedules/[id] | Update a planned release |
GET | /api/cron/overdue-check | Cron only — requires x-cron-secret |
POST | /api/notifications/email | Resend — currently unauthenticated |
POST | /api/notifications/whatsapp | WATI — currently unauthenticated |
[email protected])ap-south-1 (Mumbai) is closest to the plantgit clone <your-repo-url>
cd label-print-tracker
pnpm install
In the Supabase dashboard → SQL Editor, run every file in
supabase/migrations/ in numerical order, 001 through 018. Run them one
at a time and confirm each succeeds before the next.
Verify afterwards that Table Editor shows jobs, label_stock, machines,
printing_units and the rest, and that Database → Views shows
client_job_view and client_status_log_view.
Authentication → Users → Add user, then set Raw User Meta Data on each:
{ "department": "Prepress", "display_name": "Prepress Team" }
Create one per department: Prepress, QC, Production, Postpress,
Dispatch, Admin. The department value must match exactly — it is the
access-control claim, and a typo silently locks the account out of every stage.
cp .env.local.example .env.local
Fill in the values described in Environment variables.
pnpm dev # http://localhost:3000
pnpm build # production build
pnpm start # serve the production build
pnpm lint # ESLint
/login with the Admin account → redirects to /admin/track → enter the PO → the customer pipeline appears| Variable | Required | Purpose |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Yes | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Yes | Public anon key (RLS applies) |
SUPABASE_SERVICE_ROLE_KEY | Yes | Server only. Bypasses RLS — never expose to the browser |
NEXT_PUBLIC_APP_URL | Yes | Public base URL, used in outbound links |
CRON_SECRET | Yes | Shared secret for /api/cron/*. Generate with openssl rand -hex 32 |
RESEND_API_KEY | For email | Resend API key |
RESEND_FROM_EMAIL | For email | Verified sending address |
WATI_API_ENDPOINT | For WhatsApp | WATI instance endpoint |
WATI_API_TOKEN | For WhatsApp | WATI API token |
ADMIN_WHATSAPP_NUMBER | For alerts | Recipient of the daily overdue alert |
.env.local is gitignored and must never be committed.
Deployed on Vercel. Pushing to main triggers a production deploy.
NEXT_PUBLIC_APP_URL to the deployed URL after the first deploy, then
redeployvercel.json declares:{ "crons": [ { "path": "/api/cron/overdue-check", "schedule": "30 3 * * *" } ] }
30 3 * * * is UTC — 9:00 AM IST.
Database migrations are not automatic. A deploy ships code only. Any new migration must be run against the production Supabase project before the code that depends on it goes live, or the affected routes will fail.
Two documents at the repo root are normative for any UI work:
PRODUCT.md — who this is for and the five design principles: status is
the product; premium means precision; one vocabulary, two audiences; fast on
the floor; states are designed.DESIGN.md — the visual system, "Control Room": a light Airy Green
admin and Press Green glass for /track and /display; DM Sans for words,
Trispace for numbers; every state shown as a stage-coloured dot beside its
name. The frontmatter tokens are normative, and it links the browsable
Control Room design system (tokens in both themes, component previews).Non-negotiables: WCAG AA contrast, 44px minimum tap targets, and a
prefers-reduced-motion alternative for every animation. No generic
admin-template patterns, no consumer-app flashiness.
jobs, so internal notes,
machine assignments and other customers' data cannot leak into /track./api/notifications/email and /api/notifications/whatsapp currently have
no authentication. Any caller who can reach them can trigger a real email or
WhatsApp message. They work for internal use, but need a department check or a
shared secret before this deployment is treated as internet-facing. Known gap,
not yet fixed./api/stock/[id] supports only marking a
row dispatched; rows remain visible under the history view. Removing one
entirely requires a direct database operation.SETUP.md is historical and describes an earlier state of the project.
This README supersedes it.Private and proprietary. © Your Print Company.