import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; import { GoogleGenerativeAI } from '@google/generative-ai'; dotenv.config(); const app = express(); const port = 3001; app.use(cors()); app.use(express.json()); // Initialize Gemini API const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || ''); app.post('/api/surprise', async (req, res) => { try { if (!process.env.GEMINI_API_KEY) { return res.status(500).json({ error: 'Missing API Key' }); } const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" }); const prompt = ` Generate ONE creative, fun, specific theme for a children's worksheet (e.g. "Space-Rex Coding", "Underwater Hamster Tea Party"). Pick a random age between 3 and 7. Pick a random activity type from: coloring, numbers, writing, find-the-way, counting. Return JSON ONLY: { "theme": "string", "age": number, "section": "string" } `; const result = await model.generateContent(prompt); const text = result.response.text(); const jsonStr = text.replace(/```json/g, '').replace(/```/g, '').trim(); res.json(JSON.parse(jsonStr)); } catch (error) { console.error('Surprise error:', error); res.status(500).json({ error: 'Failed' }); } }); app.post('/api/generate', async (req, res) => { try { const { theme, age, sections } = req.body; console.log('Received generation request:', { theme, age, sections }); if (!process.env.GEMINI_API_KEY) { console.warn('Missing GEMINI_API_KEY'); return res.status(500).json({ error: 'Server configuration error: Missing API Key' }); } const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" }); const prompt = ` You are a professional illustrator of high-quality children's coloring books. Create ONLY clean, simple, bold-outline black-and-white SVGs in classic kid-book style: thick lines, large closed colorable areas, recognizable cute subjects, no distortions/blobs/weird features. Create educational worksheet metadata for a ${age}-year-old child. Theme: ${theme} Sections: ${sections.join(', ')} Return ONLY valid JSON. No other text, no explanations. MANDATORY STYLE & QUALITY RULES — MUST FOLLOW EXACTLY: - Depict the theme literally and recognizably using standard, cute children's illustration style (e.g. animals look like real animals with big eyes/smiles; no invented blobs, hybrids, pigtails/bows on wrong things, distorted proportions, extra random parts). - Every visible element MUST be FULLY CLOSED paths (use Z/z to close , or ///). NO open paths, NO , NO unless closed, NO stroke-only lines without enclosed fill regions. - Forbidden forever: blobs, distorted/wrong anatomy (e.g. elephant with pigtails, sheep with leaf legs), floating disconnected lines/parts, random dots/scribbles/noise/artifacts, self-intersecting paths making uncolorable slivers, cut-off/incomplete shapes, inconsistent stroke widths, tiny details, fill="none" on main objects (except holes), any greyscale/shading. - Stroke: #000000 solid (no dasharray except for traceable writing). Fill: #ffffff on all colorable regions. - ViewBox: exactly '0 0 500 500'. MAXIMIZE PAGE USAGE. Use the full 500x500 canvas with MINIMAL margins (10-20px). Make the main subject FILL the available space. - Attributes: single quotes ' only for all XML. - SVG: complete valid XML — ... . Use smooth curves (C, Q, S) for natural shapes. 8–20 large closed regions for coloring fun. - High-quality kid style: bold thick outlines, big simple shapes, cute friendly expressions (big round eyes as circles/ovals, smiling curved mouth), balanced proportions (big head for cuteness), no complexity/noise. AGE-SPECIFIC RULES — STRICT: - For 3–4 years: Ultra-simple (1–2 huge objects max), stroke width 10–16px, very large regions (4–10 total), cartoon-big features, no small details/textures/patterns inside. - For 5–7 years: Slightly more (3–6 elements), stroke 4–8px, allow small closed interior shapes (e.g. spots as tiny circles), but still bold and clear. SECTION-SPECIFIC LOGIC — MUST BE EDUCATIONAL & COHERENT: - colouring: One main cute subject (or 2–3 related) in simple pose/scene, many large closed areas (body parts, accessories), bold outlines, friendly look. - numbers: Large closed-path digits (1–10 or similar) + theme-related countable objects grouped nearby. - writing: Dotted/dashed traceable letters/numbers/words (use closed shapes for forms + dots/arrows for direction), clean practice space. - find-the-way: Simple maze with closed barrier walls (rect/curved), clear start (arrow/circle) + end (goal object), theme elements along path, no traps. - counting: Groups of identical closed objects (e.g. 3–10 apples) matching a shown number, tied to theme. JSON exactly this structure: { "title": "Short fun title", "subtitle": "Clear one-sentence kid instruction (e.g. Color this happy animal!)", "sections": [ { "id": "coloring-main | numbers-1-5 | writing-letters | find-the-way-maze | counting-objects", "type": "coloring|numbers|writing|find-the-way|counting", "content_svg": "...FULL complete valid SVG code here..." } // exactly one object per section in array ] } CRITICAL: content_svg MUST be a string with single quotes in SVG attributes. Paths smooth and 100% closed.`; const result = await model.generateContent(prompt); const response = await result.response; const text = response.text(); // Cleanup markdown code blocks if present const jsonStr = text.replace(/```json/g, '').replace(/```/g, '').trim(); const data = JSON.parse(jsonStr); res.json(data); } catch (error) { console.error('Generation error:', error); res.status(500).json({ error: 'Failed to generate content' }); } }); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });