@easybits.cloud/html-tailwind-generator 0.2.140 → 0.2.142
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/{ViewportToggle-Dszv1gsL.d.ts → ViewportToggle-Gns9NOvf.d.ts} +1 -1
- package/dist/buildHtmlV4.js +2 -2
- package/dist/{chunk-7XHJJBGN.js → chunk-7MGKYJTI.js} +2 -2
- package/dist/{chunk-VV5I53WR.js → chunk-DCAQAHSU.js} +39 -2
- package/dist/chunk-DCAQAHSU.js.map +1 -0
- package/dist/{chunk-YKZSLVPV.js → chunk-EIZRTLU6.js} +10 -8
- package/dist/chunk-EIZRTLU6.js.map +1 -0
- package/dist/{chunk-3I6UJ7UH.js → chunk-EP65R6DE.js} +3 -3
- package/dist/{chunk-KXOAEC33.js → chunk-ETWQS7IQ.js} +2 -2
- package/dist/{chunk-IOJ7W4ST.js → chunk-GL74S2H4.js} +52 -16
- package/dist/chunk-GL74S2H4.js.map +1 -0
- package/dist/{chunk-IDJWYC4U.js → chunk-H2YYYKUI.js} +108 -5
- package/dist/chunk-H2YYYKUI.js.map +1 -0
- package/dist/{chunk-6OJXDEL2.js → chunk-QFT3PN3L.js} +18 -10
- package/dist/chunk-QFT3PN3L.js.map +1 -0
- package/dist/{chunk-4I5FFYHG.js → chunk-SJJZEW5W.js} +2 -2
- package/dist/{chunk-OEYKRRM7.js → chunk-ULAQDD23.js} +10 -2
- package/dist/chunk-ULAQDD23.js.map +1 -0
- package/dist/components.d.ts +2 -2
- package/dist/components.js +3 -3
- package/dist/components4.js +1 -1
- package/dist/deploy.d.ts +1 -1
- package/dist/deploy.js +3 -3
- package/dist/directions.d.ts +8 -0
- package/dist/directions.js +2 -2
- package/dist/generate.d.ts +5 -3
- package/dist/generate.js +3 -3
- package/dist/generateDocument.js +3 -3
- package/dist/images.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +10 -10
- package/dist/refine.d.ts +6 -3
- package/dist/refine.js +3 -3
- package/dist/{themes-DNTBHJUH.d.ts → themes-df34nq2_.d.ts} +6 -0
- package/package.json +1 -1
- package/dist/chunk-6OJXDEL2.js.map +0 -1
- package/dist/chunk-IDJWYC4U.js.map +0 -1
- package/dist/chunk-IOJ7W4ST.js.map +0 -1
- package/dist/chunk-OEYKRRM7.js.map +0 -1
- package/dist/chunk-VV5I53WR.js.map +0 -1
- package/dist/chunk-YKZSLVPV.js.map +0 -1
- /package/dist/{chunk-7XHJJBGN.js.map → chunk-7MGKYJTI.js.map} +0 -0
- /package/dist/{chunk-3I6UJ7UH.js.map → chunk-EP65R6DE.js.map} +0 -0
- /package/dist/{chunk-KXOAEC33.js.map → chunk-ETWQS7IQ.js.map} +0 -0
- /package/dist/{chunk-4I5FFYHG.js.map → chunk-SJJZEW5W.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/generate.ts"],"sourcesContent":["import { streamGenerate, dataUrlToImagePart, extractJsonObjects } from \"./streamCore\";\nimport { buildThemePromptContext } from \"./themes\";\nimport type { Section3 } from \"./types\";\n\nexport { extractJsonObjects };\n\nexport const SYSTEM_PROMPT = `You are a world-class web designer who creates AWARD-WINNING landing pages. Your designs win Awwwards, FWA, and CSS Design Awards. You think in terms of visual hierarchy, whitespace, and emotional impact.\n\nRULES:\n- Each section is a complete <section> tag with Tailwind CSS classes\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import, no @tailwind directives)\n- NO JavaScript, only HTML+Tailwind\n- Each section must be independent and self-contained\n- Responsive: mobile-first with sm/md/lg/xl breakpoints\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real-looking content (not Lorem ipsum) — make it specific to the prompt\n\nRESPONSIVE — MANDATORY:\n- EVERY grid: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 (NEVER grid-cols-3 alone)\n- EVERY flex row: flex flex-col md:flex-row (NEVER flex flex-row alone)\n- Text sizes: text-3xl md:text-5xl lg:text-7xl (NEVER text-7xl alone)\n- Images: w-full h-auto object-cover max-w-full\n- Padding: px-4 md:px-8 lg:px-16 (NEVER px-16 alone)\n- Hide decorative on mobile if breaks layout: hidden md:block\n\nIMAGES — CRITICAL:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER use <img> without data-image-query\n- NEVER include a src attribute — the system auto-replaces data-image-query with a real image URL\n- Queries must be generic stock-photo friendly (e.g. \"modern office\" not \"Juan's cybercafe\")\n- For avatar-like elements, use colored divs with initials instead of img tags (e.g. <div class=\"w-10 h-10 rounded-full bg-primary flex items-center justify-center text-on-primary font-bold\">JD</div>)\n\nICONS — use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually — ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nIMAGE OVERLAYS — CRITICAL:\n- When using images as backgrounds or behind text, ALWAYS add a gradient overlay for text readability\n- Pattern: <div class=\"relative\"><img data-image-query=\"...\" alt=\"...\" class=\"absolute inset-0 w-full h-full object-cover\"/><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n- For hero sections with background images: use bg-gradient-to-t from-primary-dark/90 via-primary-dark/50 to-transparent\n- For testimonial/quote backgrounds: use bg-surface/90 backdrop-blur-sm on the card\n\nCOLOR SYSTEM — CRITICAL (READ CAREFULLY):\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent\n- POLARITY of surface tokens (CRITICAL — agents confuse these):\n • bg-surface = the page background (light on light themes, dark on dark themes)\n • bg-surface-alt = a SLIGHT TINT of bg-surface (almost the same lightness — used for cards/alternating rows). NOT a dark surface. Pair with text-on-surface (NOT text-on-primary).\n • bg-surface-deep = a HIGH-CONTRAST DARK SURFACE, brand-independent (use for dark cards/footers/sidebars on light themes). Pair with text-on-surface-deep (light text).\n • bg-secondary = the BRAND'S SECONDARY color (from brandkit). Different from bg-surface-alt — use this when you want a \"second brand color\" feel, not just a tint.\n Common mistake: agents reach for \"bg-surface-alt + text-on-primary\" thinking it's a dark card. That produces white text on near-white background. For dark cards, use bg-surface-deep, bg-primary, or bg-secondary instead.\n- NEVER use hardcoded Tailwind color classes: NO bg-gray-*, bg-black, bg-white, bg-indigo-*, bg-blue-*, bg-purple-*, text-gray-*, text-black, text-white, etc.\n- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color — use bg-primary, not bg-[#userhex].\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL backgrounds MUST use: bg-primary, bg-primary-dark, bg-surface, bg-surface-alt\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary — invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark → use ONLY text-on-primary. On bg-surface or bg-surface-alt → use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary — they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface. text-accent is decorative — use sparingly on bg-surface/bg-surface-alt only.\n- ANTI-PATTERN: NEVER put bg-primary on BOTH the section AND elements inside it. If section is bg-primary, inner cards/elements should be bg-surface. If section is bg-surface, cards can use bg-surface-alt or bg-primary.\n- For gradients: from-primary to-primary-dark, from-surface to-surface-alt\n- For hover: hover:bg-primary-dark, hover:bg-primary-light\n\nCOLOR VARIETY — MANDATORY:\n- ALTERNATE section backgrounds: bg-surface → bg-primary → bg-surface-alt → bg-primary-dark → bg-surface\n- Use bg-accent for at least ONE section (CTA or highlight section)\n- Use bg-secondary for at least ONE section (features or stats)\n- Cards on dark sections (bg-primary, bg-primary-dark) MUST be bg-surface (light cards on dark bg = visual pop)\n- Cards on light sections (bg-surface) can use bg-surface-alt or bg-primary-light\n- Use text-accent for decorative elements: labels, badges, icons, highlights, underlines\n- Use text-secondary for secondary information, tags, category labels\n- Gradients: mix colors creatively — from-primary to-accent for CTAs, from-secondary to-primary for headers\n- Buttons: primary CTA = bg-accent text-on-accent, secondary CTA = bg-secondary text-on-secondary or border-primary\n\nDESIGN PHILOSOPHY — what separates good from GREAT:\n- WHITESPACE is your best friend. Generous padding (py-24, py-32, px-8). Let elements breathe.\n- CONTRAST: mix dark sections with light ones. Alternate bg-primary and bg-surface sections.\n- TYPOGRAPHY: use extreme size differences for hierarchy (text-7xl headline next to text-sm label)\n- DEPTH: overlapping elements, negative margins (-mt-12), z-index layering, shadows\n- ASYMMETRY: avoid centering everything. Use grid-cols-5 with col-span-3 + col-span-2. Offset elements.\n- TEXTURE: use subtle patterns, gradients, border treatments, rounded-3xl mixed with sharp edges\n- Each section should have a COMPLETELY DIFFERENT layout from the others\n\nSECTION LAYOUT — CRITICAL:\n- Each <section> must be full-width (bg goes edge-to-edge). NO max-w on the section itself.\n- Constrain content inside with a wrapper div: <section class=\"bg-primary py-24\"><div class=\"max-w-7xl mx-auto px-4 md:px-8\">...content...</div></section>\n- EVERY section follows this pattern. The <section> handles bg color + vertical padding. The inner <div> handles horizontal padding + max-width.\n\nTESTIMONIALS SECTION:\n- Cards MUST use bg-surface or bg-surface-alt with text-on-surface\n- If section bg is bg-primary or bg-primary-dark, cards MUST be bg-surface (light cards on dark bg)\n- Quote text: text-on-surface, italic\n- Avatar: colored div with initials (bg-accent text-on-primary or bg-primary-light text-on-primary)\n- Name: text-on-surface font-semibold. Role/company: text-on-surface-muted\n- NEVER use same dark bg for both section AND cards\n\nHERO SECTION — your masterpiece:\n- Use a 2-column grid (lg:grid-cols-2) that fills the full height, NOT content floating in empty space\n- Left column: headline + description + CTAs, vertically centered with flex flex-col justify-center\n- Right column: large hero image (data-image-query) filling the column, or a bento-grid of image + stat cards\n- Bold oversized headline (text-4xl md:text-6xl lg:text-7xl font-black leading-tight)\n- Tag/label above headline (uppercase, tracking-wider, text-xs text-accent)\n- Short description paragraph (text-lg text-on-surface-muted, max-w-lg)\n- 2 CTAs: primary (large, px-8 py-4, with → arrow) + secondary (ghost/outlined)\n- Optional: social proof bar below CTAs (avatar stack + \"2,847+ users\" text)\n- Min height: min-h-[90vh] with items-center on the grid so content is vertically centered\n- CRITICAL: the grid must stretch to fill the section height. Use min-h-[90vh] on the grid container itself, not just the section\n- NEVER leave large empty areas — if using min-h-[90vh], content must be centered/distributed within it\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders`;\n\n/** @deprecated Use buildPromptSuffix(prompt) internally. Kept for backward compat. */\nexport const PROMPT_SUFFIX = `\n\nOUTPUT FORMAT: NDJSON — one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Short Label\", \"html\": \"<section>...</section>\"}\n\nGenerate 7-9 sections. Always start with Hero and end with Footer.\nIMPORTANT: Make each section VISUALLY UNIQUE — different layouts, different background colors, different grid structures.\nThink like a premium design agency creating a $50K landing page.\nNO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.`;\n\nfunction buildPromptSuffix(userPrompt: string): string {\n // Extract section count from user prompt (e.g. \"3 secciones\", \"2 sections\", \"dame 4\")\n const countMatch = userPrompt.match(/(\\d+)\\s*(?:secciones?|sections?|bloques?|blocks?|partes?|pages?)/i)\n || userPrompt.match(/(?:genera|generar|crea|crear|haz|hazme|dame|quiero)\\s*(\\d+)/i);\n const count = countMatch ? parseInt(countMatch[1] || countMatch[2] || \"0\") : 0;\n const sectionInstruction = count > 0\n ? `Generate EXACTLY ${count} sections (no more, no less). Always include Hero as first and Footer as last.`\n : `Generate 7-9 sections. Always start with Hero and end with Footer.`;\n\n return `\n\nOUTPUT FORMAT: NDJSON — one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Short Label\", \"html\": \"<section>...</section>\"}\n\n${sectionInstruction}\nIMPORTANT: Make each section VISUALLY UNIQUE — different layouts, different background colors, different grid structures.\nThink like a premium design agency creating a $50K landing page.\nNO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.`;\n}\n\nexport interface GenerateOptions {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n referenceImage?: string;\n extraInstructions?: string;\n systemPrompt?: string;\n model?: string;\n pexelsApiKey?: string;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onSection?: (section: Section3) => void;\n onImageUpdate?: (sectionId: string, html: string) => void;\n /**\n * Called with the HTML of the section currently being streamed, BEFORE it's\n * fully parsed. Fires roughly every ~3 chunks so consumers can show a live\n * element-by-element preview of the section being built. `index` is the\n * 0-based position of this section (= number of already-completed sections).\n *\n * The partial HTML may contain unclosed tags — the browser's innerHTML\n * parser closes them automatically when you inject it into a DOM node.\n */\n onPartialSection?: (index: number, partialHtml: string) => void;\n onDone?: (sections: Section3[]) => void;\n onError?: (error: Error) => void;\n /** Custom-theme palette (hex map: primary, secondary, accent, surface).\n * Required when themeName === \"custom\"; optional otherwise. Used both for\n * prompt context AND for theme-aware sanitization. */\n themeColors?: Record<string, string>;\n /** Theme name (e.g. \"minimal\", \"noche\", \"oceano\", \"custom\") — tells the AI the design mood */\n themeName?: string;\n /** Brand kit info for AI context */\n brandKit?: {\n fonts?: { heading?: string; body?: string };\n mood?: string;\n logoUrl?: string;\n };\n}\n\n/**\n * Generate a landing page with streaming AI + image enrichment.\n */\nfunction buildVisualContext(\n themeName?: string,\n brandKit?: GenerateOptions[\"brandKit\"],\n themeColors?: Record<string, string>\n): string {\n if (!themeName && !brandKit) return \"\";\n\n const lines: string[] = [\"\\n\\n## Visual Context — MANDATORY\"];\n\n if (themeName) {\n // Custom themes get their palette from themeColors; built-in themes look it up by name.\n lines.push(buildThemePromptContext(themeName, themeColors));\n }\n\n if (brandKit?.fonts) {\n const { heading, body } = brandKit.fonts;\n if (heading) lines.push(`- Heading font: use font-family: '${heading}' via inline style on h1-h6`);\n if (body) lines.push(`- Body font: use font-family: '${body}' via inline style on p, li, span`);\n }\n\n if (brandKit?.mood) {\n lines.push(`- Design mood: ${brandKit.mood} — adapt spacing, imagery style, and visual weight to match this mood`);\n }\n\n if (brandKit?.logoUrl) {\n lines.push(`- Brand logo: include <img src=\"${brandKit.logoUrl}\" alt=\"Logo\" class=\"h-8 w-auto\" /> in the navbar/hero area`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport async function generateLanding(options: GenerateOptions): Promise<Section3[]> {\n const {\n prompt,\n referenceImage,\n extraInstructions,\n systemPrompt = SYSTEM_PROMPT,\n themeColors,\n themeName,\n brandKit,\n ...rest\n } = options;\n\n const visualContext = buildVisualContext(themeName, brandKit, themeColors);\n const extra = extraInstructions ? `\\nAdditional instructions: ${extraInstructions}` : \"\";\n const content: any[] = [];\n\n if (referenceImage) {\n const converted = dataUrlToImagePart(referenceImage);\n if (converted) {\n content.push({ type: \"image\", ...converted });\n } else {\n content.push({ type: \"image\", image: referenceImage });\n }\n content.push({\n type: \"text\",\n text: `Generate a landing page for: ${prompt}${extra}\\n\\nIMPORTANT: Use the reference image as a DIRECT visual guide. Replicate its layout structure, grid arrangement, spacing, visual hierarchy, and section organization as closely as possible. Match the number of columns, element positioning, and overall composition. Adapt the content to the prompt but keep the visual DNA of the reference.${buildPromptSuffix(prompt)}`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Generate a landing page for: ${prompt}${extra}${buildPromptSuffix(prompt)}`,\n });\n }\n\n return streamGenerate({\n ...rest,\n systemPrompt: systemPrompt + visualContext,\n userContent: content,\n themeColors,\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDeployHtml
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7MGKYJTI.js";
|
|
4
4
|
|
|
5
5
|
// src/deploy.ts
|
|
6
6
|
async function deployToS3(options) {
|
|
@@ -39,4 +39,4 @@ export {
|
|
|
39
39
|
deployToS3,
|
|
40
40
|
deployToEasyBits
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-SJJZEW5W.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
currentDateLine,
|
|
3
3
|
resolveModel
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H2YYYKUI.js";
|
|
5
5
|
|
|
6
6
|
// src/directions.ts
|
|
7
7
|
import { generateObject, streamText } from "ai";
|
|
@@ -62,6 +62,14 @@ var DesignDirectionSchema = z.object({
|
|
|
62
62
|
// --- Enriched fields (community-valued) ---
|
|
63
63
|
audience: z.string().optional().describe("Target audience, e.g. 'C-level executives', 'technical PMs', 'Gen Z gamers'"),
|
|
64
64
|
voice: z.string().optional().describe("Tone of voice, e.g. 'authoritative and concise', 'warm and inviting', 'playful'"),
|
|
65
|
+
typographyScale: z.object({
|
|
66
|
+
h1: z.string().optional(),
|
|
67
|
+
h2: z.string().optional(),
|
|
68
|
+
h3: z.string().optional(),
|
|
69
|
+
body: z.string().optional(),
|
|
70
|
+
label: z.string().optional(),
|
|
71
|
+
caption: z.string().optional()
|
|
72
|
+
}).optional().describe("Mandatory pixel sizes per role (h1, h2, h3, body, label, caption) \u2014 forces typographic consistency across all pages. Use exact strings like '96px', '6rem', '13px uppercase tracking-wide'"),
|
|
65
73
|
density: z.enum(["spacious", "comfortable", "compact", "dense-editorial"]).optional().describe("Content density: spacious=lots of whitespace, dense-editorial=newspaper-style"),
|
|
66
74
|
borderRadius: z.enum(["sharp", "soft", "rounded", "pill"]).optional().describe("Corner radius: sharp=0, soft=4-6px, rounded=12-16px, pill=999px"),
|
|
67
75
|
shadows: z.enum(["none", "subtle", "soft", "dramatic"]).optional().describe("Shadow style across cards/elements"),
|
|
@@ -214,4 +222,4 @@ export {
|
|
|
214
222
|
generateDirections,
|
|
215
223
|
generateHeroPreview
|
|
216
224
|
};
|
|
217
|
-
//# sourceMappingURL=chunk-
|
|
225
|
+
//# sourceMappingURL=chunk-ULAQDD23.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/directions.ts"],"sourcesContent":["import { generateObject, streamText } from \"ai\";\nimport { z } from \"zod\";\nimport { nanoid } from \"nanoid\";\nimport { resolveModel, currentDateLine } from \"./streamCore\";\n\n/**\n * Premium layout recipes inspired by Gamma. Each recipe is a tight description\n * of structure + content discipline + visual rhythm — the AI follows it as a\n * spec instead of inventing a layout from scratch. Use via `direction.layoutPreset`.\n */\nexport const GAMMA_LAYOUTS: Record<string, string> = {\n cover:\n \"Full-bleed cover. Document title (huge, max 6 words), one-line subtitle (max 12 words), date or author in small caps. Generous whitespace; no body text. Optional accent shape or full-bleed editorial image with dark overlay.\",\n \"section-divider\":\n \"Chapter break. Section number (small) + section title (huge, single line) + one-sentence intent. 70%+ whitespace. No bullets, no images.\",\n agenda:\n \"Numbered list of 3-7 sections. Each row: number (large), section title (medium), one-line description (muted). Minimal decoration, strong vertical rhythm.\",\n \"big-statement\":\n \"Single huge headline (display type, 8-15 words max), one supporting line below in body color. Center-aligned. No bullets, no images. The page is the statement.\",\n \"one-big-stat\":\n \"ONE massive number/percentage (display, takes 50%+ of vertical space) + short label below + one-line implication ('what this means'). NEVER more than one stat. Background can use primary color with on-primary text.\",\n \"stat-grid\":\n \"3 or 4 stats in a grid. Each cell: number (large), label (small caps), one-line implication (muted). Equal weight; the grid IS the page. No paragraphs.\",\n \"two-column\":\n \"50/50 split. Left: headline + 2-4 short paragraphs OR 3-5 disciplined bullets (max 15 words each, active voice). Right: visual (image, icon list, key stat, or pull-quote). Vertical center alignment.\",\n \"three-column\":\n \"Three parallel ideas (e.g. before/during/after, problem/insight/solution, past/present/future). Each column: small icon or number, title, one short paragraph. Equal heights, equal visual weight.\",\n \"image-full-bleed\":\n \"Full-bleed editorial image with dark overlay (bg-black/40 to bg-black/60). Headline (large, white) + one-line caption sit bottom-left or center. No body text. Image MUST use data-image-query.\",\n \"image-text-split\":\n \"50/50 image-text split. One half: full-bleed image with object-cover. Other half: title (large) + 2-3 short paragraphs OR 3-4 bullets. No decorative clutter; the image carries the visual.\",\n \"bento-grid\":\n \"Asymmetric grid (e.g. 2x3 with one tall card and one wide card). Mix of cell types: stat card, image card, quote card, short-text card, icon card. Each cell self-contained. Use border or subtle shadow per cell.\",\n \"card-grid\":\n \"Uniform grid of 3-6 cards (3x2 or 2x3). Each card: icon or small number, title (medium), one-line description. Equal heights. Use the direction's borderRadius and shadows tokens.\",\n \"comparison-table\":\n \"Vs / comparison layout. Two or three columns side by side, each with a title and 4-6 rows of features/attributes. Use accent color to highlight the recommended/winning column. Plain rows; no zebra stripes unless density is dense-editorial.\",\n \"timeline-vertical\":\n \"Chronological events stacked vertically. Each event: date/step (left, accent color), title (medium), one short paragraph. Connecting line on the left. 4-7 events max.\",\n \"process-steps\":\n \"Numbered horizontal or vertical steps with arrows or chevrons between them. Each step: large number, title, one-line description. 3-5 steps. Equal sizing.\",\n quote:\n \"Centered pull-quote. Huge serif type (or display sans if mood is vibrant), 12-25 words. Attribution below in small caps with author name + role. Plenty of whitespace; optional small portrait on the side.\",\n \"closing-cta\":\n \"Final page. Big headline ('what's next', 'thank you', or strong CTA), one-line subtitle, contact info or call-to-action button styling, optional small logo. Generous whitespace; mirror the cover's energy.\",\n};\n\nexport const DesignDirectionSchema = z.object({\n name: z.string().describe(\"Creative direction name, e.g. 'The Editorial'\"),\n tagline: z\n .string()\n .describe(\"One-line vibe description, e.g. 'Bold serif typography meets minimalist space'\"),\n headingFont: z\n .string()\n .describe(\"Google Font name for headings, e.g. 'Playfair Display'\"),\n bodyFont: z\n .string()\n .describe(\"Google Font name for body text, e.g. 'Inter'\"),\n colors: z.object({\n primary: z.string().describe(\"Main brand color as hex, e.g. '#6366f1'\"),\n accent: z.string().describe(\"Accent/CTA color as hex, e.g. '#f59e0b'\"),\n surface: z.string().describe(\"Background surface color as hex, e.g. '#ffffff'\"),\n surfaceAlt: z.string().describe(\"Alt surface (cards, alternating sections) as hex, e.g. '#f8fafc'\"),\n text: z.string().describe(\"Main text color as hex, e.g. '#0f172a'\"),\n }),\n mood: z.enum([\"dark\", \"light\", \"warm\", \"cool\", \"vibrant\"]),\n layoutHint: z\n .string()\n .describe(\"Layout archetype: 'split-screen', 'editorial', 'immersive-gallery', 'community-feed', 'bento-grid', 'magazine'\"),\n\n // --- Gamma-style premium layout preset ---\n layoutPreset: z\n .enum([\n \"cover\",\n \"section-divider\",\n \"agenda\",\n \"big-statement\",\n \"one-big-stat\",\n \"stat-grid\",\n \"two-column\",\n \"three-column\",\n \"image-full-bleed\",\n \"image-text-split\",\n \"bento-grid\",\n \"card-grid\",\n \"comparison-table\",\n \"timeline-vertical\",\n \"process-steps\",\n \"quote\",\n \"closing-cta\",\n ])\n .optional()\n .describe(\"Premium layout preset (Gamma-style). When set, the AI follows that exact layout recipe instead of inventing a layout from scratch.\"),\n\n // --- Enriched fields (community-valued) ---\n audience: z\n .string()\n .optional()\n .describe(\"Target audience, e.g. 'C-level executives', 'technical PMs', 'Gen Z gamers'\"),\n voice: z\n .string()\n .optional()\n .describe(\"Tone of voice, e.g. 'authoritative and concise', 'warm and inviting', 'playful'\"),\n typographyScale: z\n .object({\n h1: z.string().optional(),\n h2: z.string().optional(),\n h3: z.string().optional(),\n body: z.string().optional(),\n label: z.string().optional(),\n caption: z.string().optional(),\n })\n .optional()\n .describe(\"Mandatory pixel sizes per role (h1, h2, h3, body, label, caption) — forces typographic consistency across all pages. Use exact strings like '96px', '6rem', '13px uppercase tracking-wide'\"),\n density: z\n .enum([\"spacious\", \"comfortable\", \"compact\", \"dense-editorial\"])\n .optional()\n .describe(\"Content density: spacious=lots of whitespace, dense-editorial=newspaper-style\"),\n borderRadius: z\n .enum([\"sharp\", \"soft\", \"rounded\", \"pill\"])\n .optional()\n .describe(\"Corner radius: sharp=0, soft=4-6px, rounded=12-16px, pill=999px\"),\n shadows: z\n .enum([\"none\", \"subtle\", \"soft\", \"dramatic\"])\n .optional()\n .describe(\"Shadow style across cards/elements\"),\n imageryStyle: z\n .string()\n .optional()\n .describe(\"Imagery rules, e.g. 'editorial photography only, no clipart'\"),\n contentDiscipline: z\n .string()\n .optional()\n .describe(\"Content rules, e.g. 'max 15 words per bullet, active voice'\"),\n referenceBrands: z\n .array(z.string())\n .optional()\n .describe(\"Brands to take design cues from, e.g. ['Stripe', 'Linear']\"),\n customInstructions: z\n .string()\n .optional()\n .describe(\"Free-form styling instructions appended to the prompt\"),\n});\n\nexport type DesignDirection = z.infer<typeof DesignDirectionSchema>;\n\nexport interface DirectionsOptions {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n count?: number;\n /** \"landing\" generates hero sections, \"document\" generates cover pages */\n product?: \"landing\" | \"document\";\n /** Override the model ID or pass a pre-built LanguageModel object */\n model?: string | import(\"ai\").LanguageModel;\n}\n\nconst DIRECTIONS_SYSTEM = `You are an elite creative director at a top design agency (Pentagram, Sagmeister, Collins).\n\nGiven a project brief, propose design directions that are MAXIMALLY diverse from each other.\n\nRULES:\n- Each direction must feel like a completely DIFFERENT design agency made it\n- Vary these axes: typography style (geometric sans, humanist sans, serif, slab, display/decorative), color mood (dark, light, warm, cool, vibrant), layout approach (editorial, split-screen, immersive, bento-grid, community)\n- Fonts MUST be popular Google Fonts that render well. Good examples:\n SANS: Inter, DM Sans, Space Grotesk, Outfit, Plus Jakarta Sans, Manrope, Sora, Figtree, Urbanist\n SERIF: Playfair Display, Lora, Merriweather, Source Serif 4, Cormorant Garamond, Libre Baskerville, DM Serif Display\n DISPLAY: Bebas Neue, Oswald, Archivo Black, Righteous, Anton, Alfa Slab One\n MONO: JetBrains Mono, Space Mono, IBM Plex Mono\n- NEVER use the same heading font twice\n- NEVER use the same color palette twice\n- AT LEAST one direction must be dark-mode\n- AT LEAST one must use serif headings\n- AT LEAST one must be bold/editorial with huge typography\n- AT LEAST one layoutHint must include \"photo\" (e.g. \"split-screen-photo\", \"immersive-gallery\") — this tells the preview generator to use a real image\n- Colors must be cohesive palettes, not random. Think Dribbble-worthy.\n- Names should be evocative (\"The Chronicle\", \"Neon Pulse\", \"Warm Atelier\")`;\n\n/**\n * Generate N design directions for a landing page.\n * Uses generateObject for type-safe structured output.\n */\nexport async function generateDirections(\n options: DirectionsOptions\n): Promise<DesignDirection[]> {\n const { prompt, count = 4, openaiApiKey, anthropicApiKey, model: modelId } = options;\n\n const model = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId,\n defaultOpenai: \"gpt-4o-mini\",\n defaultAnthropic: \"claude-haiku-4-5-20251001\",\n });\n\n const { object } = await generateObject({\n model,\n schema: z.object({\n directions: z.array(DesignDirectionSchema).describe(`Exactly ${count} design directions`),\n }),\n system: DIRECTIONS_SYSTEM + currentDateLine(),\n prompt: `Project brief: \"${prompt}\"\n\nGenerate ${count} design directions. Make them as visually distinct as possible.`,\n });\n\n return object.directions;\n}\n\n/**\n * Generate a hero section preview for a given design direction.\n * Fast Haiku call, returns raw HTML string with Google Fonts link.\n */\nexport async function generateHeroPreview(options: {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n direction: DesignDirection;\n product?: \"landing\" | \"document\";\n /** Override model ID or pass a pre-built LanguageModel object */\n model?: string | import(\"ai\").LanguageModel;\n /** Called with partial HTML as it streams in */\n onChunk?: (partialHtml: string) => void;\n /** Reference image data URL — AI will replicate this design style */\n referenceImage?: string;\n}): Promise<string> {\n const { prompt, direction, anthropicApiKey, openaiApiKey, product = \"landing\", model: modelId, onChunk, referenceImage } = options;\n\n const model = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId,\n defaultOpenai: \"gpt-4o-mini\",\n defaultAnthropic: \"claude-haiku-4-5-20251001\",\n });\n\n const fontsUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(direction.headingFont).replace(/%20/g, \"+\")}:wght@400;700;900&family=${encodeURIComponent(direction.bodyFont).replace(/%20/g, \"+\")}:wght@400;500;600&display=swap`;\n\n const isDocument = product === \"document\";\n\n const systemPrompt = isDocument\n ? `You create stunning document cover pages with HTML + Tailwind CSS.\nOutput ONLY the raw HTML — no markdown fences, no explanation.\nThe HTML must include a <link> tag for Google Fonts and a <section> tag.\nThis is a LETTER-SIZE document cover page (8.5\" × 11\"), NOT a website hero.\nUse the EXACT fonts and colors provided. The cover must feel premium and print-ready.\nUse real-looking content specific to the brief (Spanish text).\n\nCRITICAL — TEXT MUST BE VISIBLE AND READABLE:\n- The document title MUST be large (text-4xl or bigger), bold, and clearly visible\n- Include: document title, subtitle or description, date, optional author/company name\n- ALL text must have strong contrast against its background — if background is dark, text MUST be white/light\n- NEVER let text disappear into the background\n\nDESIGN APPROACHES (vary across directions):\n- Approach A: Solid color background (bg-[primary]) with large white text — NO image needed\n- Approach B: Split layout — image on one half, text on solid color half\n- Approach C: Full-bleed image WITH a solid overlay (bg-black/50 or bg-[primary]/80) AND white text on top\n- Approach D: Geometric/abstract design with color blocks, no image\n- If the layout hint contains \"photo\", you MUST use Approach B or C (with a real image).\n- Otherwise, choose the approach that best fits the mood. NOT every cover needs a full-bleed image.\n\nIf using images:\n- Pattern: <img data-image-query=\"specific english search query\" alt=\"description\" class=\"absolute inset-0 w-full h-full object-cover\"/>\n- ALWAYS add a dark overlay on top: <div class=\"absolute inset-0 bg-black/50\"></div>\n- Text goes ABOVE the overlay with z-10 and text-white\n- NEVER include a src attribute — ONLY data-image-query\n\nNO buttons or CTAs — this is a print document cover.\nNO emoji — use geometric shapes or SVG icons for decoration.`\n : `You create stunning hero sections with HTML + Tailwind CSS.\nOutput ONLY the raw HTML — no markdown fences, no explanation.\nThe HTML must include a <link> tag for Google Fonts and a <section> tag.\nUse the EXACT fonts and colors provided. The hero must feel premium and polished.\nUse real-looking content specific to the brief (Spanish text).\nInclude: headline (huge), subtitle, 1-2 CTAs, and optionally a hero image via <img data-image-query=\"...\" alt=\"...\" class=\"...\">.\nNEVER use src on img tags. Use data-image-query with English search terms.`;\n\n const sectionInstruction = isDocument\n ? `Generate a document cover page. Use inline style for font-family referencing the Google Fonts.\nStart with: <link href=\"${fontsUrl}\" rel=\"stylesheet\">\nThen a <section class=\"w-[8.5in] h-[11in] relative overflow-hidden\"> sized for letter paper.\nUse the exact hex colors in Tailwind arbitrary values like bg-[${direction.colors.primary}] text-[${direction.colors.text}] etc.\nUse full-bleed backgrounds, geometric accents, elegant typography hierarchy.\nMake it look like a $50K design agency document cover.`\n : `Generate a hero section. Use inline style for font-family referencing the Google Fonts.\nStart with: <link href=\"${fontsUrl}\" rel=\"stylesheet\">\nThen a <section> with min-h-[80vh].\nUse the exact hex colors in Tailwind arbitrary values like bg-[${direction.colors.primary}] text-[${direction.colors.text}] etc.\nMake it look like a $50K agency landing page hero.`;\n\n const textPrompt = `Brief: \"${prompt}\"\n\nDesign direction: \"${direction.name}\" — ${direction.tagline}\nLayout: ${direction.layoutHint}\nHeading font: ${direction.headingFont}\nBody font: ${direction.bodyFont}\nColors: primary=${direction.colors.primary}, accent=${direction.colors.accent}, surface=${direction.colors.surface}, surfaceAlt=${direction.colors.surfaceAlt}, text=${direction.colors.text}\nMood: ${direction.mood}\n\n${sectionInstruction}`;\n\n const messages: any[] = [{\n role: \"user\" as const,\n content: referenceImage\n ? [\n { type: \"image\" as const, image: referenceImage },\n { type: \"text\" as const, text: `Replicate the visual design style, layout, and aesthetic from the reference image above.\\n\\n${textPrompt}` },\n ]\n : textPrompt,\n }];\n\n const result = streamText({\n model,\n system: systemPrompt + currentDateLine(),\n messages,\n });\n\n let html = \"\";\n let chunkCount = 0;\n for await (const chunk of result.textStream) {\n html += chunk;\n chunkCount++;\n if (onChunk && chunkCount % 3 === 0) {\n onChunk(html);\n }\n }\n if (onChunk) onChunk(html);\n\n // Clean markdown fences if present\n html = html.trim();\n if (html.startsWith(\"```\")) {\n html = html.replace(/^```(?:html|xml)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n\n return html;\n}\n"],"mappings":"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","names":[]}
|
package/dist/components.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { C as Canvas, a as CanvasHandle, b as CodeEditor, F as FloatingToolbar, S as SectionList, V as Viewport, c as ViewportToggle } from './ViewportToggle-
|
|
1
|
+
export { C as Canvas, a as CanvasHandle, b as CodeEditor, F as FloatingToolbar, S as SectionList, V as Viewport, c as ViewportToggle } from './ViewportToggle-Gns9NOvf.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import './types-BIpbpCJr.js';
|
|
4
4
|
import 'react/jsx-runtime';
|
|
5
|
-
import './themes-
|
|
5
|
+
import './themes-df34nq2_.js';
|
|
6
6
|
|
|
7
7
|
declare function useUndoStack<T>(): {
|
|
8
8
|
pushUndo: (snapshot: T) => void;
|
package/dist/components.js
CHANGED
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
SectionList,
|
|
6
6
|
ViewportToggle,
|
|
7
7
|
useUndoStack
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-EP65R6DE.js";
|
|
9
|
+
import "./chunk-7MGKYJTI.js";
|
|
10
|
+
import "./chunk-DCAQAHSU.js";
|
|
11
11
|
export {
|
|
12
12
|
Canvas,
|
|
13
13
|
CodeEditor,
|
package/dist/components4.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
LANDING_THEMES,
|
|
3
3
|
buildCustomTheme,
|
|
4
4
|
buildSingleThemeCss
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DCAQAHSU.js";
|
|
6
6
|
|
|
7
7
|
// src/components4/GrapesEditor.tsx
|
|
8
8
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState3, forwardRef, useImperativeHandle } from "react";
|
package/dist/deploy.d.ts
CHANGED
package/dist/deploy.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deployToEasyBits,
|
|
3
3
|
deployToS3
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-SJJZEW5W.js";
|
|
5
|
+
import "./chunk-7MGKYJTI.js";
|
|
6
|
+
import "./chunk-DCAQAHSU.js";
|
|
7
7
|
export {
|
|
8
8
|
deployToEasyBits,
|
|
9
9
|
deployToS3
|
package/dist/directions.d.ts
CHANGED
|
@@ -48,6 +48,14 @@ declare const DesignDirectionSchema: z.ZodObject<{
|
|
|
48
48
|
}>>;
|
|
49
49
|
audience: z.ZodOptional<z.ZodString>;
|
|
50
50
|
voice: z.ZodOptional<z.ZodString>;
|
|
51
|
+
typographyScale: z.ZodOptional<z.ZodObject<{
|
|
52
|
+
h1: z.ZodOptional<z.ZodString>;
|
|
53
|
+
h2: z.ZodOptional<z.ZodString>;
|
|
54
|
+
h3: z.ZodOptional<z.ZodString>;
|
|
55
|
+
body: z.ZodOptional<z.ZodString>;
|
|
56
|
+
label: z.ZodOptional<z.ZodString>;
|
|
57
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, z.core.$strip>>;
|
|
51
59
|
density: z.ZodOptional<z.ZodEnum<{
|
|
52
60
|
spacious: "spacious";
|
|
53
61
|
comfortable: "comfortable";
|
package/dist/directions.js
CHANGED
package/dist/generate.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { S as Section3 } from './types-BIpbpCJr.js';
|
|
|
5
5
|
*/
|
|
6
6
|
declare function extractJsonObjects(text: string): [any[], string];
|
|
7
7
|
|
|
8
|
-
declare const SYSTEM_PROMPT = "You are a world-class web designer who creates AWARD-WINNING landing pages. Your designs win Awwwards, FWA, and CSS Design Awards. You think in terms of visual hierarchy, whitespace, and emotional impact.\n\nRULES:\n- Each section is a complete <section> tag with Tailwind CSS classes\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import, no @tailwind directives)\n- NO JavaScript, only HTML+Tailwind\n- Each section must be independent and self-contained\n- Responsive: mobile-first with sm/md/lg/xl breakpoints\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real-looking content (not Lorem ipsum) \u2014 make it specific to the prompt\n\nRESPONSIVE \u2014 MANDATORY:\n- EVERY grid: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 (NEVER grid-cols-3 alone)\n- EVERY flex row: flex flex-col md:flex-row (NEVER flex flex-row alone)\n- Text sizes: text-3xl md:text-5xl lg:text-7xl (NEVER text-7xl alone)\n- Images: w-full h-auto object-cover max-w-full\n- Padding: px-4 md:px-8 lg:px-16 (NEVER px-16 alone)\n- Hide decorative on mobile if breaks layout: hidden md:block\n\nIMAGES \u2014 CRITICAL:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER use <img> without data-image-query\n- NEVER include a src attribute \u2014 the system auto-replaces data-image-query with a real image URL\n- Queries must be generic stock-photo friendly (e.g. \"modern office\" not \"Juan's cybercafe\")\n- For avatar-like elements, use colored divs with initials instead of img tags (e.g. <div class=\"w-10 h-10 rounded-full bg-primary flex items-center justify-center text-on-primary font-bold\">JD</div>)\n\nICONS \u2014 use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually \u2014 ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nIMAGE OVERLAYS \u2014 CRITICAL:\n- When using images as backgrounds or behind text, ALWAYS add a gradient overlay for text readability\n- Pattern: <div class=\"relative\"><img data-image-query=\"...\" alt=\"...\" class=\"absolute inset-0 w-full h-full object-cover\"/><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n- For hero sections with background images: use bg-gradient-to-t from-primary-dark/90 via-primary-dark/50 to-transparent\n- For testimonial/quote backgrounds: use bg-surface/90 backdrop-blur-sm on the card\n\nCOLOR SYSTEM \u2014 CRITICAL (READ CAREFULLY):\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent\n- NEVER use hardcoded Tailwind color classes: NO bg-gray-*, bg-black, bg-white, bg-indigo-*, bg-blue-*, bg-purple-*, text-gray-*, text-black, text-white, etc.\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL backgrounds MUST use: bg-primary, bg-primary-dark, bg-surface, bg-surface-alt\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface. text-accent is decorative \u2014 use sparingly on bg-surface/bg-surface-alt only.\n- ANTI-PATTERN: NEVER put bg-primary on BOTH the section AND elements inside it. If section is bg-primary, inner cards/elements should be bg-surface. If section is bg-surface, cards can use bg-surface-alt or bg-primary.\n- For gradients: from-primary to-primary-dark, from-surface to-surface-alt\n- For hover: hover:bg-primary-dark, hover:bg-primary-light\n\nCOLOR VARIETY \u2014 MANDATORY:\n- ALTERNATE section backgrounds: bg-surface \u2192 bg-primary \u2192 bg-surface-alt \u2192 bg-primary-dark \u2192 bg-surface\n- Use bg-accent for at least ONE section (CTA or highlight section)\n- Use bg-secondary for at least ONE section (features or stats)\n- Cards on dark sections (bg-primary, bg-primary-dark) MUST be bg-surface (light cards on dark bg = visual pop)\n- Cards on light sections (bg-surface) can use bg-surface-alt or bg-primary-light\n- Use text-accent for decorative elements: labels, badges, icons, highlights, underlines\n- Use text-secondary for secondary information, tags, category labels\n- Gradients: mix colors creatively \u2014 from-primary to-accent for CTAs, from-secondary to-primary for headers\n- Buttons: primary CTA = bg-accent text-on-accent, secondary CTA = bg-secondary text-on-secondary or border-primary\n\nDESIGN PHILOSOPHY \u2014 what separates good from GREAT:\n- WHITESPACE is your best friend. Generous padding (py-24, py-32, px-8). Let elements breathe.\n- CONTRAST: mix dark sections with light ones. Alternate bg-primary and bg-surface sections.\n- TYPOGRAPHY: use extreme size differences for hierarchy (text-7xl headline next to text-sm label)\n- DEPTH: overlapping elements, negative margins (-mt-12), z-index layering, shadows\n- ASYMMETRY: avoid centering everything. Use grid-cols-5 with col-span-3 + col-span-2. Offset elements.\n- TEXTURE: use subtle patterns, gradients, border treatments, rounded-3xl mixed with sharp edges\n- Each section should have a COMPLETELY DIFFERENT layout from the others\n\nSECTION LAYOUT \u2014 CRITICAL:\n- Each <section> must be full-width (bg goes edge-to-edge). NO max-w on the section itself.\n- Constrain content inside with a wrapper div: <section class=\"bg-primary py-24\"><div class=\"max-w-7xl mx-auto px-4 md:px-8\">...content...</div></section>\n- EVERY section follows this pattern. The <section> handles bg color + vertical padding. The inner <div> handles horizontal padding + max-width.\n\nTESTIMONIALS SECTION:\n- Cards MUST use bg-surface or bg-surface-alt with text-on-surface\n- If section bg is bg-primary or bg-primary-dark, cards MUST be bg-surface (light cards on dark bg)\n- Quote text: text-on-surface, italic\n- Avatar: colored div with initials (bg-accent text-on-primary or bg-primary-light text-on-primary)\n- Name: text-on-surface font-semibold. Role/company: text-on-surface-muted\n- NEVER use same dark bg for both section AND cards\n\nHERO SECTION \u2014 your masterpiece:\n- Use a 2-column grid (lg:grid-cols-2) that fills the full height, NOT content floating in empty space\n- Left column: headline + description + CTAs, vertically centered with flex flex-col justify-center\n- Right column: large hero image (data-image-query) filling the column, or a bento-grid of image + stat cards\n- Bold oversized headline (text-4xl md:text-6xl lg:text-7xl font-black leading-tight)\n- Tag/label above headline (uppercase, tracking-wider, text-xs text-accent)\n- Short description paragraph (text-lg text-on-surface-muted, max-w-lg)\n- 2 CTAs: primary (large, px-8 py-4, with \u2192 arrow) + secondary (ghost/outlined)\n- Optional: social proof bar below CTAs (avatar stack + \"2,847+ users\" text)\n- Min height: min-h-[90vh] with items-center on the grid so content is vertically centered\n- CRITICAL: the grid must stretch to fill the section height. Use min-h-[90vh] on the grid container itself, not just the section\n- NEVER leave large empty areas \u2014 if using min-h-[90vh], content must be centered/distributed within it\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders";
|
|
8
|
+
declare const SYSTEM_PROMPT = "You are a world-class web designer who creates AWARD-WINNING landing pages. Your designs win Awwwards, FWA, and CSS Design Awards. You think in terms of visual hierarchy, whitespace, and emotional impact.\n\nRULES:\n- Each section is a complete <section> tag with Tailwind CSS classes\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import, no @tailwind directives)\n- NO JavaScript, only HTML+Tailwind\n- Each section must be independent and self-contained\n- Responsive: mobile-first with sm/md/lg/xl breakpoints\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real-looking content (not Lorem ipsum) \u2014 make it specific to the prompt\n\nRESPONSIVE \u2014 MANDATORY:\n- EVERY grid: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 (NEVER grid-cols-3 alone)\n- EVERY flex row: flex flex-col md:flex-row (NEVER flex flex-row alone)\n- Text sizes: text-3xl md:text-5xl lg:text-7xl (NEVER text-7xl alone)\n- Images: w-full h-auto object-cover max-w-full\n- Padding: px-4 md:px-8 lg:px-16 (NEVER px-16 alone)\n- Hide decorative on mobile if breaks layout: hidden md:block\n\nIMAGES \u2014 CRITICAL:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER use <img> without data-image-query\n- NEVER include a src attribute \u2014 the system auto-replaces data-image-query with a real image URL\n- Queries must be generic stock-photo friendly (e.g. \"modern office\" not \"Juan's cybercafe\")\n- For avatar-like elements, use colored divs with initials instead of img tags (e.g. <div class=\"w-10 h-10 rounded-full bg-primary flex items-center justify-center text-on-primary font-bold\">JD</div>)\n\nICONS \u2014 use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually \u2014 ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nIMAGE OVERLAYS \u2014 CRITICAL:\n- When using images as backgrounds or behind text, ALWAYS add a gradient overlay for text readability\n- Pattern: <div class=\"relative\"><img data-image-query=\"...\" alt=\"...\" class=\"absolute inset-0 w-full h-full object-cover\"/><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n- For hero sections with background images: use bg-gradient-to-t from-primary-dark/90 via-primary-dark/50 to-transparent\n- For testimonial/quote backgrounds: use bg-surface/90 backdrop-blur-sm on the card\n\nCOLOR SYSTEM \u2014 CRITICAL (READ CAREFULLY):\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent\n- POLARITY of surface tokens (CRITICAL \u2014 agents confuse these):\n \u2022 bg-surface = the page background (light on light themes, dark on dark themes)\n \u2022 bg-surface-alt = a SLIGHT TINT of bg-surface (almost the same lightness \u2014 used for cards/alternating rows). NOT a dark surface. Pair with text-on-surface (NOT text-on-primary).\n \u2022 bg-surface-deep = a HIGH-CONTRAST DARK SURFACE, brand-independent (use for dark cards/footers/sidebars on light themes). Pair with text-on-surface-deep (light text).\n \u2022 bg-secondary = the BRAND'S SECONDARY color (from brandkit). Different from bg-surface-alt \u2014 use this when you want a \"second brand color\" feel, not just a tint.\n Common mistake: agents reach for \"bg-surface-alt + text-on-primary\" thinking it's a dark card. That produces white text on near-white background. For dark cards, use bg-surface-deep, bg-primary, or bg-secondary instead.\n- NEVER use hardcoded Tailwind color classes: NO bg-gray-*, bg-black, bg-white, bg-indigo-*, bg-blue-*, bg-purple-*, text-gray-*, text-black, text-white, etc.\n- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color \u2014 use bg-primary, not bg-[#userhex].\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL backgrounds MUST use: bg-primary, bg-primary-dark, bg-surface, bg-surface-alt\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface. text-accent is decorative \u2014 use sparingly on bg-surface/bg-surface-alt only.\n- ANTI-PATTERN: NEVER put bg-primary on BOTH the section AND elements inside it. If section is bg-primary, inner cards/elements should be bg-surface. If section is bg-surface, cards can use bg-surface-alt or bg-primary.\n- For gradients: from-primary to-primary-dark, from-surface to-surface-alt\n- For hover: hover:bg-primary-dark, hover:bg-primary-light\n\nCOLOR VARIETY \u2014 MANDATORY:\n- ALTERNATE section backgrounds: bg-surface \u2192 bg-primary \u2192 bg-surface-alt \u2192 bg-primary-dark \u2192 bg-surface\n- Use bg-accent for at least ONE section (CTA or highlight section)\n- Use bg-secondary for at least ONE section (features or stats)\n- Cards on dark sections (bg-primary, bg-primary-dark) MUST be bg-surface (light cards on dark bg = visual pop)\n- Cards on light sections (bg-surface) can use bg-surface-alt or bg-primary-light\n- Use text-accent for decorative elements: labels, badges, icons, highlights, underlines\n- Use text-secondary for secondary information, tags, category labels\n- Gradients: mix colors creatively \u2014 from-primary to-accent for CTAs, from-secondary to-primary for headers\n- Buttons: primary CTA = bg-accent text-on-accent, secondary CTA = bg-secondary text-on-secondary or border-primary\n\nDESIGN PHILOSOPHY \u2014 what separates good from GREAT:\n- WHITESPACE is your best friend. Generous padding (py-24, py-32, px-8). Let elements breathe.\n- CONTRAST: mix dark sections with light ones. Alternate bg-primary and bg-surface sections.\n- TYPOGRAPHY: use extreme size differences for hierarchy (text-7xl headline next to text-sm label)\n- DEPTH: overlapping elements, negative margins (-mt-12), z-index layering, shadows\n- ASYMMETRY: avoid centering everything. Use grid-cols-5 with col-span-3 + col-span-2. Offset elements.\n- TEXTURE: use subtle patterns, gradients, border treatments, rounded-3xl mixed with sharp edges\n- Each section should have a COMPLETELY DIFFERENT layout from the others\n\nSECTION LAYOUT \u2014 CRITICAL:\n- Each <section> must be full-width (bg goes edge-to-edge). NO max-w on the section itself.\n- Constrain content inside with a wrapper div: <section class=\"bg-primary py-24\"><div class=\"max-w-7xl mx-auto px-4 md:px-8\">...content...</div></section>\n- EVERY section follows this pattern. The <section> handles bg color + vertical padding. The inner <div> handles horizontal padding + max-width.\n\nTESTIMONIALS SECTION:\n- Cards MUST use bg-surface or bg-surface-alt with text-on-surface\n- If section bg is bg-primary or bg-primary-dark, cards MUST be bg-surface (light cards on dark bg)\n- Quote text: text-on-surface, italic\n- Avatar: colored div with initials (bg-accent text-on-primary or bg-primary-light text-on-primary)\n- Name: text-on-surface font-semibold. Role/company: text-on-surface-muted\n- NEVER use same dark bg for both section AND cards\n\nHERO SECTION \u2014 your masterpiece:\n- Use a 2-column grid (lg:grid-cols-2) that fills the full height, NOT content floating in empty space\n- Left column: headline + description + CTAs, vertically centered with flex flex-col justify-center\n- Right column: large hero image (data-image-query) filling the column, or a bento-grid of image + stat cards\n- Bold oversized headline (text-4xl md:text-6xl lg:text-7xl font-black leading-tight)\n- Tag/label above headline (uppercase, tracking-wider, text-xs text-accent)\n- Short description paragraph (text-lg text-on-surface-muted, max-w-lg)\n- 2 CTAs: primary (large, px-8 py-4, with \u2192 arrow) + secondary (ghost/outlined)\n- Optional: social proof bar below CTAs (avatar stack + \"2,847+ users\" text)\n- Min height: min-h-[90vh] with items-center on the grid so content is vertically centered\n- CRITICAL: the grid must stretch to fill the section height. Use min-h-[90vh] on the grid container itself, not just the section\n- NEVER leave large empty areas \u2014 if using min-h-[90vh], content must be centered/distributed within it\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders";
|
|
9
9
|
/** @deprecated Use buildPromptSuffix(prompt) internally. Kept for backward compat. */
|
|
10
10
|
declare const PROMPT_SUFFIX = "\n\nOUTPUT FORMAT: NDJSON \u2014 one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Short Label\", \"html\": \"<section>...</section>\"}\n\nGenerate 7-9 sections. Always start with Hero and end with Footer.\nIMPORTANT: Make each section VISUALLY UNIQUE \u2014 different layouts, different background colors, different grid structures.\nThink like a premium design agency creating a $50K landing page.\nNO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.";
|
|
11
11
|
interface GenerateOptions {
|
|
@@ -32,9 +32,11 @@ interface GenerateOptions {
|
|
|
32
32
|
onPartialSection?: (index: number, partialHtml: string) => void;
|
|
33
33
|
onDone?: (sections: Section3[]) => void;
|
|
34
34
|
onError?: (error: Error) => void;
|
|
35
|
-
/**
|
|
35
|
+
/** Custom-theme palette (hex map: primary, secondary, accent, surface).
|
|
36
|
+
* Required when themeName === "custom"; optional otherwise. Used both for
|
|
37
|
+
* prompt context AND for theme-aware sanitization. */
|
|
36
38
|
themeColors?: Record<string, string>;
|
|
37
|
-
/** Theme name (e.g. "minimal", "noche", "oceano") — tells the AI the design mood */
|
|
39
|
+
/** Theme name (e.g. "minimal", "noche", "oceano", "custom") — tells the AI the design mood */
|
|
38
40
|
themeName?: string;
|
|
39
41
|
/** Brand kit info for AI context */
|
|
40
42
|
brandKit?: {
|
package/dist/generate.js
CHANGED
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
PROMPT_SUFFIX,
|
|
3
3
|
SYSTEM_PROMPT,
|
|
4
4
|
generateLanding
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QFT3PN3L.js";
|
|
6
6
|
import {
|
|
7
7
|
extractJsonObjects
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-H2YYYKUI.js";
|
|
9
|
+
import "./chunk-DCAQAHSU.js";
|
|
10
10
|
export {
|
|
11
11
|
PROMPT_SUFFIX,
|
|
12
12
|
SYSTEM_PROMPT,
|
package/dist/generateDocument.js
CHANGED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
generateDocumentParallel,
|
|
7
7
|
getDocumentPromptSuffix,
|
|
8
8
|
getDocumentSystemPrompt
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-GL74S2H4.js";
|
|
10
|
+
import "./chunk-ULAQDD23.js";
|
|
11
|
+
import "./chunk-H2YYYKUI.js";
|
|
12
12
|
export {
|
|
13
13
|
DOCUMENT_PROMPT_SUFFIX,
|
|
14
14
|
DOCUMENT_SYSTEM_PROMPT,
|
package/dist/images.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { S as Section3 } from './types-BIpbpCJr.js';
|
|
2
2
|
export { I as IframeMessage } from './types-BIpbpCJr.js';
|
|
3
|
-
import { C as CustomColors } from './themes-
|
|
4
|
-
export { L as LANDING_THEMES, a as LandingTheme, b as buildCustomTheme, c as buildCustomThemeCss, d as buildSingleThemeCss, e as buildThemeCss } from './themes-
|
|
3
|
+
import { C as CustomColors } from './themes-df34nq2_.js';
|
|
4
|
+
export { L as LANDING_THEMES, a as LandingTheme, b as buildCustomTheme, c as buildCustomThemeCss, d as buildSingleThemeCss, e as buildThemeCss } from './themes-df34nq2_.js';
|
|
5
5
|
export { GenerateOptions, PROMPT_SUFFIX, SYSTEM_PROMPT, extractJsonObjects, generateLanding } from './generate.js';
|
|
6
6
|
export { DOCUMENT_PROMPT_SUFFIX, DOCUMENT_SYSTEM_PROMPT, GenerateDocumentOptions, generateDocument } from './generateDocument.js';
|
|
7
7
|
export { REFINE_SYSTEM, RefineOptions, refineLanding } from './refine.js';
|
|
8
8
|
export { DeployToEasyBitsOptions, DeployToS3Options, deployToEasyBits, deployToS3 } from './deploy.js';
|
|
9
9
|
export { E as EnrichImagesOptions, P as PexelsResult, e as enrichImages, f as findImageSlots, g as generateImage, a as generateSvg, s as searchImage } from './svgGenerator-CduZJvMf.js';
|
|
10
|
-
export { C as Canvas, a as CanvasHandle, b as CodeEditor, F as FloatingToolbar, S as SectionList, V as Viewport, c as ViewportToggle } from './ViewportToggle-
|
|
10
|
+
export { C as Canvas, a as CanvasHandle, b as CodeEditor, F as FloatingToolbar, S as SectionList, V as Viewport, c as ViewportToggle } from './ViewportToggle-Gns9NOvf.js';
|
|
11
11
|
export { buildDeployHtmlV4 } from './buildHtmlV4.js';
|
|
12
12
|
export { grapesToSections } from './grapesToSections.js';
|
|
13
13
|
export { useThumbnailCapture } from './hooks/useThumbnailCapture.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDeployHtmlV4
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ETWQS7IQ.js";
|
|
4
4
|
import {
|
|
5
5
|
grapesToSections
|
|
6
6
|
} from "./chunk-7LKFTF32.js";
|
|
@@ -13,23 +13,23 @@ import {
|
|
|
13
13
|
FloatingToolbar,
|
|
14
14
|
SectionList,
|
|
15
15
|
ViewportToggle
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-EP65R6DE.js";
|
|
17
17
|
import "./chunk-DUHALQL7.js";
|
|
18
18
|
import {
|
|
19
19
|
PROMPT_SUFFIX,
|
|
20
20
|
SYSTEM_PROMPT,
|
|
21
21
|
generateLanding
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-QFT3PN3L.js";
|
|
23
23
|
import {
|
|
24
24
|
DOCUMENT_PROMPT_SUFFIX,
|
|
25
25
|
DOCUMENT_SYSTEM_PROMPT,
|
|
26
26
|
generateDocument
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-GL74S2H4.js";
|
|
28
|
+
import "./chunk-ULAQDD23.js";
|
|
29
29
|
import {
|
|
30
30
|
REFINE_SYSTEM,
|
|
31
31
|
refineLanding
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-EIZRTLU6.js";
|
|
33
33
|
import {
|
|
34
34
|
enrichImages,
|
|
35
35
|
extractJsonObjects,
|
|
@@ -37,23 +37,23 @@ import {
|
|
|
37
37
|
generateImage,
|
|
38
38
|
generateSvg,
|
|
39
39
|
searchImage
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-H2YYYKUI.js";
|
|
41
41
|
import {
|
|
42
42
|
deployToEasyBits,
|
|
43
43
|
deployToS3
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-SJJZEW5W.js";
|
|
45
45
|
import {
|
|
46
46
|
buildDeployHtml,
|
|
47
47
|
buildPreviewHtml,
|
|
48
48
|
getIframeScript
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-7MGKYJTI.js";
|
|
50
50
|
import {
|
|
51
51
|
LANDING_THEMES,
|
|
52
52
|
buildCustomTheme,
|
|
53
53
|
buildCustomThemeCss,
|
|
54
54
|
buildSingleThemeCss,
|
|
55
55
|
buildThemeCss
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-DCAQAHSU.js";
|
|
57
57
|
export {
|
|
58
58
|
Canvas,
|
|
59
59
|
CodeEditor,
|
package/dist/refine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const REFINE_SYSTEM = "You are an expert HTML/Tailwind CSS developer. You receive the current HTML of a landing page section and a user instruction.\n\nRULES:\n- Return ONLY the modified HTML \u2014 no full page, no <html>/<head>/<body> tags\n- Use Tailwind CSS classes (CDN loaded)\n- You may use inline styles for specific adjustments\n- Images: use data-image-query=\"english search query\" for new images\n- Keep all text in its original language unless asked to translate\n- Be creative \u2014 don't just make minimal changes, improve the design\n- Return raw HTML only \u2014 no markdown fences, no explanations\n\nCOLOR SYSTEM \u2014 CRITICAL:\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent\n- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.\n- Use bg-accent, bg-secondary, text-accent, text-secondary for visual variety \u2014 not everything should be primary.\n\nIMAGE OVERLAYS:\n- When placing text over images, ALWAYS add a gradient overlay for readability\n- Pattern: <div class=\"relative\"><img .../><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders";
|
|
1
|
+
declare const REFINE_SYSTEM = "You are an expert HTML/Tailwind CSS developer. You receive the current HTML of a landing page section and a user instruction.\n\nRULES:\n- Return ONLY the modified HTML \u2014 no full page, no <html>/<head>/<body> tags\n- Use Tailwind CSS classes (CDN loaded)\n- You may use inline styles for specific adjustments\n- Images: use data-image-query=\"english search query\" for new images\n- Keep all text in its original language unless asked to translate\n- Be creative \u2014 don't just make minimal changes, improve the design\n- Return raw HTML only \u2014 no markdown fences, no explanations\n\nCOLOR SYSTEM \u2014 CRITICAL:\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent\n- POLARITY (critical): bg-surface-alt = LIGHT TINT of surface (cards on light pages \u2014 pair with text-on-surface). bg-surface-deep = HIGH-CONTRAST DARK surface (dark cards/footers on light themes \u2014 pair with text-on-surface-deep). bg-secondary = the brand's secondary color. NEVER use bg-surface-alt + text-on-primary for \"dark cards\" \u2014 that produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary.\n- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.\n- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color \u2014 use bg-primary, not bg-[#userhex].\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.\n- Use bg-accent, bg-secondary, text-accent, text-secondary for visual variety \u2014 not everything should be primary.\n\nIMAGE OVERLAYS:\n- When placing text over images, ALWAYS add a gradient overlay for readability\n- Pattern: <div class=\"relative\"><img .../><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders";
|
|
2
2
|
/**
|
|
3
3
|
* Extract a text description from HTML for variant generation.
|
|
4
4
|
* Instead of sending full HTML to the model, we send a content summary
|
|
@@ -35,9 +35,12 @@ interface RefineOptions {
|
|
|
35
35
|
onDone?: (html: string) => void;
|
|
36
36
|
/** Called on error */
|
|
37
37
|
onError?: (error: Error) => void;
|
|
38
|
-
/**
|
|
38
|
+
/** Custom-theme palette (hex map: primary, secondary, accent, surface).
|
|
39
|
+
* Required when themeName === "custom"; optional otherwise (built-in themes
|
|
40
|
+
* resolve their hex values via LANDING_THEMES). Used both for prompt context
|
|
41
|
+
* AND for theme-aware sanitization of arbitrary `bg-[#hex]` classes. */
|
|
39
42
|
themeColors?: Record<string, string>;
|
|
40
|
-
/** Theme name (e.g. "minimal", "noche") — tells the AI the design mood */
|
|
43
|
+
/** Theme name (e.g. "minimal", "noche", "custom") — tells the AI the design mood */
|
|
41
44
|
themeName?: string;
|
|
42
45
|
/** Brand kit info for AI context */
|
|
43
46
|
brandKit?: {
|
package/dist/refine.js
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
REFINE_SYSTEM,
|
|
3
3
|
extractSectionDescription,
|
|
4
4
|
refineLanding
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-EIZRTLU6.js";
|
|
6
|
+
import "./chunk-H2YYYKUI.js";
|
|
7
|
+
import "./chunk-DCAQAHSU.js";
|
|
8
8
|
export {
|
|
9
9
|
REFINE_SYSTEM,
|
|
10
10
|
extractSectionDescription,
|
|
@@ -8,9 +8,15 @@ interface LandingTheme {
|
|
|
8
8
|
secondary: string;
|
|
9
9
|
accent: string;
|
|
10
10
|
surface: string;
|
|
11
|
+
/** Slight tint of `surface` (almost-same lightness) — used for cards and
|
|
12
|
+
* alternating row backgrounds on a light page. NOT a dark contrast surface. */
|
|
11
13
|
"surface-alt": string;
|
|
14
|
+
/** A high-contrast dark surface that's INDEPENDENT of brand colors. Use
|
|
15
|
+
* for dark cards/footers/sidebars on light themes. Pairs with text-on-surface-deep. */
|
|
16
|
+
"surface-deep": string;
|
|
12
17
|
"on-surface": string;
|
|
13
18
|
"on-surface-muted": string;
|
|
19
|
+
"on-surface-deep": string;
|
|
14
20
|
"on-primary": string;
|
|
15
21
|
"on-secondary": string;
|
|
16
22
|
"on-accent": string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easybits.cloud/html-tailwind-generator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.142",
|
|
4
4
|
"description": "AI-powered landing page generator with Tailwind CSS — canvas editor, streaming generation, and one-click deploy",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"type": "module",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generate.ts"],"sourcesContent":["import { streamGenerate, dataUrlToImagePart, extractJsonObjects } from \"./streamCore\";\nimport { buildThemePromptContext } from \"./themes\";\nimport type { Section3 } from \"./types\";\n\nexport { extractJsonObjects };\n\nexport const SYSTEM_PROMPT = `You are a world-class web designer who creates AWARD-WINNING landing pages. Your designs win Awwwards, FWA, and CSS Design Awards. You think in terms of visual hierarchy, whitespace, and emotional impact.\n\nRULES:\n- Each section is a complete <section> tag with Tailwind CSS classes\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import, no @tailwind directives)\n- NO JavaScript, only HTML+Tailwind\n- Each section must be independent and self-contained\n- Responsive: mobile-first with sm/md/lg/xl breakpoints\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real-looking content (not Lorem ipsum) — make it specific to the prompt\n\nRESPONSIVE — MANDATORY:\n- EVERY grid: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 (NEVER grid-cols-3 alone)\n- EVERY flex row: flex flex-col md:flex-row (NEVER flex flex-row alone)\n- Text sizes: text-3xl md:text-5xl lg:text-7xl (NEVER text-7xl alone)\n- Images: w-full h-auto object-cover max-w-full\n- Padding: px-4 md:px-8 lg:px-16 (NEVER px-16 alone)\n- Hide decorative on mobile if breaks layout: hidden md:block\n\nIMAGES — CRITICAL:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER use <img> without data-image-query\n- NEVER include a src attribute — the system auto-replaces data-image-query with a real image URL\n- Queries must be generic stock-photo friendly (e.g. \"modern office\" not \"Juan's cybercafe\")\n- For avatar-like elements, use colored divs with initials instead of img tags (e.g. <div class=\"w-10 h-10 rounded-full bg-primary flex items-center justify-center text-on-primary font-bold\">JD</div>)\n\nICONS — use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually — ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nIMAGE OVERLAYS — CRITICAL:\n- When using images as backgrounds or behind text, ALWAYS add a gradient overlay for text readability\n- Pattern: <div class=\"relative\"><img data-image-query=\"...\" alt=\"...\" class=\"absolute inset-0 w-full h-full object-cover\"/><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n- For hero sections with background images: use bg-gradient-to-t from-primary-dark/90 via-primary-dark/50 to-transparent\n- For testimonial/quote backgrounds: use bg-surface/90 backdrop-blur-sm on the card\n\nCOLOR SYSTEM — CRITICAL (READ CAREFULLY):\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent\n- NEVER use hardcoded Tailwind color classes: NO bg-gray-*, bg-black, bg-white, bg-indigo-*, bg-blue-*, bg-purple-*, text-gray-*, text-black, text-white, etc.\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL backgrounds MUST use: bg-primary, bg-primary-dark, bg-surface, bg-surface-alt\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary — invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark → use ONLY text-on-primary. On bg-surface or bg-surface-alt → use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary — they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface. text-accent is decorative — use sparingly on bg-surface/bg-surface-alt only.\n- ANTI-PATTERN: NEVER put bg-primary on BOTH the section AND elements inside it. If section is bg-primary, inner cards/elements should be bg-surface. If section is bg-surface, cards can use bg-surface-alt or bg-primary.\n- For gradients: from-primary to-primary-dark, from-surface to-surface-alt\n- For hover: hover:bg-primary-dark, hover:bg-primary-light\n\nCOLOR VARIETY — MANDATORY:\n- ALTERNATE section backgrounds: bg-surface → bg-primary → bg-surface-alt → bg-primary-dark → bg-surface\n- Use bg-accent for at least ONE section (CTA or highlight section)\n- Use bg-secondary for at least ONE section (features or stats)\n- Cards on dark sections (bg-primary, bg-primary-dark) MUST be bg-surface (light cards on dark bg = visual pop)\n- Cards on light sections (bg-surface) can use bg-surface-alt or bg-primary-light\n- Use text-accent for decorative elements: labels, badges, icons, highlights, underlines\n- Use text-secondary for secondary information, tags, category labels\n- Gradients: mix colors creatively — from-primary to-accent for CTAs, from-secondary to-primary for headers\n- Buttons: primary CTA = bg-accent text-on-accent, secondary CTA = bg-secondary text-on-secondary or border-primary\n\nDESIGN PHILOSOPHY — what separates good from GREAT:\n- WHITESPACE is your best friend. Generous padding (py-24, py-32, px-8). Let elements breathe.\n- CONTRAST: mix dark sections with light ones. Alternate bg-primary and bg-surface sections.\n- TYPOGRAPHY: use extreme size differences for hierarchy (text-7xl headline next to text-sm label)\n- DEPTH: overlapping elements, negative margins (-mt-12), z-index layering, shadows\n- ASYMMETRY: avoid centering everything. Use grid-cols-5 with col-span-3 + col-span-2. Offset elements.\n- TEXTURE: use subtle patterns, gradients, border treatments, rounded-3xl mixed with sharp edges\n- Each section should have a COMPLETELY DIFFERENT layout from the others\n\nSECTION LAYOUT — CRITICAL:\n- Each <section> must be full-width (bg goes edge-to-edge). NO max-w on the section itself.\n- Constrain content inside with a wrapper div: <section class=\"bg-primary py-24\"><div class=\"max-w-7xl mx-auto px-4 md:px-8\">...content...</div></section>\n- EVERY section follows this pattern. The <section> handles bg color + vertical padding. The inner <div> handles horizontal padding + max-width.\n\nTESTIMONIALS SECTION:\n- Cards MUST use bg-surface or bg-surface-alt with text-on-surface\n- If section bg is bg-primary or bg-primary-dark, cards MUST be bg-surface (light cards on dark bg)\n- Quote text: text-on-surface, italic\n- Avatar: colored div with initials (bg-accent text-on-primary or bg-primary-light text-on-primary)\n- Name: text-on-surface font-semibold. Role/company: text-on-surface-muted\n- NEVER use same dark bg for both section AND cards\n\nHERO SECTION — your masterpiece:\n- Use a 2-column grid (lg:grid-cols-2) that fills the full height, NOT content floating in empty space\n- Left column: headline + description + CTAs, vertically centered with flex flex-col justify-center\n- Right column: large hero image (data-image-query) filling the column, or a bento-grid of image + stat cards\n- Bold oversized headline (text-4xl md:text-6xl lg:text-7xl font-black leading-tight)\n- Tag/label above headline (uppercase, tracking-wider, text-xs text-accent)\n- Short description paragraph (text-lg text-on-surface-muted, max-w-lg)\n- 2 CTAs: primary (large, px-8 py-4, with → arrow) + secondary (ghost/outlined)\n- Optional: social proof bar below CTAs (avatar stack + \"2,847+ users\" text)\n- Min height: min-h-[90vh] with items-center on the grid so content is vertically centered\n- CRITICAL: the grid must stretch to fill the section height. Use min-h-[90vh] on the grid container itself, not just the section\n- NEVER leave large empty areas — if using min-h-[90vh], content must be centered/distributed within it\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders`;\n\n/** @deprecated Use buildPromptSuffix(prompt) internally. Kept for backward compat. */\nexport const PROMPT_SUFFIX = `\n\nOUTPUT FORMAT: NDJSON — one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Short Label\", \"html\": \"<section>...</section>\"}\n\nGenerate 7-9 sections. Always start with Hero and end with Footer.\nIMPORTANT: Make each section VISUALLY UNIQUE — different layouts, different background colors, different grid structures.\nThink like a premium design agency creating a $50K landing page.\nNO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.`;\n\nfunction buildPromptSuffix(userPrompt: string): string {\n // Extract section count from user prompt (e.g. \"3 secciones\", \"2 sections\", \"dame 4\")\n const countMatch = userPrompt.match(/(\\d+)\\s*(?:secciones?|sections?|bloques?|blocks?|partes?|pages?)/i)\n || userPrompt.match(/(?:genera|generar|crea|crear|haz|hazme|dame|quiero)\\s*(\\d+)/i);\n const count = countMatch ? parseInt(countMatch[1] || countMatch[2] || \"0\") : 0;\n const sectionInstruction = count > 0\n ? `Generate EXACTLY ${count} sections (no more, no less). Always include Hero as first and Footer as last.`\n : `Generate 7-9 sections. Always start with Hero and end with Footer.`;\n\n return `\n\nOUTPUT FORMAT: NDJSON — one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Short Label\", \"html\": \"<section>...</section>\"}\n\n${sectionInstruction}\nIMPORTANT: Make each section VISUALLY UNIQUE — different layouts, different background colors, different grid structures.\nThink like a premium design agency creating a $50K landing page.\nNO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.`;\n}\n\nexport interface GenerateOptions {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n referenceImage?: string;\n extraInstructions?: string;\n systemPrompt?: string;\n model?: string;\n pexelsApiKey?: string;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onSection?: (section: Section3) => void;\n onImageUpdate?: (sectionId: string, html: string) => void;\n /**\n * Called with the HTML of the section currently being streamed, BEFORE it's\n * fully parsed. Fires roughly every ~3 chunks so consumers can show a live\n * element-by-element preview of the section being built. `index` is the\n * 0-based position of this section (= number of already-completed sections).\n *\n * The partial HTML may contain unclosed tags — the browser's innerHTML\n * parser closes them automatically when you inject it into a DOM node.\n */\n onPartialSection?: (index: number, partialHtml: string) => void;\n onDone?: (sections: Section3[]) => void;\n onError?: (error: Error) => void;\n /** Theme colors to inject into the AI prompt (deprecated — use themeName) */\n themeColors?: Record<string, string>;\n /** Theme name (e.g. \"minimal\", \"noche\", \"oceano\") — tells the AI the design mood */\n themeName?: string;\n /** Brand kit info for AI context */\n brandKit?: {\n fonts?: { heading?: string; body?: string };\n mood?: string;\n logoUrl?: string;\n };\n}\n\n/**\n * Generate a landing page with streaming AI + image enrichment.\n */\nfunction buildVisualContext(themeName?: string, brandKit?: GenerateOptions[\"brandKit\"]): string {\n if (!themeName && !brandKit) return \"\";\n\n const lines: string[] = [\"\\n\\n## Visual Context — MANDATORY\"];\n\n if (themeName && themeName !== \"custom\") {\n lines.push(buildThemePromptContext(themeName));\n }\n\n if (brandKit?.fonts) {\n const { heading, body } = brandKit.fonts;\n if (heading) lines.push(`- Heading font: use font-family: '${heading}' via inline style on h1-h6`);\n if (body) lines.push(`- Body font: use font-family: '${body}' via inline style on p, li, span`);\n }\n\n if (brandKit?.mood) {\n lines.push(`- Design mood: ${brandKit.mood} — adapt spacing, imagery style, and visual weight to match this mood`);\n }\n\n if (brandKit?.logoUrl) {\n lines.push(`- Brand logo: include <img src=\"${brandKit.logoUrl}\" alt=\"Logo\" class=\"h-8 w-auto\" /> in the navbar/hero area`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport async function generateLanding(options: GenerateOptions): Promise<Section3[]> {\n const {\n prompt,\n referenceImage,\n extraInstructions,\n systemPrompt = SYSTEM_PROMPT,\n themeColors: _themeColors,\n themeName,\n brandKit,\n ...rest\n } = options;\n\n const visualContext = buildVisualContext(themeName, brandKit);\n const extra = extraInstructions ? `\\nAdditional instructions: ${extraInstructions}` : \"\";\n const content: any[] = [];\n\n if (referenceImage) {\n const converted = dataUrlToImagePart(referenceImage);\n if (converted) {\n content.push({ type: \"image\", ...converted });\n } else {\n content.push({ type: \"image\", image: referenceImage });\n }\n content.push({\n type: \"text\",\n text: `Generate a landing page for: ${prompt}${extra}\\n\\nIMPORTANT: Use the reference image as a DIRECT visual guide. Replicate its layout structure, grid arrangement, spacing, visual hierarchy, and section organization as closely as possible. Match the number of columns, element positioning, and overall composition. Adapt the content to the prompt but keep the visual DNA of the reference.${buildPromptSuffix(prompt)}`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Generate a landing page for: ${prompt}${extra}${buildPromptSuffix(prompt)}`,\n });\n }\n\n return streamGenerate({\n ...rest,\n systemPrompt: systemPrompt + visualContext,\n userContent: content,\n });\n}\n"],"mappings":"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","names":[]}
|