What we shipped

Changelog

Every release shipped to binnacleai.com, weekly cadence.


2026-05-26 — Pricing routed through contact

Removed every published product price from binnacleai.com. Tiers, comparison table, hero, FAQ, ROI calculator, blog posts, JSON-LD structured data, meta descriptions, and onboarding email templates now route to a single CTA: Contact BinnacleAI for a demo and pricing. Feature lists, tier names, and descriptive copy are unchanged. Designed so a prospect's first touchpoint is a real conversation, not a number on a card.


2026-05-24 — Security + UX audit fixes (11 items)

Second audit pass on binnacleai.com. One deploy.

Security:

  • `/admin` now 404s for non-admin users — was silently redirecting to /dashboard, which implied the route existed. notFound() is cleaner and doesn't leak route presence.
  • `/api/health` strips `service` field — removing "service": "binnacle-ai" from public responses so the stack name isn't confirmed to scanners.
  • `tracker.js` removedai.portofcams.com/static/tracker.js was returning 503, had no SRI hash, and was actively failing on every page load. Removed from layout.tsx and the CSP SCRIPT_HOSTS allowlist in proxy.ts.
  • GA4 no longer sends query params — added page_location: origin + pathname override to the GA4 config so ?signed=ok, ?callbackUrl=, and any future state tokens are never sent to Google's servers.
  • Port Captain input capped at 2 000 charsmaxLength={2000} on the dashboard widget input + server-side .slice(0, 2000) in /api/port-captain/chat/route.ts to prevent unbounded AI inference costs.

UX:

  • `?signed=ok` stripped from URL on mount — new <UrlCleaner> client component in the dashboard layout strips known sentinel params (signed, callbackUrl) via history.replaceState without triggering a navigation.
  • `HI GET #TBD` placeholder removed — the /pricing footer note previously read "registered under HI GET #TBD"; simplified to just "Hawaii GET is a passthrough. Not tax advice."
  • Duplicate `mobile-web-app-capable` meta removed — Next.js appleWebApp.capable already generates this tag; the redundant other["mobile-web-app-capable"] entry was causing a duplicate.

SEO:

  • `public/robots.txt` created — disallows /dashboard with and without trailing slash, plus all other protected dashboard routes and /api/.

Copy:

  • Layout meta description — "operators running 2-15 vessels" → "operators running 2 to 200 vessels" (same canonical range as landing/hero).

2026-05-20 — Dashboard audit polish (13 fixes)

Visitor-style dashboard audit found 13 issues. All fixed in one deploy.

🔴 Critical / functional:

  • #1 Demo Tour Skip wired — added ESC handler, backdrop-click dismiss, and an explicit X close button in the corner. The original Skip button onClick was already wired but invisible to testers; making the dismiss affordances explicit eliminates the ambiguity.
  • #2 Port Captain renders markdown — minimal renderInlineMarkdown() helper in src/lib/markdown-inline.tsx handles **bold**, *italic*, ` code , and link`. No external dep; safe URL allowlist (http/s + relative + hash).
  • #3 "Drills overdue" / "Aboard visitors" cards — the dimWhenZero prop was rendering an em-dash for zero values, which testers read as "load failed." Now shows the actual 0 in the muted tone so "you have zero" is unambiguous.

🟠 High-severity UX:

  • #4 "Next 30 days" no longer shows past-due items — drydock surveys with a windowOpenAt in the past were rendered using startAt (the window-open date), producing labels like "34d ago" in a forward-looking widget. Fixed to display endAt ?? startAt so the deadline is shown.
  • #5 Mobile drawer hardening — added transform-gpu will-change-transform for smoother hardware-accelerated transitions, overscroll-contain on the nav scroll area, and switched h-screenh-[100dvh] for correct iOS viewport handling.
  • #6 Renewal heatmap got axis labels — weekday headers anchored to today's start day (since the grid starts at "today," not Monday), and the day-of-month is now rendered inside each cell. Bonus: ARIA role="img" + aria-label for screen readers.
  • #7 "Pick vessel →" CTA is now visible — was a barely-visible text span with hidden md:inline. Now a proper blue-bordered pill that's visible at all viewport sizes with a clear hover state.

