Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KRN International

Japanese export stock — cars, spare parts, machinery and bikes — presented as a port departure board, with a customer dashboard for order tracking and a separate management back office.

Next.js 16 · React 19 · Tailwind v4 · Postgres via Prisma 7.


The three surfaces

Surface Route Who
Public board /, /cars, /spare-parts, /machinery, /bikes Anyone. Live stock, no account needed to enquire.
Customer dashboard /dashboard Signed-in buyers. Order tracking and history.
Management /manage Admins only. Stock, sailings, orders, buyer accounts.

/manage is not linked from the public site and carries noindex, nofollow. It shares the design system with the public site and nothing else — no public header, no footer, no route back into the public navigation.

The Dashboard link appears in the public header only when a customer is signed in. /dashboard itself stays reachable when signed out: it renders a "Please log in" page rather than silently redirecting, so a bookmarked or shared link explains itself.


Running it

1. Database

Local development, no setup — Prisma ships a local Postgres:

npx prisma dev --name krn      # leave this running; it prints two URLs

Paste the DATABASE_URL and SHADOW_DATABASE_URL it prints into .env (see .env.example). Keep that process alive — killing it drops the database connection and every page will 500.

If it will not restart (ERROR Lock file is already being held, and pages 500 with ECONNREFUSED): a force-killed server leaves a stale lock. Delete it and start again.

rm -rf "$LOCALAPPDATA/prisma-dev-nodejs/Data/durable-streams/krn/server.lock.lock"
npx prisma dev --name krn

Your data survives this; it lives in …/prisma-dev-nodejs/Data/krn. Stop the server with Ctrl-C rather than by killing the process and you will not hit it. None of this applies to a real Postgres — prisma dev is PGlite, not a server you would deploy.

Or point at your own Postgres:

DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/krn?schema=public"

2. Schema and data

npm install
npm run db:push      # or: npm run db:migrate  (prisma migrate deploy)
npm run db:seed
npm run dev

db:push syncs the schema directly and is the quickest way to get going. db:migrate applies the SQL in prisma/migrations/ and is what you want for a real deployment.

3. Sign in

The seed creates three accounts. All three share the password krn-demo-2026. Change or delete them before this goes anywhere real.

Email Role Lands on
admin@krn-international.example Admin /manage
dealer@example.com Customer /dashboard — orders in progress
buyer@example.com Customer /dashboard — one in progress, one completed

How selling works

This is the flow that connects the three surfaces:

  1. A unit sits on the public board while its status is AVAILABLE or RESERVED.
  2. In /manage/stock you press Mark sold and choose the buyer:
    • A buyer with an account → the order lands on their /dashboard immediately.
    • An external buyer (eBay, walk-in) → the order is tracked internally against a free-text label. External buyers have no dashboard.
  3. The unit's status becomes SOLD in the same transaction, which removes it from every public board. One unit can only ever carry one order — the database enforces it with a unique constraint.
  4. You record stages on the order page. Each writes a TrackingEvent the buyer sees, with an optional note.
  5. CANCELLED releases the unit back onto the public board.

Stages: RESERVED → DEPOSIT_PAID → IN_YARD → LOADED → SAILED → ARRIVED → RELEASED, plus CANCELLED off-path. RELEASED and CANCELLED move an order into the buyer's history.

Sailings

The sailing schedule used to sit on the public home page. It now lives in /manage/sailings, and the public board reads from it — every row takes its destination, vessel, cut-off and ETA from the sailing its unit is booked onto. Change a date there and every row that references it follows.


Auth

  • Passwords hashed with bcrypt, cost 12.
  • Sessions are a 256-bit random token in an httpOnly, SameSite=Lax cookie (Secure in production). The database stores only its SHA-256, so a database dump cannot be replayed as a live session.
  • Two roles, CUSTOMER and ADMIN. Self-registration can only ever create a CUSTOMER; admins are made in /manage/buyers.
  • Every admin page and every admin server action calls requireAdmin(). Server actions are separately addressable endpoints, so guarding the layout alone would leave them open.
  • Sign-in gives the same response whether or not an address is registered.

Scripts

Command What
npm run dev Dev server
npm run build / npm start Production
npm run db:push Sync schema to the database (no migration history)
npm run db:migrate prisma migrate deploy — for real environments
npm run db:seed Reset and reseed stock, sailings, demo accounts and orders
npm run db:studio Prisma Studio
npm run lint ESLint

Before this goes live

All stock, pricing, vessels and sailings are authored placeholder data. REPLACE-ME.md lists every invented value and where it lives. The public footer carries a standing notice saying so — remove it only when the data is real.

Design

DESIGN.md is the system of record for the visual language ("The Departure Board"), with .impeccable/design.json carrying shadows, motion and component snippets. Read it before adding a surface.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages