Imports tradein-mvp/frontend (38 components) to a claude.ai/design design-system project. Synth-entry build (Next.js app, no dist): - overrides/source-kit.mjs: process.env shim for browser IIFE - preview-provider.tsx: seeded TanStack Query provider (mirrors the repo's offline ui-preview client) so fetch-coupled + auth-gated cards render - previews/*.tsx: authored preview compositions (real fixture data) - conventions.md: README header for the design agent - config.json + NOTES.md: reproducible re-sync inputs
5 KiB
5 KiB
design-sync NOTES — tradein-mvp-frontend
Target: tradein-mvp/frontend (NOT the repo-root frontend/, which is the Site-Finder app). Project: gendesign-tradein.
Build gotchas
- No dist / no Storybook → synth-entry mode. The package is a Next.js app, not a lib;
package.jsonhas nomain/module/exports. --entrymust point at a NON-existent dist path (tradein-mvp/frontend/dist/index.js). Two jobs:- PKG_DIR resolution walks up
dirname(--entry)to the real namedpackage.json→ PKG_DIR=tradein-mvp/frontend(without--entry, PKG_DIR defaults tonode_modules/<pkg>which doesn't self-install → ENOENT crash). - The path being absent makes
resolveDistEntry(soft)return null →synthEntry=true→deriveComponentsFromSrcdiscovers components fromsrc/. A path that EXISTS (e.g. package.json) suppresses synth mode →[ZERO_MATCH]tokens-only.
- PKG_DIR resolution walks up
cfg.*path fields are PACKAGE-relative (relative to PKG_DIR), not repo-relative. srcDir=src, cssEntry=src/components/trade-in/trade-in.css, tokensGlob=src/app/globals.css.--node-modules tradein-mvp/frontend/node_modules(react + @types/react live there).
Styling
- Tokens in
src/app/globals.css(:root{--bg-app,--accent,…}); component CSS insrc/components/trade-in/trade-in.css(2277 lines). Manrope via remote Google Fonts@import(→[FONT_REMOTE], no action).
Re-sync risks
- Synth scan over-includes non-component PascalCase exports (51 found vs ~37 files) — prune with
componentSrcMap: {Name: null}as identified. - Components are app-coupled (next/*, TanStack Query, data hooks); many need providers/mock props to render → expect floor cards / authored previews with composed props.
Authoring (38 components, all authored-good)
- Import contract: preview imports
{X} from 'tradein-mvp-frontend'(mapped to window.TradeInUI bundle) + data from./_fixtures(re-exports the repo's offlineapp/ui-preview/estimate/fixture.ts). Type imports erased. - Provider = seeded
PreviewProvider(.design-sync/preview-provider.tsx, wired viacfg.extraEntries+cfg.provider). Mirrorsapp/ui-preview/estimate/page.tsx's seeded QueryClient: pre-fills["auth","me"](fake admin user) + the estimate sub-queries (placement-history, house-analytics, sell-time-sensitivity, cian-price-changes=[], sales-vs-listings). This is what makes fetch-coupled cards (StreetDealsCard, HouseAnalyticsSection, PlacementHistoryCard) and auth-gated ones (RouteGuard, UserMenu) render offline.- CRITICAL: an extraEntries module must NOT import anything that reads
process.envat module top-level (e.g.@/lib/useMe→@/lib/api) — extraEntries evaluate BEFORE the synth-entry.pkg-shim.mjs, soprocessis undefined and the whole IIFE aborts (38/38 vanish from the global). The provider hardcodesME_QUERY_KEY = ["auth","me"]instead of importing useMe. - extraEntries path is PACKAGE-relative:
../../.design-sync/preview-provider.tsx. Its@/aliases don't resolve from outside the tsconfig root → use relative../tradein-mvp/frontend/src/...for repo imports inside it.
- CRITICAL: an extraEntries module must NOT import anything that reads
- Chart cards gate on analog count ≥8 (DistributionCard, ExposureCard): the shared fixture has 3 analogs → "not enough data" fallback. Those two previews extend
analogsto 10 realistic ЕКБ lots INLINE in their own preview file (spread FIXTURE_ESTIMATE, override analogs+n_analogs) — never edit_fixtures.ts. - Admin/scraper panels (DataQualitySection, ProviderProxySection, RunsTable, PacingSection, SystemHealthSection) fetch their own data with no repo fixture → they render their real styled LOADING/header state. Graded good as honest states; richer data would need admin fixtures that don't exist in the repo.
- MapCard / MapPicker: Leaflet from unpkg loads in the capture env; OSM raster tiles sometimes don't paint within the screenshot window (external tile fetch) — markers/popup/controls still render. Both graded good. MapPicker is a
createPortalfull-viewport overlay — rendered contained in capture; if a future capture viewport change makes it escape, addcfg.overrides.MapPicker.cardMode/viewport.
Re-sync risks
- The
processshim env defaults live in.design-sync/overrides/source-kit.mjs(synth entry). If the app reads NEWprocess.env.NEXT_PUBLIC_*vars, add them there or components throw. PreviewProviderseed keys are pinned to the fixture'sestimate_idand address/area/rooms — iffixture.tschanges those, updatepreview-provider.tsxto match (else fetch-coupled cards re-floor).- Synth scan re-includes Next route/layout/error files on every build →
componentSrcMapnulls (13 entries) must persist. New app-router pages would need adding. .d.tsprops are weak ([key:string]:unknown) — synth mode has no built types. Real prop contracts live in each component's sourceinterface Props. A realtsup/tsclib build would fix this (recommend if the agent needs strong API contracts).- Grades clear on any
cfg.provider/preview-affecting config change (expected) — re-grade from fresh sheets.