Javis OS
Javis OS는 기업가를 돕는 에이전시 AI로, 업무를 지원하고 함께 성장합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
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".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.