Sam Janvey

Sam Janvey

I build B2B commerce and operations software for a distributor that ships real pallets to real customers every morning.

bash — 80×24 guest
guest@janvey:~$

cat ~/work/vendure-janvey/README.md

B2B commerce, wired into the ERP

A Vendure and Next.js storefront for Janvey, built so the catalog, the prices, the customers and the orders all stay the ERP's version of the truth. NetSuite is the system of record; nothing in the storefront gets to disagree with it.

NetSuiteItems, customer pricing, contacts, images, sales orders
RESTletsFive custom endpoints under one token-based integration role
VendureCustom sync plugin, Postgres, job queue, admin dashboard
Next.jsStorefront, account area, approval queue, checkout
Catalog sync
Every NetSuite web item imports as a product with an optionless variant, so SKU, price and availability live where Vendure expects them without showing a variant picker. Items arriving without a valid online price are disabled rather than sold for zero.
Category hierarchy
NetSuite class values map to a staff-editable collection tree. The exact class string is pinned as a private key, so merchandisers can rename, re-parent and re-describe a category and the next sync refreshes membership without stomping their work. An unrecognized class lands in a private Needs Classification bucket and gets reported — it never fails the run.
Account pricing
Contacts belong to a NetSuite account, and the storefront serves that account's negotiated price rather than list. Eligibility is checked on both the account and the contact link, so a suspended account stops transacting immediately.
Order approval
Approval-required contacts submit a checked-out cart into a pending state it can't leave on its own. Approvers see only their own account's requests, can edit quantities, lines and ship-to, comment, approve or reject — and every action is audited with actor, timestamp and totals. Edits run inside one transaction and reprice authoritatively before returning to pending.
Order export
Orders export only after their final business decision, never on submission. Each gets one ledger row keyed on an external ID the RESTlet checks before it creates anything, so a retried job returns the existing transaction instead of a duplicate. If NetSuite's total disagrees with Vendure's, the row is flagged rather than quietly accepted.
Fail-closed by default
Export ships disabled, then dry-run, then live. Dry-run authenticates and validates the whole payload without saving a transaction, and flipping to live doesn't promote the dry-run backlog — a human picks each one. First live order went through on 7 October 2026.

ls ~/work/netsuite/

NetSuite enhancements

Internal systems, all custom. Mostly the same problem each time: a process the business already runs on paper, phone calls and somebody's memory, given a record so it can be counted.

Repair services workflow

Custom record, quote and order chain

Equipment coming in for repair used to live in a notebook. Now a custom record tracks each repair from the moment it's flagged for pickup, and carries forward into the rest of the chain so the whole job is one traceable thread instead of four disconnected ones.

  • Repair logged and queued for pickup
  • Quote raised against the repair
  • Sales order on approval
  • Whole chain linked end to end

Warehouse KPI dashboard

SuiteScript, custom reporting

Routes, load percentage, SLA attainment and exceptions in one place, so dispatch stops reconstructing yesterday from memory every morning.

Rebate engine

Tiered rules, audit exports

Tiered vendor rebates calculated automatically, with exports an auditor can follow without a phone call.

ls -l ~/projects

The rest of it

Smaller, finished, and in somebody's hands. Select a row to expand it.

-rwxr-xr-x Golf Betting App Nassau, skins and side bets, scored live

Scoring for real foursomes. Handicap-aware, so the strokes come off the right holes instead of the whole round. Mobile-first, because nobody opens a laptop on the 4th tee.

-rwxr-xr-x SAM FM for Android Native client with background and car playback

Java and ExoPlayer, talking to the station's AzuraCast API over OkHttp. A foreground service keeps playback alive through screen locks and app switches, and the now-playing title, artist and album art ride along into the notification, the lock screen and the Android Auto head unit. No login, no account — open it and it plays. Min SDK 26, targeting 35.

-rw-r--r-- Futura CSS The framework this site used to run on

A utility-first stylesheet written in college for fast prototyping. Still the origin of everything you're looking at — the phosphor palette, the pixel headings, the terminal.

-rwxr-xr-x Five Nights at Chappy's Survival game, playable in the browser

Started as a Java Swing game for an IST course at Penn State, then became a running joke with my son, who invented Chappy. You have the overnight watch at a doll factory: two aisles, a monitor that keeps the units still, and a breaker that won't last until six. The hard part isn't watching — it's knowing when to look away. Five nights, each one meaner.

-rw-r--r-- The Embrace Found-footage horror prototype, Unity

Shot on a phone, assembled in Unity. A prototype for testing whether the format holds up when the camera is the only light source.

systemctl status sam-fm

SAM FM

A hand-picked library, run through Stereo Tool, broadcasting around the clock on AzuraCast.

active (running) · 24/7

Press play to connect Track info loads once the stream opens

mail -s "hello" sam

Get in touch

permission denied — the form below runs as sam, and you're guest. Escalate in the terminal at the top of the page and it unlocks. Everything you need is in the home directory. Start with ls -a.

Not in the mood for a puzzle? Plain email works fine: sam@samjanvey.com.