wondersheets/server/index.js

124 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 <path>, or <circle>/<ellipse>/<polygon>/<rect>). NO open paths, NO <line>, NO <polyline> 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'. Center content with 50100px margins on all sides. No touching edges.
- Attributes: single quotes ' only for all XML.
- SVG: complete valid XML — <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 500 500'> ... </svg>. Use smooth curves (C, Q, S) for natural shapes. 820 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 34 years: Ultra-simple (12 huge objects max), stroke width 1016px, very large regions (410 total), cartoon-big features, no small details/textures/patterns inside.
- For 57 years: Slightly more (36 elements), stroke 48px, 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 23 related) in simple pose/scene, many large closed areas (body parts, accessories), bold outlines, friendly look.
- numbers: Large closed-path digits (110 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. 310 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": "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 500 500'>...FULL complete valid SVG code here...</svg>"
}
// 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}`);
});