🟡 Medium / content:

  • #8 Activity ticker fixed — (a) verbFor() had a naive past-tense rule that produced "requestd" / "viewd" / "signd"; replaced with a proper pastTense() helper. (b) Filtered out api.request / api.auth / mobile.token audit-log rows from the ticker; the mobile-bearer-token endpoint had been writing one per call, drowning out real business events.
  • #9 Blank bottom gap shrunk — removed redundant pb-16 on the dashboard page (the layout already supplies bottom padding).
  • #10 "Commercial Profile" label de-afforded — dropped the gauge icon that made it look like a button; now reads as a passive label.

🟢 Minor / polish:

  • #11 "Replay tour" styled as a button — bordered pill matching the "Sign up for free trial" affordance.
  • #12 Empty Port Captain submit feedback — pressing Enter on an empty input now shows a 2.4s status hint ("Type a question to ask the Port Captain") instead of silently doing nothing.
  • #13 "Today" cell explained — renewal heatmap legend now includes a "today" pip swatch; the today cell shows the day-of-month in blue text inside its blue ring, so the outline is recognizable as "you are here" rather than "weird empty bar."

2026-05-20 — Tokenised demo flow rebuilt (PR #14 un-stub)

After the 2026-05-16 5-layer lockdown nuked the gated demo (because the prior ALLOW_DEMO_LOGIN backdoor had given the public ADMIN access for months), /demo/access/{token} was a static "we're rebuilding" stub and the underlying Prisma models had been removed.

Restored in this deploy:

  • Prisma modelsDemoRequest, DemoAccessToken, DemoAccessView (no new migration; original migration was still applied on prod)
  • `src/lib/demo-access.ts` — full issueDemoToken / resolveToken / logDemoView / tokenAllowsRequest / revokeToken implementation
  • `/demo/access/[token]/route.ts` — Route Handler (not Server Component, per Next.js 16 strictness), uses publicUrl() to handle x-forwarded-host behind NPM+Cloudflare
  • `/demo/access/denied/page.tsx` — failure UI
  • `/api/demo/request` — public POST endpoint (24h dedupe per email)
  • `/api/admin/demo-requests/[id]` — ADMIN/OWNER-only approve/decline/revoke
  • `/admin/demo-requests` — 3-section admin queue (pending, active tokens, recently decided)

The 4 untouchable lockdown layers remain in place: entrypoint guard, no test/test in auth.ts, /api/demo/sign-in still hard-503 in prod, hashedPassword: null in the demo seed. The tokenised flow is its own independent security envelope: 192-bit random tokens, admin approval gate, expiry + view-cap + revocation + optional IP pin, signs into isDemoOrg orgs only.

End-to-end smoke verified: prospect POST → admin approval → token URL → demo dashboard with both cookies set correctly, view-cap incremented, firstSeenIp pinned.


2026-05-20 — Landing audit polish (6 fixes)

Visitor-style audit caught six inconsistencies on the public landing. Single deploy:

  • Fleet-size copy unified to "2 to 200" across hero, personas, comparison, and FAQ (was mixing "2–200" with "1-15 vessels," which undermined the Enterprise tier and could confuse evaluators)
  • Comparison-table row renamed from "Pricing transparency" to a row about direct, no-sales-call access to pricing — Spreadsheet cell flipped from green check to partial dash (spreadsheets aren't a vendor with publishable pricing)
  • Legend added below the comparison table explaining ✓ / – / ✗ (Full support / Partial / manual / Not supported)
  • HI GET passthrough line added on the Multi-vessel tier to match the Solo tier's transparent-pricing layout (since superseded — see 2026-05-26)
  • Final-CTA "Request demo" moved from bare mailto:hello@binnacleai.com to /demo — matches the Hero's "Try the live demo" target and pre-empts the bad email-client UX
  • "Live status page" trust chip moved from off-brand https://status.portofcams.com to the on-brand internal /status page (which already existed)

2026-04-27 — 8-module Helm/Mariner-IQ parity push

Eight new modules in one evening:

  • LSA/FFE Equipment Log/safety-equipment + /boat/safety (46 CFR 199 + 25.30)
  • MARPOL Records — Oil ORB / Garbage / Sewage / Bilge in one unified model (33 CFR 151, Annex IV-V)
  • Spare Parts & Inventory — atomic ledger, low-stock filter, fleet-wide vs vessel-specific
  • Vendors + Purchase Orders — auto PO numbering, partial-receive flow
  • Class Surveys + 5-yr Special Periodical planner — separate from drydock; tracks every class + flag-state cert
  • Engineer's Mechanical Log — engine readings every watch, CSV export, immutable per 46 CFR 4.06
  • Bilge Operations & Slop — OWS pumps, weekly OWS tests, ppm > 15 highlighted red
  • Ballast Water Management — BWMP per vessel + per-event log w/ GPS, depth, salinity, BWMS run minutes

Also today: trust strip + founder chat FAB + /integrations + /pricing comparison table + cache header fix (was making deploys invisible for 1 year). Real founder phone number (907-769-1165) wired into the chat FAB. /#showcase cut its empty top space and gained an 8-module feature stripe.


2026-04-26 — Maritime visual identity: backdrop + typography

Compass-rose ghost + tug-and-barge wave-line drift on every auth page, every welcome step, and the marketing tool/info pages. Single visual language from landing to register to onboarding to dashboard. Bigger and brighter typography across the board: 16px medium inputs, bold uppercase labels, Bitter serif at 28-56px. Lifted text-secondary and text-tertiary tokens site-wide so every label gets brighter outdoor-screen legibility. /compliance-calculator and /roi-calculator got the same louder-typography pass.

Also today: shared AuthShell component for /login and /register, animated tug + barge backdrop on the login page, founder impersonate route, stub-button audit, prod-readiness audit, rollout-readiness synthesis, S-2 incident photos, S-4 org contact form, N-2/N-3 SMS forms, N-4 DPA, route-integrity audit, and the form-handler audit doc.


2026-04-25 — /boat redesign + Phase 3 design-partner 1-pager

/boat hero rebuilt: 32px Bitter serif, severity-coded compliance cards, EN/ES/TL inline locale switcher, compass rose + wave-line motion. Drills and incidents now fire deliverAlert() to Slack and Teams. Phase 3 design-partner 1-pager (615 words + xelatex PDF) shipped. Layout-wide locale switcher applied to every /boat route, bolder bottom nav, louder labels. Drill-save bug fixed and the Request Renewal button now hits a real endpoint instead of a stub. /api/admin/webhooks/[id]/test endpoint wired for the integrations admin UI. Walkthrough pack at docs/WALKTHROUGH-PACK-2026-04-25.md.

Also today: blog post 9 — _Charter Party Agreements_ (1,798 words).


2026-04-24 — Phase 1+2+3 stack: blog, P&L, ROI calculator, public API

Six SEO-optimized blog posts shipped with cross-link strip and featured-hero card. Voyage P&L panel (revenue, cost-per-mile, fuel burn) added to every voyage detail page. ROI calculator at /roi-calculator turns operator inputs into a dollar figure. Phase 3 ships the design system, public API, webhooks, Slack/Teams alert delivery, and a Zapier scaffold.

Also today: blog post 7 — _Inspection Day Survival_, post 8 — _STCW Manila_, the first round of Card-component sweep, Spanish + Tagalog i18n for /boat (922-line dictionary, 3 locales: EN/ES/TL), MMC verify against USCG NMC, photo OCR via Claude Vision, and the weekly compliance digest email.


2026-04-22 — Five new modules + unified compliance calendar

Five modules in one drop: Fishing Log, Charts/ENC, Port Calls, Weather Routing, and Cargo Manifest. Unified compliance calendar at /calendar that aggregates every expiration, drill, and survey across the fleet — with webcal:// iCal subscription export so it lands in Apple Calendar and Outlook automatically. Dashboard cockpit gained the wired-up UpcomingDeadlines widget. /boat /more menu picked up bunker, fishing, and calendar entries, reordered by operator priority.

Also today: crew detail cross-links, the 18-modules-in-5-days launch post, and polish that cross-links new modules from vessel and voyage detail pages.


2026-04-20 — CRM, payroll, dry-dock, SMS/ISM, enterprise SSO

Big drop of operator-grade modules:

  • Customer / Charterer CRM — track who is hiring whom, when, and at what rate
  • Payroll / time tracking — punch in, hours, gross-net split
  • Dry-dock + survey scheduler — plan haul-outs and Coast Guard inspections months out
  • SMS / ISM document control module — Safety Management System with ISM-required revision history
  • Enterprise SSO — Google + Azure AD + Okta providers via NextAuth

Also today: blog posts 1, 2, and 3 went live; SEO with JSON-LD structured data and canonical URLs site-wide; sales 1-pager (PDF); Google Search Console walkthrough; status-monitor fixes; LinkedIn post drafts; navbar polish; and a polish sweep across new pages.


2026-04-19 — Cyber rule, ISPS visitor log, insurance vault, bunker

USCG 2025 cyber rule module shipped on the same day the rule's compliance window opens. ISPS visitor-log module at /security covers MARSEC level reporting. Insurance document vault holds policy PDFs, certificates of insurance, and renewal reminders. Bunker / fuel operations module tracks every uplift, blender, and burn rate. Phase 11 user-invite flow (admin to email + role to magic link) and Phase 10 dashboard cockpit + AI SOP onboarding + RACE_OBSERVER shipped.

Also today: SLA doc, status-page runbook, cyber banner on the landing page, demo cyber-event seed, /deep health endpoint, ISPS visitor log SEO, docs index, and fleet-tracking mobile polish. Master TODO filed at docs/MASTER-TODO-2026-04-19.md splitting human vs agent lanes.


2026-04-18 — 30+ feature mega-ship

One commit, thirty-plus features: integrations layer, AI document classification, charter mode for Sub T operators, security hardening pass, full audit-log surface, plus the foundational pieces for everything that landed the rest of the week.


2026-04-17 — Backups + dashboard overhaul

4x-daily backups along the Vultr to Mac-Mini to M1 chain with pre-deploy safety snapshots. Dashboard overhaul ships five new features and the first round of enterprise-polish work.


2026-04-16 — Mariner Onboarding Portal + 12+ features (#11–#30)

Major feature wave from Inspection Simulator (#9) through AIS integration (#30). Highlights:

  • Inspection Simulator — runs an operator through a mock CG-840 inspection and scores them
  • Insurance Compliance Package — auto-generates the binder underwriters ask for
  • Compliance API — public endpoint with API-key auth so customers can pull their own data
  • Multi-Vessel Crew Rotation Planner — Gantt-style view, conflict detection
  • USCG Career Tracker — sea-time accumulator, next-license eligibility
  • Renewals page — every expiring credential, one-click reminder email
  • Mariner Onboarding Portal — invite a new hire, they upload docs, you approve
  • Ship Broker auth, Mariner auto-create, AIS integration — features #28, #29, #30

Also today: password-reset flow, About / Contact / Careers pages, contact-form endpoint, Resend + Cloudflare Email Routing setup, demo-script polish, LinkedIn content, outreach templates, MFA-scope updates in SOC2 docs, lead-count update, OG-image fixes, signup, legal pages, Stripe, Sentry, alerting, 182 maritime leads loaded into the dashboard, and security hardening (port binding, auth gates, security headers, 404 page).


2026-04-15 — Project init: landing + auth + AI services + dashboard

Day one of Binnacle AI. Initial Next.js scaffold, then the core platform on top: landing page, auth (NextAuth credentials provider), the first AI services (POST /api/classify-document and POST /api/sea-service/parse via Claude Vision), the dashboard shell, and the seeded demo data behind it. Production deploy infrastructure (Docker, compose, deploy script) lands the same day so binnacleai.com can go live. Initial 111-company prospect list loaded for outreach.

Eighteen routes, the Prisma schema, and the regulatory-alerts framework all stand up before midnight HST.


Built for evaluation-grade trust