FERNWAY

Changelog

Every change, as it shipped.

Read from Fernway’s own commits, newest first, with the moment each one went live. 65 changes so far.

Monday, 9 November 2026

  1. 61

    d3d2288

    The delivery engine: shipments, scans, the retry schedule, no duplicates

    • db/migrations/0002_delivery.sql: accounts, routes (pipeline, stage, tags), shipments with waybill numbers and an idempotency key per account, and scans: every step with what was sent and what GHL answered. The app's role can add scans but never change or remove one.
    • packages/delivery: leads checked at the door (an email or a phone GHL can match, phones cleaned for GHL); the GHL client (contact upsert, then opportunity upsert in the route's stage; 2xx signed, 429/5xx/no answer retried, 401 refreshes the token, any other 4xx held with GHL's reason); the engine, which writes every scan in the same transaction that moves the shipment and skips any try that isn't due; one-click resend; and a sweep that puts overdue shipments back on the queue if Redis ever lost them. Drizzle over the SQL migrations, with a test that the two still match.
    • apps/worker: runs the queue (BullMQ on Redis, under GHL's rate limit) and the sweep every minute. Until GHL is connected (next step) a lead is held with that reason, never lost.
    • 19 tests against a real Postgres and Redis with a fake GHL: the landing page's promises (8 tries on the stated schedule, no second contact even when GHL's answer is lost, a scan for every hand-off), holds, 401s, repeated and late jobs, resend, the sweep, and a lead refused twice that the worker delivers on its own through the real queue.
  2. 62

    c8bee55

    Landing: the background fills the whole screen, however tall

    • At 33% zoom the grid and route lines stopped at a hard edge 980px down, with flat navy below. The page now fills the screen, so the background reaches the bottom on any monitor, while the first screen's content still stops growing at 850px so the bottom strip stays with it. 1440, 1536, 1366 and the phone are unchanged.
  3. 63

    90f54c5

    Landing: content stays in one centred column on wide screens

    • At 1920 and wider (or zoomed out) the header, hero and waybill were pinned to the screen's edges, leaving an empty gap in the middle. Content now lives in one centred column (1312px wide, never less than the gutter at the sides); only the background, the rules and the bottom strip's bar reach the edges. The page's first screen is at most 980px tall, so a very tall screen no longer pushes the strip away from the content. 1440, 1536, 1366 and the phone look as before.
  4. 64

    d040b26

    Deploy: check the public site through this box's own Nginx, not its DNS cache

    • The final check called https://fernway.jeromebadour.com by name. Right after the DNS record was added, the box's resolver still held the old "no such name" answer, so a healthy deploy would have failed its last check. It now reaches the same URL, certificate and Nginx with the name pinned to this box.
  5. 65

    12bd820

    Skeleton: monorepo, the landing page, health, CI and deploy

    • apps/web: Next.js 16 with Fernway's world (G) as tokens and glyphs, the approved landing page at three sizes, a designed 404, and /api/health that checks the database, the queue and the worker for real.
    • apps/worker: the delivery worker's first version, a heartbeat the health check reads.
    • packages/core: waybill numbers and the delivery promise (8 tries over 24 h), with tests.
    • db: migrations applied on every deploy; the app's own role can read and write but never change tables.
    • compose.yaml: Postgres, migrations, Redis, web on 127.0.0.1:3103, worker.
    • CI: types, lint, unit tests, then the real images and stack, checked as the box runs them.
    • scripts/deploy.sh and ops/nginx for fernway.jeromebadour.com.

Deploys are recorded from the first deploy after the status page shipped; earlier changes went live in the deploys of their day.