@astralkit/mcp 1.5.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @astralkit/mcp
2
+
3
+ The **AstralKit MCP server** — search, preview, and build with the AstralKit UI
4
+ component library from any MCP-capable AI coding tool (Claude Code, Cursor,
5
+ Windsurf, Copilot, …). AstralKit is a premium, design-token-based component
6
+ library; this server lets your agent build **from real library components**
7
+ instead of freestyling look-alike UI.
8
+
9
+ Requires a **Pro or higher** AstralKit subscription. Get an API key at
10
+ <https://astralkit.com/settings>.
11
+
12
+ ## Install / configure
13
+
14
+ The server runs via `npx` — no global install needed. Add it to your MCP client
15
+ config with your API key:
16
+
17
+ ```jsonc
18
+ {
19
+ "mcpServers": {
20
+ "astralkit": {
21
+ "command": "npx",
22
+ "args": ["@astralkit/mcp@latest"],
23
+ "env": { "ASTRALKIT_API_KEY": "ak_your_key_here" }
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ - **Claude Code:** `claude mcp add astralkit -e ASTRALKIT_API_KEY=ak_… -- npx @astralkit/mcp@latest`
30
+ - **Cursor / Windsurf / others:** add the JSON block above to the client's MCP settings.
31
+
32
+ Optional env: `ASTRALKIT_API_URL` (defaults to `https://astralkit.com`; must be HTTPS except localhost).
33
+
34
+ ## The golden path
35
+
36
+ For any UI request the agent should: `get_coding_standards` → `get_design_tokens`
37
+ → `search_components` → `get_preview` → `get_component` (recipe) →
38
+ `install_component` → `get_icons` / `get_setup` → `validate_code` + `review_app`
39
+ → build. The library is the source of truth — install and re-content real
40
+ components; don't hand-write what the library already provides.
41
+
42
+ ## Tools
43
+
44
+ **Discover:** `search_components`, `list_components`, `list_categories`,
45
+ `get_preview`, `install_component`, `search_logos`
46
+ **Build:** `get_component`, `get_coding_standards`, `get_design_tokens`,
47
+ `get_icons`, `get_setup`
48
+ **Structure & quality:** `get_build_standards`, `get_screen_blueprint`,
49
+ `polish_ui`, `validate_code`, `review_app`
50
+ **Boosters** (Plus/Lifetime): `list_boosters`, `get_booster`
51
+
52
+ All tools are read-only. Resources (`astralkit://tokens`, `://rules`, `://icons`,
53
+ `://setup`, `://catalog`) mirror the static references for clients that support
54
+ MCP resources.
55
+
56
+ ## License
57
+
58
+ Proprietary — see `LICENSE`. © Blue Beacon Creative LLC.
package/dist/api.js CHANGED
@@ -35,8 +35,8 @@ async function request(path) {
35
35
  const url = `${apiBase}${path}`;
36
36
  const headers = {
37
37
  'Accept': 'application/json',
38
- 'User-Agent': '@astralkit/mcp/1.0.0',
39
- 'X-AstralKit-CLI': 'mcp-1.0.0',
38
+ 'User-Agent': '@astralkit/mcp/1.7.1',
39
+ 'X-AstralKit-CLI': 'mcp-1.7.1',
40
40
  };
41
41
  if (apiKey) {
42
42
  headers['x-api-key'] = apiKey;
package/dist/auth.js CHANGED
@@ -20,9 +20,11 @@ export async function validatePremiumAccess(apiKey) {
20
20
  if (err.code === 'AUTH_REQUIRED') {
21
21
  throw new AuthError('Invalid or expired API key. Get a new one at https://astralkit.com/settings');
22
22
  }
23
+ // Network/timeout is TRANSIENT — re-throw the original ApiError (NOT an
24
+ // AuthError) so the caller can tell "connectivity blip" apart from "key is
25
+ // invalid" and avoid permanently revoking a valid subscriber.
23
26
  if (err.code === 'NETWORK_ERROR' || err.code === 'TIMEOUT') {
24
- throw new AuthError(`Could not validate API key: ${err.message}\n` +
25
- 'Check your internet connection and try again.');
27
+ throw err;
26
28
  }
27
29
  }
28
30
  throw err;
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAQ9C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAqB;IAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,SAAS,CACjB,wEAAwE;YACxE,wDAAwD;YACxD,wDAAwD;YACxD,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CACjB,iFAAiF;YACjF,oDAAoD,CACrD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACjC,MAAM,IAAI,SAAS,CACjB,6EAA6E,CAC9E,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC3D,MAAM,IAAI,SAAS,CACjB,+BAA+B,GAAG,CAAC,OAAO,IAAI;oBAC9C,+CAA+C,CAChD,CAAC;YACJ,CAAC;QACH,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CACjB,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,SAAS,CACjB,wDAAwD;YACxD,sBAAsB,MAAM,CAAC,IAAI,MAAM;YACvC,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAQ9C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAqB;IAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,SAAS,CACjB,wEAAwE;YACxE,wDAAwD;YACxD,wDAAwD;YACxD,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CACjB,iFAAiF;YACjF,oDAAoD,CACrD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACjC,MAAM,IAAI,SAAS,CACjB,6EAA6E,CAC9E,CAAC;YACJ,CAAC;YACD,wEAAwE;YACxE,2EAA2E;YAC3E,8DAA8D;YAC9D,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC3D,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CACjB,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,SAAS,CACjB,wDAAwD;YACxD,sBAAsB,MAAM,CAAC,IAAI,MAAM;YACvC,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export declare const BUILD_STANDARDS: Record<string, string>;
2
+ export declare const BUILD_STANDARD_TOPICS: string[];
3
+ /** Build the get_build_standards response. No topic -> an index of all topics. */
4
+ export declare function buildStandardsGuide(topic?: string): string;
5
+ //# sourceMappingURL=build-standards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-standards.d.ts","sourceRoot":"","sources":["../../src/data/build-standards.ts"],"names":[],"mappings":"AAqKA,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQlD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAA+B,CAAC;AAYlE,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAa1D"}
@@ -0,0 +1,190 @@
1
+ // Structural & non-visual build standards served by the get_build_standards tool
2
+ // and the astralkit://standards resource. The sibling of rules.ts (visual rules):
3
+ // rules.ts covers tokens/colors/spacing/icons; this covers ARCHITECTURE and the
4
+ // states/error/responsive/radix correctness that make an app "built well" vs messy.
5
+ //
6
+ // Source: docs/CODE_ARCHITECTURE_GUIDE.md, docs/empty-states-guide.md,
7
+ // docs/empty-states-engagement-guide.md, docs/error-handing.md, the radix-research
8
+ // bank, and src/sdk/astralkit/ai-rules.md. Principles kept verbatim; every code
9
+ // example is written in AstralKit conventions (ak-* tokens, Phosphor icons,
10
+ // the existing atoms/empty-state.tsx) so this never contradicts get_coding_standards.
11
+ const ARCHITECTURE = `# Architecture & Separation of Concerns
12
+
13
+ The golden test for every file/function/component: "Can I describe what this does in ONE sentence WITHOUT using 'and'?" If not, split it.
14
+
15
+ ## Atomic design (and the import rule)
16
+ - atoms — smallest building blocks, zero business logic, self-contained (Button, Input, Badge, Spinner, Avatar). Import NOTHING.
17
+ - molecules — 2-4 atoms forming one unit (SearchInput, FormField, NavLink). Import atoms only.
18
+ - organisms — full sections (Header, Sidebar, DataTable, PricingCard, LoginForm). Import atoms + molecules.
19
+ - templates — page layout with slots, no real data.
20
+ - pages — route files (Next.js app/), wire data to templates/organisms.
21
+ RULE: never skip levels upward. An atom CANNOT call an API. An organism is NOT composed entirely of other organisms — prefer composition of smaller parts.
22
+
23
+ ## Separation of concerns — data flows in ONE direction
24
+ Routes -> Services -> Repositories -> Database. Components -> Hooks -> Services. Never sideways, never upward.
25
+ - page.tsx is THIN (wire data + compose; aim < 50 lines). It does not hold business logic.
26
+ - Hooks hold logic, never return JSX. Extract a hook when useState+useEffect do one "thing", logic is reusable, or the file grows from logic (not JSX).
27
+ - Services hold business rules; they call repositories, never the DB/Prisma directly; framework-agnostic (no React).
28
+ - Repositories are the ONLY place DB calls happen; one per entity; map DB types to your own types at the boundary (don't let Prisma types leak through the app).
29
+ - utils are PURE functions (same input -> same output, no side effects), categorized by kind (formatters/validators/transformers/helpers) — never a junk-drawer utils.ts.
30
+
31
+ ## Composition over inheritance
32
+ Build complex UI by combining simple parts, not a god-component with 8 boolean props. Prefer compound components (Card + Card.Header + Card.Content) and asChild composition over prop explosions.
33
+
34
+ ## Presentational vs container
35
+ Presentational (dumb): all data via props, no fetching, no business logic, only UI state (isOpen). Container/hook (smart): fetch, manage state, handle logic, pass down. This is what makes a component reusable and testable.
36
+
37
+ ## File-size limits (hard)
38
+ component 150 · hook 100 · service 200 · repository 150 · utility 100 · ANY file 300 = STOP and refactor now. Approaching a limit means a sub-component, a hook, or a util wants to be extracted.
39
+
40
+ ## Naming & imports
41
+ PascalCase components; 'use' prefix hooks; 'Service'/'Repository' suffixes; SCREAMING_SNAKE constants; 'handle' event handlers; is/has/can/should booleans. Import order: framework -> third-party -> '@/' aliases -> relative -> types. Barrel-export each component folder (index.ts) and import from the barrel, never reach into internals.`;
42
+ const REFACTORING = `# Refactoring a Messy App (do this, don't rewrite)
43
+
44
+ The #1 way AI makes things worse: rewriting a working file "more cleanly" and changing behavior. Don't.
45
+
46
+ ## Golden rules
47
+ - MOVE code, don't REWRITE it. Copy-paste EXACT blocks into new files.
48
+ - Small bites. ONE area at a time. Verify before moving on.
49
+ - Do NOT rename, "optimize", or "clean up" while moving. Do NOT refactor multiple areas at once.
50
+
51
+ ## The incremental process
52
+ 1. SURVEY — list every area that needs work, group into scopes, estimate complexity. Don't start yet.
53
+ 2. PRIORITIZE — start with scopes that have NO dependencies on others; save the interconnected pieces for last.
54
+ 3. REFACTOR ONE SCOPE — analyze (list concerns + line numbers), extract one concern at a time (exact copy + only necessary imports), verify it still works.
55
+ 4. CHECKPOINT — stop, report what moved, confirm it works, then continue.
56
+
57
+ ## What a "scope" is
58
+ The smallest independently-refactorable unit: "the top nav bar", "the user avatar dropdown", "one form", "one data table", "one service". NOT "the entire header" or "all the modals". If a scope has > 3 components, > 2 hooks, > 200 lines, or > 5 new files — split it further.
59
+
60
+ ## Must stay identical while refactoring
61
+ Function signatures, component props + types, state logic, API patterns, error handling, the rendered JSX, classNames/styling, conditional logic. If you're changing any of these, you're rewriting, not refactoring — stop.
62
+
63
+ ## Red flags (stop if you catch yourself)
64
+ Rewriting a function "more efficiently", changing state management, altering prop shapes, "improving" patterns, or touching something unrelated. When two scopes seem tightly coupled or a scope is bigger than expected — pause and ask.
65
+
66
+ End state: when you need to change how something works, you touch ONE file.`;
67
+ const STATE_LIFECYCLE = `# The Four-State Contract
68
+
69
+ EVERY component that renders data (a list, table, feed, card-grid, detail view) must handle all four states. This is the single biggest "looks unfinished / looks broken" tell.
70
+
71
+ 1. LOADING — a skeleton that matches the shape of the real content (not a centered spinner for page content).
72
+ 2. EMPTY — a real empty state (see the empty-states topic), never blank space.
73
+ 3. ERROR — a recovery UI with an action (see the error-handling topic), never a raw error or a white screen.
74
+ 4. POPULATED — the data.
75
+
76
+ Build the EMPTY and ERROR states FIRST, before the populated state — they are part of the component's contract, not an afterthought.
77
+
78
+ The shape, every time:
79
+ if (isLoading) return <Skeleton />
80
+ if (isError) return <ErrorState onRetry={refetch} />
81
+ if (!data?.length) return <EmptyState ... />
82
+ return <List data={data} />
83
+
84
+ Anti-pattern (the "Ghost"): {data.length > 0 && <List/>} with no else branch — the user sees blank space and assumes the app is broken. Always render an explicit empty/loading branch.`;
85
+ const EMPTY_STATES = `# Empty States
86
+
87
+ An empty state is a UX moment, not a placeholder. It answers: what's happening, why, and what to do next.
88
+
89
+ ## Five types — never reuse one design for all
90
+ 1. First-use (zero data) — your onboarding moment. Frame as "ready to begin", not "no data".
91
+ 2. User-cleared — they removed everything. Celebrate completion or offer undo.
92
+ 3. No results — search/filter returned nothing. MUST echo the query ("No results for 'invoic'", not "Nothing here").
93
+ 4. Error — data should exist but failed. Icon (not illustration), and ALWAYS a recovery action.
94
+ 5. Conditional/positive — "No issues found", "All caught up" — a good thing; say so.
95
+
96
+ ## Anatomy (centered in its container, max-w ~28rem text)
97
+ visual (icon or illustration) -> title (what's happening) -> description (why + what to do) -> primary CTA -> optional secondary. Reuse the existing component: src/components/atoms/empty-state.tsx.
98
+
99
+ ## Messaging
100
+ Formula: title = state what's empty; description = why OR what to do + the benefit; CTA = verb + object ("Create project", not "Click here"). Be human, helpful, specific, encouraging, action-oriented. Headline can carry light brand personality; description stays informative.
101
+
102
+ ## Voice — match the emotional temperature
103
+ Don't use the same cheerfulness for an error and a celebration. First-use = warm/encouraging; no-results = neutral/helpful; error = calm/reassuring ("your work is safe, this is on our end"); all-done = briefly celebratory.
104
+
105
+ ## Visual
106
+ Illustration for first-use and positive/celebration and full-page states; icon-only for errors, table/inline empties, and states the user sees often. Keep it on-brand (ak-* colors, no new palette). Subtle entrance animation signals "intentional, not broken" — honor prefers-reduced-motion.
107
+
108
+ ## Seven anti-patterns to avoid
109
+ - Naked Empty: "No data" with no context or path. - Apologizer: "Oops! So sorry!". - Blamer: "You haven't added anything yet". - Dead End: states the problem, no CTA. - Novel: a wall of text. - Confuser: "Error 500 / ECONNREFUSED". - Ghost: rendering nothing at all when empty.`;
110
+ const ERROR_HANDLING = `# Error Handling
111
+
112
+ Three principles: never show raw errors to users; always provide a path forward; fail gracefully and recover automatically where possible. Every error must answer the user's three questions: what happened, is it my fault, what do I do now.
113
+
114
+ ## Classify, then map to a recovery
115
+ - Network/offline -> "You're offline. Check your connection." -> Retry.
116
+ - Timeout / 5xx / 503 -> "Taking longer than expected / temporarily unavailable." -> auto-retry with exponential backoff (1s -> 2s -> 4s, max 3), then a Retry button + status link.
117
+ - 401 / session expired -> redirect to login (preserve the intended destination).
118
+ - 403 -> "You don't have permission." -> go back / contact admin.
119
+ - 404 (user action) -> "This item doesn't exist or was removed." -> go back / search.
120
+ - 400 / validation -> inline field errors (NOT a toast).
121
+ - 429 -> "Slow down — too many requests." -> countdown.
122
+
123
+ ## Boundaries (Next.js App Router)
124
+ Error boundary hierarchy: Root -> Layout -> Page -> Section -> Component — a broken chart must NEVER crash the nav. Every route ships error.tsx + loading.tsx (and not-found.tsx where relevant). Isolate non-critical sections in their own boundary with a fallback so the rest of the page keeps working.
125
+
126
+ ## Rules
127
+ - Never an empty catch: catch (e) {} is forbidden — every catch logs AND updates the UI.
128
+ - Never alert() — use a toast (react-hot-toast / Sonner / Radix Toast). Error toasts do NOT auto-dismiss (manual close); success/info auto-dismiss ~4s; max ~3 at once.
129
+ - Retry network/5xx, NEVER 4xx.
130
+ - Forms: inline errors with aria-invalid + aria-describedby; on submit failure, focus the first error field; preserve the user's input; prevent double-submit.
131
+ - Error UI anatomy: title (plain) + description (is it my fault?) + primary action + optional error ID for support. Use role="alert" / aria-live for dynamic errors.
132
+
133
+ Empty state vs error state: empty = no data yet, encouraging/forward-looking. Error = data should exist but failed, calm/recovery-focused. Don't confuse them.`;
134
+ const RESPONSIVE = `# Responsive & Mobile Navigation
135
+
136
+ Mobile-first: unprefixed classes are the mobile base; add complexity upward with md:/lg:. Type scales UP, never down. 48px touch targets (min-h-ak-control-lg). No horizontal scroll on mobile. Test at 375 / 390 / 768 / 1280.
137
+
138
+ ## The AstralKit layout-primitive trap
139
+ ak-stack / ak-cluster / ak-grid / ak-switcher already set display. A naive md:hidden / md:flex on top of them fights the primitive. Wrap-then-toggle the wrapper, don't toggle display on the primitive itself.
140
+
141
+ ## Navigation by breakpoint (every nav needs a mobile answer)
142
+ - Top bar: desktop = inline links. Mobile = a hamburger that opens a drawer. The desktop links MUST be hidden behind it (e.g. nav links 'hidden md:flex', hamburger 'md:hidden'). A top bar with desktop links and NO mobile menu is the most common responsiveness bug.
143
+ - Mobile menu: a Radix Dialog used as a sheet (w-[85vw] max-w-sm, slides from the side), not a fragile custom dropdown. Trap focus, close on route change and Escape.
144
+ - Mega-menu: full panel on desktop; collapse to a stacked accordion (<details> or a Radix Accordion) inside the mobile drawer.
145
+ - Sidebar: persistent on desktop; on mobile it becomes the drawer (full replacement), toggled by the hamburger.
146
+
147
+ Confirm the mobile menu actually exists and is reachable — most AI-built navs ship desktop-only.`;
148
+ const RADIX = `# Radix UI Correctness
149
+
150
+ AstralKit overlays/menus/forms build on Radix primitives. The common failures:
151
+
152
+ - asChild / Slot: use asChild to merge a primitive's behavior onto YOUR styled element (e.g. <DialogTrigger asChild><Button>…</Button></DialogTrigger>) — exactly one child, which must forward props/ref. Don't double-wrap (a styled button inside a styled button).
153
+ - Dialog/AlertDialog a11y: every Dialog needs a Title (visually-hidden if there's no visible heading) and a description or aria-describedby — otherwise screen readers announce nothing and Radix warns.
154
+ - Focus management: Radius traps focus inside an open overlay and restores it on close. Don't fight it; use onOpenAutoFocus / onCloseAutoFocus to retarget focus deliberately, not to disable it. Keep visible focus rings.
155
+ - Portal + theme: Radix renders overlays in a Portal at <body>, OUTSIDE your themed tree — so the AstralKit theme/dark-mode class may not reach it. Wrap portalled content in the theme context (or apply the data-ak-theme on the portal container) or dropdowns/dialogs render unthemed.
156
+ - Styling: style by state with data-[state=open]/data-[state=checked] attributes, not by toggling classes in JS.
157
+ - Versions: keep all @radix-ui/* (or the unified radix-ui) on one resolved version — mismatched primitive + react versions cause focus/dismiss bugs.`;
158
+ export const BUILD_STANDARDS = {
159
+ architecture: ARCHITECTURE,
160
+ refactoring: REFACTORING,
161
+ 'state-lifecycle': STATE_LIFECYCLE,
162
+ 'empty-states': EMPTY_STATES,
163
+ 'error-handling': ERROR_HANDLING,
164
+ responsive: RESPONSIVE,
165
+ radix: RADIX,
166
+ };
167
+ export const BUILD_STANDARD_TOPICS = Object.keys(BUILD_STANDARDS);
168
+ const TOPIC_BLURBS = {
169
+ architecture: 'atomic design, separation of concerns, layers, file-size limits, naming',
170
+ refactoring: 'the safe incremental process for cleaning up a messy app (move, don\'t rewrite)',
171
+ 'state-lifecycle': 'the loading/empty/error/populated contract every data component must handle',
172
+ 'empty-states': 'the 5 empty-state types, messaging, voice, and 7 anti-patterns',
173
+ 'error-handling': 'error classification, boundaries, toasts, retries, never-empty-catch',
174
+ responsive: 'mobile-first rules + the mobile-menu / mega-menu navigation patterns',
175
+ radix: 'correct Radix usage: asChild, focus, portal theming, a11y, versions',
176
+ };
177
+ /** Build the get_build_standards response. No topic -> an index of all topics. */
178
+ export function buildStandardsGuide(topic) {
179
+ if (topic && BUILD_STANDARDS[topic])
180
+ return BUILD_STANDARDS[topic];
181
+ const index = BUILD_STANDARD_TOPICS.map(t => `- ${t} — ${TOPIC_BLURBS[t]}`).join('\n');
182
+ const unknown = topic ? `\n\n(No topic "${topic}". Returning the index.)` : '';
183
+ return (`# AstralKit Build Standards\n\n` +
184
+ `Structural & correctness rules that make an app "built well", not just visually polished. ` +
185
+ `Call get_build_standards with one topic to get that section:\n\n${index}\n\n` +
186
+ `These complement get_coding_standards (visual rules) and polish_ui (visual revamp). ` +
187
+ `For per-screen-type guidance (dashboard, nav, pricing, auth…) use get_screen_blueprint. ` +
188
+ `To audit existing code against these rules, use review_app.${unknown}`);
189
+ }
190
+ //# sourceMappingURL=build-standards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-standards.js","sourceRoot":"","sources":["../../src/data/build-standards.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,oFAAoF;AACpF,EAAE;AACF,uEAAuE;AACvE,mFAAmF;AACnF,gFAAgF;AAChF,4EAA4E;AAC5E,sFAAsF;AAEtF,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gVA8B2T,CAAC;AAEjV,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;4EAwBwD,CAAC;AAE7E,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;wLAiBgK,CAAC;AAEzL,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;sRAwBiQ,CAAC;AAEvR,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;+JAuBwI,CAAC;AAEhK,MAAM,UAAU,GAAG;;;;;;;;;;;;;iGAa8E,CAAC;AAElG,MAAM,KAAK,GAAG;;;;;;;;;qJASuI,CAAC;AAEtJ,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,YAAY,EAAE,YAAY;IAC1B,WAAW,EAAE,WAAW;IACxB,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,YAAY;IAC5B,gBAAgB,EAAE,cAAc;IAChC,UAAU,EAAE,UAAU;IACtB,KAAK,EAAE,KAAK;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAElE,MAAM,YAAY,GAA2B;IAC3C,YAAY,EAAE,yEAAyE;IACvF,WAAW,EAAE,iFAAiF;IAC9F,iBAAiB,EAAE,6EAA6E;IAChG,cAAc,EAAE,gEAAgE;IAChF,gBAAgB,EAAE,sEAAsE;IACxF,UAAU,EAAE,sEAAsE;IAClF,KAAK,EAAE,qEAAqE;CAC7E,CAAC;AAEF,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,KAAK,IAAI,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAEnE,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,kBAAkB,KAAK,0BAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,OAAO,CACL,iCAAiC;QACjC,4FAA4F;QAC5F,mEAAmE,KAAK,MAAM;QAC9E,sFAAsF;QACtF,0FAA0F;QAC1F,8DAA8D,OAAO,EAAE,CACxE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const SCREEN_BLUEPRINTS: Record<string, string>;
2
+ export declare const SCREEN_TYPES: string[];
3
+ /** Build the get_screen_blueprint response for a screen type. */
4
+ export declare function buildScreenBlueprint(screenType: string): string;
5
+ //# sourceMappingURL=screens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screens.d.ts","sourceRoot":"","sources":["../../src/data/screens.ts"],"names":[],"mappings":"AAoJA,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQpD,CAAC;AAEF,eAAO,MAAM,YAAY,UAAiC,CAAC;AAE3D,iEAAiE;AACjE,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAY/D"}
@@ -0,0 +1,161 @@
1
+ // Per-screen-type UX blueprints served by the get_screen_blueprint tool.
2
+ // Each blueprint = structure + must-haves + anti-patterns + the four-state
3
+ // requirement + which AstralKit pieces to reach for (categories, ready-to-run
4
+ // search_components queries, and polish_ui archetypes). This is the screen-aware
5
+ // companion to get_build_standards (cross-cutting rules) — it tells the agent
6
+ // how THIS kind of screen should be built and what to pull from the library.
7
+ //
8
+ // Source: docs/CODE_ARCHITECTURE_GUIDE.md, docs/empty-states-guide.md,
9
+ // docs/error-handing.md, the radix-research bank, and the real category slugs in
10
+ // src/types/component-filters.ts + src/lib/components/taxonomy.ts.
11
+ const DASHBOARD = `# Screen Blueprint: Dashboard
12
+
13
+ ## Structure (inverted pyramid)
14
+ Global KPIs first (top-left — F/Z scan), then charts/trends, then tabular detail. Persistent app shell: sidebar + top bar around the content canvas.
15
+
16
+ ## Must-haves
17
+ - KPI cards carry name + value + trend + comparison period + timestamp. A number without context is decoration.
18
+ - Keep it scannable: aim <= 5 charts per view and <= 7 data points per chart.
19
+ - Filters are visible and persistent (chips with one-click clear), not buried in a menu.
20
+ - Every data widget honors the four-state contract (skeleton matching the widget shape -> empty -> error -> data). Isolate each widget in its own error boundary so one failed chart never blanks the dashboard.
21
+
22
+ ## Anti-patterns
23
+ 3D charts; pie charts with >5 segments; a wall of equal-weight tiles (no hierarchy); a spinner for the whole page instead of per-widget skeletons; the "Ghost" (blank widget when a query returns nothing).
24
+
25
+ ## AstralKit pieces
26
+ - Categories: sidebars, top-bars, data-display.
27
+ - search_components: "analytics dashboard", "stats overview", "data table".
28
+ - polish_ui archetypes: stat-tile, table, sidebar, top-bar, section-header.`;
29
+ const NAV = `# Screen Blueprint: Navigation (top bar, mega-menu, mobile menu)
30
+
31
+ ## Structure
32
+ Top bar: brand left, primary links center/left, actions (search, account, CTA) right. Mega-menu for grouped destinations. A mobile menu is REQUIRED, not optional.
33
+
34
+ ## Must-haves
35
+ - Desktop links hidden behind a hamburger on mobile: nav links 'hidden md:flex', hamburger 'md:hidden'. The mobile menu must actually exist and be reachable — desktop-only navs are the most common responsiveness bug.
36
+ - Mobile menu = a Radix Dialog used as a side sheet (w-[85vw] max-w-sm): traps focus, closes on Escape AND on route change.
37
+ - Mega-menu collapses to a stacked accordion (<details> or Radix Accordion) inside the mobile drawer.
38
+ - Mark the current page (aria-current="page"); keyboard-operable; visible focus rings.
39
+ - Sticky bars: don't trap scroll; ensure overlay menus sit above content (z-index) and over the themed surface.
40
+
41
+ ## Anti-patterns
42
+ Desktop-only nav (no mobile menu); a custom click-dropdown for the mobile menu instead of a focus-trapping Dialog; mega-menu that overflows the viewport on mobile; low-contrast active state.
43
+
44
+ ## AstralKit pieces
45
+ - Categories: top-bars, sidebars, overlays.
46
+ - search_components: "navigation bar", "mega menu", "mobile menu".
47
+ - polish_ui archetypes: top-bar, sidebar-nav.`;
48
+ const PRICING = `# Screen Blueprint: Pricing
49
+
50
+ ## Structure
51
+ Tier cards in a row (3 is typical), one tier visually emphasized as "most popular", a clear CTA per tier, optional comparison table below, FAQ + final CTA to close.
52
+
53
+ ## Must-haves
54
+ - Strong CTA hierarchy: the recommended tier's button is the primary; others are secondary/outline. Don't make all three equal.
55
+ - Show what each tier includes with check/x rows; keep value (not just price) legible.
56
+ - Billing toggle (monthly/annual) updates prices in place; annual savings called out.
57
+ - Mobile: cards reflow to a single column; the comparison table becomes per-tier stacked cards or a horizontal-scroll with a sticky first column.
58
+ - Trust elements near the CTA (guarantee, social proof, logos via search_logos).
59
+
60
+ ## Anti-patterns
61
+ Equal-weight CTAs (no clear recommendation); a comparison table that horizontally overflows on mobile with no affordance; prices that don't update with the billing toggle; pricing on a dark hero with low-contrast text.
62
+
63
+ ## AstralKit pieces
64
+ - Categories: pricing, footers.
65
+ - search_components: "pricing tiers", "pricing comparison".
66
+ - polish_ui archetypes: pricing card via card, section-header, footer, hero.`;
67
+ const MARKETING = `# Screen Blueprint: Marketing / Landing
68
+
69
+ ## Structure
70
+ Hero (headline + subhead + primary CTA + visual) -> social proof / logo strip -> feature sections (alternating) -> testimonials -> pricing teaser -> FAQ -> final CTA -> footer.
71
+
72
+ ## Must-haves
73
+ - One dominant CTA repeated down the page; secondary CTA is lower-emphasis.
74
+ - 3x+ size hierarchy on the hero headline; restrained weights; 60-30-10 color restraint with the accent reserved for CTAs.
75
+ - Real content, not lorem/placeholder; real logos via search_logos.
76
+ - Sections are responsive (stack on mobile); images use next/image with sizes; honor prefers-reduced-motion on any scroll/entrance animation.
77
+
78
+ ## Anti-patterns
79
+ Multiple competing CTAs of equal weight; a hero that buries the value prop; stock-illustration soup; animation that ignores reduced-motion.
80
+
81
+ ## AstralKit pieces
82
+ - Categories: footers, pricing (teaser).
83
+ - search_components: "hero section", "feature section", "testimonials", "footer".
84
+ - polish_ui archetypes: hero, section-header, footer (flagship — copy the full treatment).`;
85
+ const AUTH = `# Screen Blueprint: Auth (sign in / sign up / reset)
86
+
87
+ ## Structure
88
+ Focused single-column card, centered, minimal chrome (no full app nav). Brand at top, the form, a primary submit, secondary links (forgot password, switch sign-in/up), optional social sign-in.
89
+
90
+ ## Must-haves
91
+ - Inline validation with aria-invalid + aria-describedby; on submit failure, focus the first error field and preserve input. Validation errors are inline, NOT toasts.
92
+ - Distinct, calm error states for wrong credentials / expired session ("Please sign in again") — never a raw error.
93
+ - Submit button shows a loading state and prevents double-submit.
94
+ - Social sign-in buttons use real brand logos (search_logos), 48px targets, accessible labels.
95
+ - After login, return the user to their intended destination.
96
+
97
+ ## Anti-patterns
98
+ Errors shown as toasts instead of inline; no loading state (double-submits); raw auth error text; tiny touch targets; password field with no show/hide.
99
+
100
+ ## AstralKit pieces
101
+ - Categories: forms, overlays.
102
+ - search_components: "login form", "sign up form".
103
+ - polish_ui archetypes: form (flagship), form-field, button.`;
104
+ const ONBOARDING = `# Screen Blueprint: Onboarding
105
+
106
+ ## Structure
107
+ A short stepped flow (progress indicator) or a first-use empty state that guides the very first action. Reduce choices to one clear next step per screen.
108
+
109
+ ## Must-haves
110
+ - Frame the first-use state as opportunity ("Ready to begin / your dashboard is ready for its first item"), not absence ("No data").
111
+ - Reduce first-move anxiety: "you can edit or delete this later", offer a template, keep stakes low.
112
+ - A visible progress sense (checklist or step dots: Account created -> Verify -> Create first project <- you are here).
113
+ - One primary CTA per step; outcome-focused label ("Start organizing", not "Create project"). Optional secondary (start from template).
114
+ - Skippable where reasonable; remembers where the user left off.
115
+
116
+ ## Anti-patterns
117
+ Dumping every feature at once; a blank dashboard with no guidance; multiple equal CTAs; a flow with no progress sense or no skip.
118
+
119
+ ## AstralKit pieces
120
+ - Categories: forms, overlays, utility.
121
+ - search_components: "onboarding", "stepper", "empty state".
122
+ - polish_ui archetypes: form, progress, empty-state, section-header.`;
123
+ const SETTINGS = `# Screen Blueprint: Settings
124
+
125
+ ## Structure
126
+ Sectioned page (account, security, billing, notifications, danger zone) with a sub-nav (left rail or tabs) and one section visible at a time. Each section is a small, self-contained form.
127
+
128
+ ## Must-haves
129
+ - Group related fields; clear section headers; generous vertical rhythm.
130
+ - Dirty/save state: a save button that enables only on change, shows saving/saved feedback, and surfaces errors inline (not a toast for field errors). Destructive actions (delete account) sit in a clearly separated danger zone behind a confirm Dialog.
131
+ - Optimistic or clearly-pending toggles; success confirmation for saved changes (toast OK for global success).
132
+ - Each form field follows the form-field rules (label above font-medium text-ak-sm, 48px control, helper/error below, focus ring).
133
+
134
+ ## Anti-patterns
135
+ One giant form with no sectioning; destructive actions next to normal ones with no confirm; no dirty/save feedback; field errors as toasts.
136
+
137
+ ## AstralKit pieces
138
+ - Categories: forms, sidebars, overlays.
139
+ - search_components: "settings form", "account settings", "tabs".
140
+ - polish_ui archetypes: form, form-field, sidebar-nav, modal.`;
141
+ export const SCREEN_BLUEPRINTS = {
142
+ dashboard: DASHBOARD,
143
+ nav: NAV,
144
+ pricing: PRICING,
145
+ marketing: MARKETING,
146
+ auth: AUTH,
147
+ onboarding: ONBOARDING,
148
+ settings: SETTINGS,
149
+ };
150
+ export const SCREEN_TYPES = Object.keys(SCREEN_BLUEPRINTS);
151
+ /** Build the get_screen_blueprint response for a screen type. */
152
+ export function buildScreenBlueprint(screenType) {
153
+ const bp = SCREEN_BLUEPRINTS[screenType];
154
+ if (bp) {
155
+ return (bp +
156
+ `\n\n---\nEvery data view here owes the four-state contract (get_build_standards topic "state-lifecycle"). ` +
157
+ `INSTALL the named pieces: search_components -> get_preview -> get_component (recipe) -> install_component, then RE-CONTENT them to THIS app (nav, copy, logo, data) and match the app theme. Do not freestyle the screen. Finish with validate_code + review_app.`);
158
+ }
159
+ return (`No blueprint for "${screenType}". Available screen types: ${SCREEN_TYPES.join(', ')}.`);
160
+ }
161
+ //# sourceMappingURL=screens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screens.js","sourceRoot":"","sources":["../../src/data/screens.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,iFAAiF;AACjF,8EAA8E;AAC9E,6EAA6E;AAC7E,EAAE;AACF,uEAAuE;AACvE,iFAAiF;AACjF,mEAAmE;AAEnE,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;4EAiB0D,CAAC;AAE7E,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;8CAkBkC,CAAC;AAE/C,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;6EAkB6D,CAAC;AAE9E,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;2FAiByE,CAAC;AAE5F,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;6DAkBgD,CAAC;AAE9D,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;qEAkBkD,CAAC;AAEtE,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;8DAiB6C,CAAC;AAE/D,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,SAAS,EAAE,SAAS;IACpB,GAAG,EAAE,GAAG;IACR,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,UAAU;IACtB,QAAQ,EAAE,QAAQ;CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAE3D,iEAAiE;AACjE,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,MAAM,EAAE,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,EAAE,EAAE,CAAC;QACP,OAAO,CACL,EAAE;YACF,4GAA4G;YAC5G,mQAAmQ,CACpQ,CAAC;IACJ,CAAC;IACD,OAAO,CACL,qBAAqB,UAAU,8BAA8B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACxF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ export interface ReviewIssue {
2
+ rule: string;
3
+ severity: 'high' | 'medium';
4
+ detail: string;
5
+ fix: string;
6
+ }
7
+ export interface ReviewInput {
8
+ code?: string;
9
+ files?: Record<string, string>;
10
+ screenType?: string;
11
+ }
12
+ export interface ReviewResult {
13
+ valid: boolean;
14
+ issueCount: number;
15
+ issues: ReviewIssue[];
16
+ summary: string;
17
+ }
18
+ export declare function reviewApp(input: ReviewInput): ReviewResult;
19
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAyJD,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CA2C1D"}