Changelog
What's shipped in MarginLock — features, improvements, and fixes.
April 2026
- feature
Marketing website launch
The marketing site is live. Plans 4, 5, and 6 collapsed into a single shipping surface: the home page, four product-pillar pages, three solutions pages, pricing with localized currency conversion, and the company pages all render from the same compound library that the SaaS app reuses.
Highlights:
- Localized pricing — prices render in the visitor's currency using daily FX snapshots. No client-side fetch.
- Compound components —
Hero,FeatureGrid,MetricsBand,PricingTable, and friends are dual-use. The SaaS app borrows them for empty states. - A11y baseline — every interactive component ships with keyboard navigation
and
aria-*correctness, verified by axe in CI.
See /product for the pillar overview and /pricing for the new pricing surface.
- improvement
Coverage thresholds and unified test layout across packages
Every package and app now enforces explicit coverage thresholds in its Vitest config: 80% lines/branches/functions for frontend code, 90% for backend code, and a 50% per-file floor that prevents one well-tested module from masking a neglected one.
We also moved every package onto the same test layout — co-located
*.test.tsfiles undersrc/, withtests/reserved for integration suites. The CI job now reports a single coverage summary per workspace instead of stitching results from four different shapes. - feature
Marketing design system and compound library
The marketing design system landed today. Beyond the existing UI primitives shared with the SaaS app, the marketing site adds a compound library:
Hero,FeatureGrid,FeatureSpotlight,MetricsBandPricingTable,LogoStrip,QuoteFAQ,Steps,Compare,CTAGradientPanelfor product mock placeholders
Every compound is theme-aware, dark-mode-correct, and uses the same tokens as the SaaS app, so any component we build for marketing can be reused as-is for in-product empty states or onboarding flows.
- feature
apps/web skeleton bootstrapped
The marketing surface now has a home of its own.
apps/web/is a separate Next.js 15 app with the App Router, i18n routing baked in, the shared theme provider, the Geist font family, and a marketing-style nav and footer.It deploys to a Vercel preview on every PR and to production on every merge to
main. The SaaS app atapp.marginlock.iois unchanged; this is a separate deploy target so we can iterate on landing-page content without rebuilding the authenticated bundle. - feature
Warehouse inventory page
The warehouse pillar gained a new top-level surface today: the warehouse-inventory page. It pivots stock three ways:
- By location — every active warehouse with current on-hand counts and reserved-for-shipment counts side by side.
- By SKU — each SKU's distribution across all warehouses, with a single "where is it?" lookup.
- By aging band — fresh, 30+, 60+, 90+, and stale buckets, so slow-moving inventory is visible at a glance.
The page hangs off the existing warehouse navigation. Multi-warehouse plans get the cross-warehouse view; single-warehouse plans see the same layout collapsed to a single column.
- feature
Fee detector forecasting
The fee engine just learned to look forward. After every settlement closes, MarginLock runs each detector against the last-cycle data and ranks them by expected hit rate on the next settlement.
The forecast surfaces in two places:
- The fee dashboard now shows a "next-cycle outlook" card with the top three detectors ordered by expected adjustments.
- The alert center uses the same forecast to pre-stage the watch list, so ops teams know what to look for before the settlement lands.
Forecasts are advisory, not auto-acting. The detectors still run for real on the next settlement and only the actual hits drive
FeeAdjustmentrows. - improvement
Postgres LISTEN/NOTIFY for the worker job queue
The worker fleet used to poll the
Jobtable on a 5-second interval. As the SP-API integration grew, that poll started to dominate the database's read load — and the 5-second floor on job pickup time was visible in the UI.Workers now subscribe to a Postgres
LISTENchannel that the API processNOTIFYs when a job is enqueued. Pickup latency dropped from ~5 seconds to sub-100 ms in steady state, and database CPU dropped about a third in production at idle.