@koda-sl/baker-cli 0.548.0 → 0.549.0
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/dist/cli.js +1 -1
- package/dist/{inspiration-CSN3AXDD.js → inspiration-573KZNQA.js} +5 -5
- package/dist/inspiration-573KZNQA.js.map +1 -0
- package/dist/{landing-ZHDHE65Z.js → landing-EAEMVCED.js} +2 -2
- package/dist/{scrape-3PWNMK4D.js → scrape-U6DIREQ2.js} +3 -3
- package/dist/scrape-U6DIREQ2.js.map +1 -0
- package/dist/{search-BR5KK7BE.js → search-37JQZPX3.js} +8 -4
- package/dist/search-37JQZPX3.js.map +1 -0
- package/dist/{view-VFZUL5UL.js → view-OZLXM7R6.js} +22 -10
- package/dist/view-OZLXM7R6.js.map +1 -0
- package/package.json +1 -1
- package/dist/inspiration-CSN3AXDD.js.map +0 -1
- package/dist/scrape-3PWNMK4D.js.map +0 -1
- package/dist/search-BR5KK7BE.js.map +0 -1
- package/dist/view-VFZUL5UL.js.map +0 -1
- /package/dist/{landing-ZHDHE65Z.js.map → landing-EAEMVCED.js.map} +0 -0
|
@@ -25,7 +25,7 @@ import path from "path";
|
|
|
25
25
|
import { defineCommand } from "citty";
|
|
26
26
|
registerSchema({
|
|
27
27
|
command: "landing.inspiration.search",
|
|
28
|
-
description: "Search the shared library of real landing-page sections for reference before you design. Start here: baker landing inspiration search 'pricing with a monthly/annual toggle'. Returns the idea behind each section plus a downloaded screenshot
|
|
28
|
+
description: "Search the shared library of real landing-page sections for reference before you design. Start here: baker landing inspiration search 'pricing with a monthly/annual toggle'. Returns the idea behind each section plus a downloaded screenshot to look at through the visual-check subagent. Defaults to this company's saved sections; pass --scope all for the whole library.",
|
|
29
29
|
args: {
|
|
30
30
|
query: { type: "string", description: "What you want to see, in plain English", required: false },
|
|
31
31
|
type: {
|
|
@@ -121,6 +121,9 @@ async function downloadShots(results) {
|
|
|
121
121
|
);
|
|
122
122
|
return saved;
|
|
123
123
|
}
|
|
124
|
+
function searchShotsHint(count) {
|
|
125
|
+
return `${count} screenshot${count === 1 ? "" : "s"} saved to .baker/inspiration/ \u2014 look at them through the visual-check subagent (the paths and what you need to decide) before deciding, not by Reading them yourself: every image you Read is re-sent on every later request.`;
|
|
126
|
+
}
|
|
124
127
|
var searchCommand = defineCommand({
|
|
125
128
|
meta: {
|
|
126
129
|
name: "search",
|
|
@@ -198,7 +201,7 @@ var searchCommand = defineCommand({
|
|
|
198
201
|
if (rows.length > 0 && data.moreInFullLibrary > 0) {
|
|
199
202
|
hints.push(`${data.moreInFullLibrary} more match in the full library \u2014 re-run with --scope all.`);
|
|
200
203
|
}
|
|
201
|
-
if (shots.size > 0) hints.push(
|
|
204
|
+
if (shots.size > 0) hints.push(searchShotsHint(shots.size));
|
|
202
205
|
writeJson({
|
|
203
206
|
ok: true,
|
|
204
207
|
data: {
|
|
@@ -219,6 +222,7 @@ var searchCommand = defineCommand({
|
|
|
219
222
|
});
|
|
220
223
|
export {
|
|
221
224
|
buildSearchBody,
|
|
222
|
-
searchCommand
|
|
225
|
+
searchCommand,
|
|
226
|
+
searchShotsHint
|
|
223
227
|
};
|
|
224
|
-
//# sourceMappingURL=search-
|
|
228
|
+
//# sourceMappingURL=search-37JQZPX3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/landing/inspiration/search.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { InspirationSearchRequest, InspirationSearchResponse } from \"@baker/api/landing-library\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../../client.ts\";\nimport { writeJson } from \"../../../output.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { favoritesScopeHints, INSPIRATION_HINTS, parseNumber, reportError, splitList } from \"./shared.ts\";\nimport { downloadReadableShot, READABLE_SHOT } from \"./shot.ts\";\n\nregisterSchema({\n command: \"landing.inspiration.search\",\n description:\n \"Search the shared library of real landing-page sections for reference before you design. Start here: baker landing inspiration search 'pricing with a monthly/annual toggle'. Returns the idea behind each section plus a downloaded screenshot to look at through the visual-check subagent. Defaults to this company's saved sections; pass --scope all for the whole library.\",\n args: {\n query: { type: \"string\", description: \"What you want to see, in plain English\", required: false },\n type: {\n type: \"string\",\n description: \"Comma list of section types: hero,pricing,faq,testimonials,…\",\n required: false,\n },\n composition: {\n type: \"string\",\n description: \"Comma list of composition patterns (references/composition.md)\",\n required: false,\n },\n register: {\n type: \"string\",\n description: \"Comma list of visual registers: dev-tool-minimal,luxury-high-end,…\",\n required: false,\n },\n interaction: { type: \"string\", description: \"Comma list of interaction patterns\", required: false },\n motion: {\n type: \"string\",\n description: \"Comma list of motion kinds: scroll-reveal,marquee,parallax,…\",\n required: false,\n },\n media: { type: \"string\", description: \"Comma list of media kinds\", required: false },\n device: { type: \"string\", description: \"Comma list of content devices\", required: false },\n theme: { type: \"string\", description: \"light | dark | mixed\", required: false },\n \"max-rank\": {\n type: \"number\",\n description: \"Show>Tell rank ceiling 1-7; 3 means 'rank 3 or better'\",\n required: false,\n },\n \"min-craft\": { type: \"number\", description: \"Craft floor 0-1\", required: false },\n \"min-fidelity\": {\n type: \"number\",\n description: \"Only sections whose markup reproduces this well (0-1)\",\n required: false,\n },\n domain: { type: \"string\", description: \"Restrict to one site\", required: false },\n \"similar-to\": {\n type: \"string\",\n description: \"Section id — find sections that look like this one\",\n required: false,\n },\n scope: { type: \"string\", description: \"favorites (default) | all\", required: false },\n limit: { type: \"number\", description: \"Max results (default 8)\", required: false },\n \"no-images\": { type: \"boolean\", description: \"Skip downloading screenshots\", required: false },\n full: {\n type: \"boolean\",\n description:\n \"Add every classification facet (theme, density, rank, interactions, media, devices, tags, headline)\",\n required: false,\n },\n },\n});\n\nexport function buildSearchBody(args: Record<string, unknown>): InspirationSearchRequest {\n const body: InspirationSearchRequest = {};\n const setList = (key: keyof InspirationSearchRequest, value: unknown) => {\n const list = splitList(value as string | undefined);\n if (list) Object.assign(body, { [key]: list });\n };\n\n if (args.query) body.query = String(args.query);\n if (args[\"similar-to\"]) body.similarToSectionId = String(args[\"similar-to\"]);\n setList(\"sectionType\", args.type);\n setList(\"composition\", args.composition);\n setList(\"visualRegister\", args.register);\n setList(\"interaction\", args.interaction);\n setList(\"motion\", args.motion);\n setList(\"mediaKind\", args.media);\n setList(\"contentDevice\", args.device);\n if (args.theme) body.theme = String(args.theme) as InspirationSearchRequest[\"theme\"];\n if (args.domain) body.domain = String(args.domain);\n\n const maxRank = parseNumber(args[\"max-rank\"] as string | undefined);\n if (maxRank !== undefined) body.maxShowTellRank = maxRank;\n const minCraft = parseNumber(args[\"min-craft\"] as string | undefined);\n if (minCraft !== undefined) body.minCraftScore = minCraft;\n const minFidelity = parseNumber(args[\"min-fidelity\"] as string | undefined);\n if (minFidelity !== undefined) body.minFidelity = minFidelity;\n const limit = parseNumber(args.limit as string | undefined);\n body.limit = limit ?? 8;\n body.scope = args.scope === \"all\" ? \"all\" : \"favorites\";\n return body;\n}\n\n/**\n * Put the screenshots on disk.\n *\n * The whole library is a visual one, and an agent that can only read a text\n * description of a section is working from exactly the second-hand doctrine this\n * was built to replace. Downloading each hit so it can be looked at (through visual-check) is the point.\n *\n * At the readable size, not the archive size — see `shot.ts`. This runs at the\n * default limit of eight hits, so the difference is eight 2x PNGs of context\n * against eight design-width renditions.\n */\nasync function downloadShots(results: InspirationSearchResponse[\"results\"]): Promise<Map<string, string>> {\n const dir = path.join(process.cwd(), \".baker\", \"inspiration\");\n const saved = new Map<string, string>();\n await Promise.all(\n results.map(async (result) => {\n const file = await downloadReadableShot(\n result.desktopShotUrl,\n path.join(dir, `${result.id}.${READABLE_SHOT.extension}`),\n );\n if (file) saved.set(result.id, file);\n }),\n );\n return saved;\n}\n\n/**\n * Where to look at the screenshots a search saved: through the visual-check\n * subagent, never a Read on the build thread, where each image rides every\n * later request.\n */\nexport function searchShotsHint(count: number): string {\n return `${count} screenshot${count === 1 ? \"\" : \"s\"} saved to .baker/inspiration/ — look at them through the visual-check subagent (the paths and what you need to decide) before deciding, not by Reading them yourself: every image you Read is re-sent on every later request.`;\n}\n\nexport const searchCommand = defineCommand({\n meta: {\n name: \"search\",\n description:\n \"Search real landing-page sections for reference. Example: baker landing inspiration search 'dark developer hero with a terminal' --register dev-tool-minimal --scope all\",\n },\n args: {\n query: { type: \"positional\", description: \"What you want to see, in plain English\", required: false },\n type: { type: \"string\", description: \"Comma list of section types\", required: false },\n composition: { type: \"string\", description: \"Comma list of composition patterns\", required: false },\n register: { type: \"string\", description: \"Comma list of visual registers\", required: false },\n interaction: { type: \"string\", description: \"Comma list of interaction patterns\", required: false },\n motion: { type: \"string\", description: \"Comma list of motion kinds\", required: false },\n media: { type: \"string\", description: \"Comma list of media kinds\", required: false },\n device: { type: \"string\", description: \"Comma list of content devices\", required: false },\n theme: { type: \"string\", description: \"light | dark | mixed\", required: false },\n \"max-rank\": { type: \"string\", description: \"Show>Tell rank ceiling 1-7\", required: false },\n \"min-craft\": { type: \"string\", description: \"Craft floor 0-1\", required: false },\n \"min-fidelity\": { type: \"string\", description: \"Reproduction-fidelity floor 0-1\", required: false },\n domain: { type: \"string\", description: \"Restrict to one site\", required: false },\n \"similar-to\": { type: \"string\", description: \"Section id to find lookalikes of\", required: false },\n scope: { type: \"string\", description: \"favorites (default) | all\", required: false, default: \"favorites\" },\n limit: { type: \"string\", description: \"Max results (default 8)\", required: false },\n \"no-images\": { type: \"boolean\", description: \"Skip downloading screenshots\", required: false, default: false },\n full: { type: \"boolean\", description: \"Include every classification facet\", required: false, default: false },\n },\n run: async ({ args }) => {\n try {\n const body = buildSearchBody(args as Record<string, unknown>);\n const data = await apiPost<InspirationSearchResponse>(\"/api/landing-inspiration/search\", body);\n const results = Array.isArray(data?.results) ? data.results : [];\n const shots = (args[\"no-images\"] as boolean) ? new Map<string, string>() : await downloadShots(results);\n\n const full = args.full as boolean;\n const rows = results.map((result) => ({\n id: result.id,\n // The id `page` takes. Its own schema says \"from a search result's source\n // id\", and until this line no projection emitted one — so the ordering\n // view could only be reached straight after `add`, never from a search.\n page_id: result.sourceId,\n section: result.sectionType,\n composition: result.composition,\n look: result.visualRegister,\n motion: result.motionSummary,\n why_it_works: result.whyItWorks,\n craft: Number(result.craftScore?.toFixed?.(2) ?? result.craftScore),\n fidelity: result.fidelity,\n domain: result.domain,\n // Only worth saying when it means something: >1 marks a section the site\n // reuses across its pages, which is a stronger signal than a one-off.\n ...(result.pageCount > 1 ? { used_on_pages: result.pageCount } : {}),\n // With --no-images there is no file, so hand back the URL instead. A row\n // with neither is a section the agent is asked to judge sight unseen,\n // which is the one thing a visual library must never produce.\n ...((args[\"no-images\"] as boolean)\n ? { screenshot_url: result.desktopShotUrl ?? null }\n : { screenshot: shots.get(result.id) ?? null }),\n ...(full\n ? {\n theme: result.theme,\n density: result.density,\n show_tell_rank: result.showTellRank,\n interactions: result.interactions,\n media: result.mediaKinds,\n devices: result.contentDevices,\n tags: result.tags,\n headline: result.headline,\n source_url: result.sourceUrl,\n }\n : {}),\n }));\n\n const hints = [INSPIRATION_HINTS.adapt];\n // A thin favorites result is explained by the state of the saved set, not\n // by the search — and the three states it can be in call for opposite\n // next moves. The scope is never widened here; it is only made legible.\n const scopeHints = body.scope === \"favorites\" ? favoritesScopeHints(data.favoritesHealth, rows.length) : [];\n if (scopeHints.length > 0) {\n hints.push(...scopeHints);\n } else if (rows.length === 0) {\n hints.push(\n body.scope === \"favorites\"\n ? \"No matches in this company's saved sections. Retry with --scope all to search the whole library, or add a page with `baker landing inspiration add <url>`.\"\n : \"No matches. Loosen the filters, or add reference pages with `baker landing inspiration add <url>`.\",\n );\n }\n if (rows.length > 0 && data.moreInFullLibrary > 0) {\n hints.push(`${data.moreInFullLibrary} more match in the full library — re-run with --scope all.`);\n }\n if (shots.size > 0) hints.push(searchShotsHint(shots.size));\n\n writeJson({\n ok: true,\n data: {\n results: rows,\n scope: data.scope,\n more_in_full_library: data.moreInFullLibrary,\n total: data.total,\n // Only present when there was something to explain, so a healthy\n // search pays nothing for it.\n ...(data.favoritesHealth ? { saved_pages: data.favoritesHealth } : {}),\n },\n hints,\n });\n } catch (error) {\n reportError(error);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -23,7 +23,7 @@ import path from "path";
|
|
|
23
23
|
import { defineCommand } from "citty";
|
|
24
24
|
registerSchema({
|
|
25
25
|
command: "landing.inspiration.view",
|
|
26
|
-
description: "Everything known about one section: composition, motion, design tokens, the copy it uses, why it works, and what must change to make it yours. Downloads the desktop and mobile screenshots plus the motion filmstrip
|
|
26
|
+
description: "Everything known about one section: composition, motion, design tokens, the copy it uses, why it works, and what must change to make it yours. Downloads the desktop and mobile screenshots plus the motion filmstrip, to look at through the visual-check subagent.",
|
|
27
27
|
args: {
|
|
28
28
|
id: { type: "string", description: "Section id from search", required: true },
|
|
29
29
|
full: {
|
|
@@ -33,10 +33,24 @@ registerSchema({
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
|
+
function viewShotHints(shots) {
|
|
37
|
+
const hints = [];
|
|
38
|
+
if (shots.desktop) {
|
|
39
|
+
hints.push(
|
|
40
|
+
`Look at ${shots.desktop} through the visual-check subagent (the path and what you need to learn) before you build \u2014 the description is not the section \u2014 not by Reading it yourself: every image you Read is re-sent on every later request.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (shots.filmstrip) {
|
|
44
|
+
hints.push(
|
|
45
|
+
`${shots.filmstrip} shows this section animating in, six frames left-to-right then top-to-bottom, with the elapsed time on each. If you want the motion, not just the layout, ask visual-check about it.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return hints;
|
|
49
|
+
}
|
|
36
50
|
var viewCommand = defineCommand({
|
|
37
51
|
meta: {
|
|
38
52
|
name: "view",
|
|
39
|
-
description: "Full detail for one reference section. Example: baker landing inspiration view k57abc\u2026 \u2014
|
|
53
|
+
description: "Full detail for one reference section. Example: baker landing inspiration view k57abc\u2026 \u2014 look at the screenshots it saves (through the visual-check subagent) before you build."
|
|
40
54
|
},
|
|
41
55
|
args: {
|
|
42
56
|
id: { type: "positional", description: "Section id from search", required: true },
|
|
@@ -61,15 +75,12 @@ var viewCommand = defineCommand({
|
|
|
61
75
|
]);
|
|
62
76
|
const full = args.full;
|
|
63
77
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
64
|
-
|
|
78
|
+
const [desktopHint, filmstripHint] = viewShotHints({ desktop, filmstrip });
|
|
79
|
+
if (desktopHint) hints.push(desktopHint);
|
|
65
80
|
hints.push("Need the mechanics? `baker landing inspiration code <id>` writes the standalone HTML+CSS to disk.");
|
|
66
81
|
const fidelity = fidelityHint(section.fidelity);
|
|
67
82
|
if (fidelity) hints.push(fidelity);
|
|
68
|
-
if (
|
|
69
|
-
hints.push(
|
|
70
|
-
`${filmstrip} shows this section animating in, six frames left-to-right then top-to-bottom, with the elapsed time on each. Read it if you want the motion, not just the layout.`
|
|
71
|
-
);
|
|
72
|
-
}
|
|
83
|
+
if (filmstripHint) hints.push(filmstripHint);
|
|
73
84
|
writeJson({
|
|
74
85
|
ok: true,
|
|
75
86
|
data: {
|
|
@@ -116,6 +127,7 @@ var viewCommand = defineCommand({
|
|
|
116
127
|
}
|
|
117
128
|
});
|
|
118
129
|
export {
|
|
119
|
-
viewCommand
|
|
130
|
+
viewCommand,
|
|
131
|
+
viewShotHints
|
|
120
132
|
};
|
|
121
|
-
//# sourceMappingURL=view-
|
|
133
|
+
//# sourceMappingURL=view-OZLXM7R6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/landing/inspiration/view.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { InspirationSectionResponse } from \"@baker/api/landing-library\";\nimport { defineCommand } from \"citty\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeJson } from \"../../../output.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { fidelityHint, INSPIRATION_HINTS, reportError } from \"./shared.ts\";\nimport { downloadReadableShot, READABLE_SHOT } from \"./shot.ts\";\n\nregisterSchema({\n command: \"landing.inspiration.view\",\n description:\n \"Everything known about one section: composition, motion, design tokens, the copy it uses, why it works, and what must change to make it yours. Downloads the desktop and mobile screenshots plus the motion filmstrip, to look at through the visual-check subagent.\",\n args: {\n id: { type: \"string\", description: \"Section id from search\", required: true },\n full: {\n type: \"boolean\",\n description:\n \"Add the classification facets (theme, density, rank, interactions, media, devices, tags) and the reproduction notes\",\n required: false,\n },\n },\n});\n\n/**\n * Where to look at what `view` saved: through the visual-check subagent, never\n * a Read on the build thread, where each image rides every later request.\n * Returns the desktop hint then the filmstrip hint, each absent without its file.\n */\nexport function viewShotHints(shots: { desktop: string | null; filmstrip: string | null }): string[] {\n const hints: string[] = [];\n if (shots.desktop) {\n hints.push(\n `Look at ${shots.desktop} through the visual-check subagent (the path and what you need to learn) before you build — the description is not the section — not by Reading it yourself: every image you Read is re-sent on every later request.`,\n );\n }\n if (shots.filmstrip) {\n hints.push(\n `${shots.filmstrip} shows this section animating in, six frames left-to-right then top-to-bottom, with the elapsed time on each. If you want the motion, not just the layout, ask visual-check about it.`,\n );\n }\n return hints;\n}\n\nexport const viewCommand = defineCommand({\n meta: {\n name: \"view\",\n description:\n \"Full detail for one reference section. Example: baker landing inspiration view k57abc… — look at the screenshots it saves (through the visual-check subagent) before you build.\",\n },\n args: {\n id: { type: \"positional\", description: \"Section id from search\", required: true },\n full: {\n type: \"boolean\",\n description: \"Include classification facets and reproduction notes\",\n required: false,\n default: false,\n },\n },\n run: async ({ args }) => {\n try {\n const id = args.id as string;\n const data = await apiGet<InspirationSectionResponse>(\"/api/landing-inspiration/section\", { id });\n const section = data.section;\n const dir = path.join(process.cwd(), \".baker\", \"inspiration\", id);\n\n const ext = READABLE_SHOT.extension;\n const [desktop, mobile, filmstrip] = await Promise.all([\n downloadReadableShot(section.desktopShotUrl, path.join(dir, `desktop.${ext}`)),\n downloadReadableShot(section.mobileShotUrl, path.join(dir, `mobile.${ext}`)),\n downloadReadableShot(section.motionFilmstripUrl, path.join(dir, `motion-filmstrip.${ext}`)),\n ]);\n\n const full = args.full as boolean;\n const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];\n const [desktopHint, filmstripHint] = viewShotHints({ desktop, filmstrip });\n if (desktopHint) hints.push(desktopHint);\n hints.push(\"Need the mechanics? `baker landing inspiration code <id>` writes the standalone HTML+CSS to disk.\");\n const fidelity = fidelityHint(section.fidelity);\n if (fidelity) hints.push(fidelity);\n if (filmstripHint) hints.push(filmstripHint);\n\n writeJson({\n ok: true,\n data: {\n id: section.id,\n page_id: section.sourceId,\n section: section.sectionType,\n composition: section.composition,\n look: section.visualRegister,\n motion: section.motionSummary,\n design_tokens: section.designTokens,\n size: section.boundingBox,\n copy: {\n headline: section.headline,\n subhead: section.subhead,\n ctas: section.ctaLabels,\n proof: section.proofSignals,\n },\n why_it_works: section.whyItWorks,\n adaptation_notes: section.adaptationNotes,\n craft: section.craftScore,\n fidelity: section.fidelity,\n source_url: section.sourceUrl,\n screenshots: { desktop, mobile, motion_filmstrip: filmstrip },\n // Behind --full: exactly the block `search` already gates, plus the\n // reproduction notes, which `code` returns again for the one caller\n // that acts on them. Everything above is what you design *from*;\n // these are how the section was filed and how it rebuilds.\n ...(full\n ? {\n theme: section.theme,\n density: section.density,\n show_tell_rank: section.showTellRank,\n interactions: section.interactions,\n media: section.mediaKinds,\n devices: section.contentDevices,\n tags: section.tags,\n reproduction_notes: section.reproductionNotes,\n }\n : {}),\n },\n hints,\n });\n } catch (error) {\n reportError(error);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/landing/inspiration/index.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\n\nexport const inspirationCommand = defineCommand({\n meta: {\n name: \"inspiration\",\n description: `Reference library of real landing-page sections — look at how good pages actually solve a problem before you design one.\n\nStart here: \\`baker landing inspiration search \"<what you want to see>\"\\` during research, BEFORE you write the Direction Contract.\n\nThis is inspiration, never a clipboard. Take the mechanism — what the eye hits first, what proof arrives before the ask, how the grid is split. The words are never yours to reuse: shipping a reference's headline is a Tier 0 message-match failure.\n\nSubcommands:\n baker landing inspiration search \"<query>\" — search by look, section type, composition, register or motion; saves screenshots you can Read\n baker landing inspiration view <id> — one section in full: tokens, motion filmstrip, why it works, what to change\n baker landing inspiration code <id> — its standalone HTML+CSS, for structure only\n baker landing inspiration page <id> — a whole page as a sequence: how it orders its sections\n baker landing inspiration sequences \"<q>\" — what follows what across MANY pages: openers, transitions, closers\n baker landing inspiration add <url> — add a page to the library and save it to this company (returns immediately); --refresh re-studies a page that changed\n baker landing inspiration favorites — what this company has saved; the default search scope\n baker landing inspiration favorite <id> — save a section\n baker landing inspiration unfavorite <id> — unsave a section\n baker landing inspiration retry-failed — study again every saved page that failed\n baker landing inspiration scrape <url> — internal/ops: run the capture locally\n\nExamples:\n baker landing inspiration search \"pricing with a monthly/annual toggle\" --max-rank 3\n baker landing inspiration search \"dark developer hero with a terminal\" --register dev-tool-minimal --scope all\n baker landing inspiration search \"testimonial wall with faces and company logos\" --motion scroll-reveal\n baker landing inspiration sequences \"b2b saas pricing page\" --scope all\n baker landing inspiration add https://linear.app\n\nFull guide: __tooling__/docs/tools/baker/landing.md`,\n },\n subCommands: {\n search: () => import(\"./search.ts\").then((m) => m.searchCommand),\n view: () => import(\"./view.ts\").then((m) => m.viewCommand),\n code: () => import(\"./code.ts\").then((m) => m.codeCommand),\n page: () => import(\"./page.ts\").then((m) => m.pageCommand),\n sequences: () => import(\"./sequences.ts\").then((m) => m.sequencesCommand),\n add: () => import(\"./add.ts\").then((m) => m.addCommand),\n favorites: () => import(\"./favorites.ts\").then((m) => m.favoritesCommand),\n favorite: () => import(\"./favorites.ts\").then((m) => m.favoriteCommand),\n unfavorite: () => import(\"./favorites.ts\").then((m) => m.unfavoriteCommand),\n \"retry-failed\": () => import(\"./retry-failed.ts\").then((m) => m.retryFailedCommand),\n scrape: () => import(\"./scrape.ts\").then((m) => m.scrapeCommand),\n },\n});\n"],"mappings":";;;AAAA,SAAS,qBAAqB;AAEvB,IAAM,qBAAqB,cAAc;AAAA,EAC9C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2Bf;AAAA,EACA,aAAa;AAAA,IACX,QAAQ,MAAM,OAAO,sBAAa,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa;AAAA,IAC/D,MAAM,MAAM,OAAO,oBAAW,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,IACzD,MAAM,MAAM,OAAO,oBAAW,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,IACzD,MAAM,MAAM,OAAO,oBAAW,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,IACzD,WAAW,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACxE,KAAK,MAAM,OAAO,mBAAU,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU;AAAA,IACtD,WAAW,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACxE,UAAU,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe;AAAA,IACtE,YAAY,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,iBAAiB;AAAA,IAC1E,gBAAgB,MAAM,OAAO,4BAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,kBAAkB;AAAA,IAClF,QAAQ,MAAM,OAAO,sBAAa,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa;AAAA,EACjE;AACF,CAAC;","names":[]}
|