Meridian

Architecture · App map

Every route, walked from the filesystem

This list is derived from app/**/page.tsx when the page renders, not typed. A route added tomorrow appears here tomorrow — without a description, which is the signal that someone should write one. 25 of 25 currently have one.

How a seller moves through the product

From any page, where can you actually get to?

Fig. 01

Every edge is a link that exists today. Most of them did not until recently — a figure that named an account, a code or a supplier and stopped was the norm, and closing those was the work this section documents.

Pages · 25

RouteAnswersFile
/Home. Global flow map and the full analytics suite, cross-filtered in the browser.app/page.tsx
/account/[family]One account: displace / defend / whitespace, with real incumbents.app/account/[family]/page.tsx
/accountsCovered accounts, ranked by what your portfolio can displace.app/accounts/page.tsx
/analyticsRedirect kept for old links → /.app/analytics/page.tsx
/architectureThis section. How the system is put together.app/architecture/page.tsx
/architecture/appThis page: routes, page graph, portfolio state.app/architecture/app/page.tsx
/architecture/contractsThe payloads: builder, readers, size, and what breaks.app/architecture/contracts/page.tsx
/architecture/engineThe opportunity model, the defect log, and the limits.app/architecture/engine/page.tsx
/architecture/mappingHow products and declarations both become HS6, and what that join loses.app/architecture/mapping/page.tsx
/architecture/pipelineThe Python side: normalization and entity resolution.app/architecture/pipeline/page.tsx
/architecture/runbookWhat to type, in order, from a data drop to a deploy.app/architecture/runbook/page.tsx
/competitionSuppliers shipping your codes to a named buyer.app/competition/page.tsx
/lanxessCustomer-one dashboard: where Lanxess can displace an incumbent.app/lanxess/page.tsx
/lanxess/code/[hs6]One HS6 from Lanxess's seat — who buys it and what Lanxess sells into it.app/lanxess/code/[hs6]/page.tsx
/lanxess/family/[slug]One brand family: reach vs exclusive value, codes, roster.app/lanxess/family/[slug]/page.tsx
/lanxess/product/[uvp]One product: identity, and the opportunity inherited from its code.app/lanxess/product/[uvp]/page.tsx
/opportunitiesEvery HS6 an account imports from a third party, ranked, filterable by play.app/opportunities/page.tsx
/opportunity/[account]/[hs6]One account × one code: the evidence page a seller takes to a call.app/opportunity/[account]/[hs6]/page.tsx
/portfoliosSaved portfolios — what you can sell.app/portfolios/page.tsx
/portfolios/[id]One portfolio's reach, plus the HS6 editor. `draft` is the working copy.app/portfolios/[id]/page.tsx
/productSearch HS6 products by keyword or code.app/product/page.tsx
/product/[hs6]One commodity, analyst view: corridors, transport, company relationships.app/product/[hs6]/page.tsx
/prospectCompanies buying your codes, staged by how much is actually known about them.app/prospect/page.tsx
/setupRedirect kept for old links → /portfolios/draft.app/setup/page.tsx
/supplier/[key]One competing supplier: which codes, which buyers, which of your accounts.app/supplier/[key]/page.tsx

Dynamic routes are not linked because there is no correct default parameter to send you to. Reach them by clicking a row on the page that lists them.

API routes · 4

/api/accountsapp/api/accounts/route.ts
/api/demandapp/api/demand/route.ts
/api/pullapp/api/pull/route.ts
/api/searchapp/api/search/route.ts

Portfolio state

There is no backend and no account. A portfolio — the HS6 codes you can sell, plus your own company name — lives in three localStorage keys and, when shared, in the URL.

KeyHolds
trade-portfolio-v1The working draft, rewritten on every edit so nothing is lost to a refresh. This is what every screen reads.
trade-portfolios-v1Named portfolios kept deliberately, so one person can hold several books of business.
trade-portfolio-active-v1Which saved portfolio the draft was copied from. Using a portfolio copies it into the draft rather than creating a second source of truth.
?p=Base64 of {me, codes[]}. The URL wins over the draft, so a shared link always shows the sender what they saw.
Two things about ?p= worth knowing

Detail pages read it but do not re-emit it, so every link out of one has to append it explicitly. Four links did not, and a forwarded link silently lost the Defend/Displace split on arrival — the failure is invisible, because the page still renders, just as if you sold nothing.

The masthead readout in components/Nav.tsx calls loadPortfolio("") — localStorage only, ignoring the URL. So a recipient opening a shared link sees the page correctly scoped while the header still names their own portfolio. That is deliberate, and it is the one place the two disagree.