A collection of developer-experience improvements that I kept wanting for weeks and finally bundled into a single PR. None of them are flashy; all of them remove daily friction.
/dev/ — command center for every service
A new route at /dev/ that renders a grid of quick links to every external service the project touches: PostHog, Vercel, Xero, GitHub, Stripe, plus placeholders for six more services I'm planning to plug in (SendGrid, Linear, Fly.io, Cloudflare, Stripe Connect, 1Password).
- Dev-mode only. The route is registered conditionally on
PORTAL_DEV_MODE=1, and middleware redirects any request under/dev/*away in production, independently of the env var, as a second layer of safety. - Renders as a simple dashboard card grid — each card has a name, a one-line description of what the service does for the project, and a button that opens the relevant dashboard in a new tab.
- Saves me the "which bookmark folder was Xero in again" problem about fifteen times a day.
macOS Keychain as a secrets fallback
Previously: every secret lived in .env, and I had to remember to keep .env in sync across the Mac mini and my laptop. Error-prone.
Now: honest-cam reads secrets in this order:
- Environment variable.
.envfile.- macOS Keychain via the
securityCLI.
For the Mac mini and my laptop, the Keychain layer means there's a canonical, encrypted, OS-managed place each machine reads from, and .env becomes strictly for dev-only override values. Covered secrets: Anthropic API key, Xero client ID and secret, Stripe keys.
The Keychain read is wrapped in a small helper that silently falls through if the key isn't set — so the same code runs unmodified on Linux or in CI, where Keychain doesn't exist and the env var / .env path handles everything.
Proactive Xero token refresh
The Xero OAuth bug that kept biting me: refresh tokens expire 60 days after last use. If I didn't run a Xero command for two months (easy during heads-down feature work), the next run would hit a 401 and I'd have to re-authorize through the web UI.
Fix: every honestcam xero-* command now proactively refreshes the token at startup, regardless of whether the current access token is about to expire. The refresh itself counts as "use" and resets the 60-day clock. The tradeoff is one extra HTTP call per command invocation, which is fine at this scale.
A small status message fires on refresh so I can see it happened: Xero token refreshed (expires in 30m, refresh window reset to 60d).
Landing page redesign (rolled in)
PR #12 landed the first cut of the GoHighLevel-inspired redesign. This PR carries forward some follow-on tweaks that came out of the live review: tightened hero spacing on mobile, staggered animation timing, and a couple of typographic nits in the dark navy sections.
Vendor mapping fixes
Three new real-world vendor aliases added to the Xero sync mapping that Bamboo House's bills uncovered:
- Waste Management — variations including "WM MIAMI", "Waste Management Inc.", "W.M. of Florida".
- Nobus Group II — property inspection contractor, three filename variants.
- Neighborhood Compliance Services — code enforcement consulting, two variants.
Each one adds rows to the vendor alias YAML; the resolver picks them up automatically on the next sync.
OG screenshots retaken
The OG preview images on the landing pages were showing the pre-redesign layout. Retook them at 1200×630 via Playwright, now matching the current live pages. Every landing page's social preview reflects the new design.
Docs
docs/feature-landing-pages.md— added the update process checklist (carried over from PR #13).docs/feature-vendor-portal.md— notes on the next vendor-facing feature.docs/memory/…— session notes from the review that produced this bundle.
Test plan
- Verify all four landing pages on desktop and mobile.
honestcam xero-sync bamboo-house --dry-run— confirm Keychain fallback kicks in when.envis absent.- Confirm the "token refreshed" message appears on the next Xero command.
- Verify
/dev/is reachable whenPORTAL_DEV_MODE=1and redirects without it. - Re-check OG previews via the Facebook Sharing Debugger.