From e868e2a2e720ce4f0c4140aa7fec21949034720a Mon Sep 17 00:00:00 2001
From: iamdoubz <>
Date: Wed, 17 Jun 2026 21:19:17 -0500
Subject: [PATCH] Add three lesson structure to remaining Early Beginner levels
---
src/lib/curriculum.ts | 279 ++++++++++++++++++++----------------------
1 file changed, 133 insertions(+), 146 deletions(-)
diff --git a/src/lib/curriculum.ts b/src/lib/curriculum.ts
index 6155f10..5b2fc5b 100644
--- a/src/lib/curriculum.ts
+++ b/src/lib/curriculum.ts
@@ -1,11 +1,9 @@
/**
- * The DrawIt curriculum. Levels describe the learner; each level has numbered sub-levels (lessons).
- * Draw lessons: SVG fragments STACK (steps 1..n = full picture). Shade lessons (mode "shade"):
- * each step's svg is a full guide (light source + zone hints), not cumulative.
+ * DrawIt curriculum. Each Early Beginner subject is a 3-lesson set: Outline -> Details -> Color it.
+ * Outline/Detail steps use per-step `lines` (coloring-book strokes drawn one at a time). The Detail
+ * lesson awards the subject badge (it is gated behind Outline). `mode "shade"` = shading studio.
*/
-
export interface LevelMeta { key: string; name: string; emoji: string; blurb: string; }
-
export const LEVELS: LevelMeta[] = [
{ key: "early-beginner", name: "Early Beginner", emoji: "\u{1F331}", blurb: "First lines and simple shapes. Perfect for brand-new artists." },
{ key: "beginner", name: "Beginner", emoji: "\u270F\uFE0F", blurb: "Combine shapes into friendly characters and objects." },
@@ -13,183 +11,172 @@ export const LEVELS: LevelMeta[] = [
{ key: "advanced-learned", name: "Advanced Learner", emoji: "\u{1F680}", blurb: "Proportion, perspective, and more complex scenes." },
{ key: "superb", name: "Superb", emoji: "\u{1F31F}", blurb: "Confident, expressive drawing in your own style." },
];
-
export function getLevel(key: string): LevelMeta | undefined { return LEVELS.find((l) => l.key === key); }
-
export type StepKind = "construct" | "outline" | "color" | "shade" | "detail";
export type Phase = "outline" | "detail" | "extra";
-
export interface LessonStep { n: number; title: string; instruction: string; tip?: string; kind?: StepKind; svg?: string; lines?: string[]; }
+export interface Lesson {
+ level: string; sublevel: number; slug: string; title: string; subject: string; emoji: string; intro: string;
+ badgeKey: string; badgeName: string; mode?: "draw" | "shade"; phase?: Phase; baseSvg?: string;
+ subjectKey?: string; subjectName?: string; subjectEmoji?: string; order?: number; steps: LessonStep[];
+}
-export interface Lesson { level: string; sublevel: number; slug: string; title: string; subject: string; emoji: string; intro: string; badgeKey: string; badgeName: string; mode?: "draw" | "shade"; phase?: Phase; baseSvg?: string; subjectKey?: string; subjectName?: string; subjectEmoji?: string; order?: number; steps: LessonStep[]; }
-
-
-// Fish is the pilot for the 3-lesson model: Outline → Detail → Color it.
-// Outline/Detail use per-step `lines` (coloring-book strokes drawn one at a time).
-const LN = (d: string) => ``;
const FISH_OUTLINE_STEPS: LessonStep[] = [
- { n: 1, title: "The body", instruction: "Draw the big rounded body — loop all the way around.", tip: "Slow and smooth, like an egg.",
- lines: [LN("M85 150 C 95 95, 180 78, 252 96 C 292 107, 306 128, 306 150 C 306 172, 292 193, 252 204 C 180 222, 95 205, 85 150 Z")] },
- { n: 2, title: "The tail", instruction: "Add the fan-shaped tail at the back.",
- lines: [LN("M300 150 C 332 130, 360 112, 390 100 C 374 130, 374 170, 390 200 C 360 188, 332 170, 300 150 Z")] },
- { n: 3, title: "The fins", instruction: "Draw a fin on the back, then one under the belly.",
- lines: [LN("M150 92 C 168 62, 212 60, 240 84"), LN("M150 178 C 168 208, 206 210, 228 196")] },
+ { n: 1, title: "The body", instruction: "Draw the big rounded body — loop all the way around.", tip: "Slow and smooth, like an egg.", lines: [``] },
+ { n: 2, title: "The tail", instruction: "Add the fan-shaped tail at the back.", lines: [``] },
+ { n: 3, title: "The fins", instruction: "Draw a fin on the back, then one under the belly.", lines: [``, ``] },
];
const FISH_DETAIL_STEPS: LessonStep[] = [
- { n: 1, title: "The eye", instruction: "Draw a round eye, then a little dot inside.",
- lines: [LN("M147 134 a15 15 0 1 0 0.1 0"), ``] },
- { n: 2, title: "The mouth", instruction: "Add a small smile at the front.",
- lines: [LN("M90 162 q15 13 32 4")] },
- { n: 3, title: "The gill", instruction: "Add a curved gill line behind the head.",
- lines: [LN("M160 104 q-16 46 0 92")] },
- { n: 4, title: "Stripes", instruction: "Add a couple of curved stripes across the body.", tip: "Now it's ready to color!",
- lines: [LN("M205 96 q-20 54 4 110"), LN("M240 100 q-16 50 4 100")] },
+ { n: 1, title: "The eye", instruction: "Draw a round eye, then a little dot inside.", lines: [``, ``] },
+ { n: 2, title: "The mouth", instruction: "Add a small smile at the front.", lines: [``] },
+ { n: 3, title: "The gill", instruction: "Add a curved gill line behind the head.", lines: [``] },
+ { n: 4, title: "Stripes", instruction: "Add a couple of curved stripes across the body.", tip: "Now it's ready to color!", lines: [``, ``] },
];
const FISH_OUTLINE_SVG = FISH_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
+
const FISH_DETAIL_SVG = FISH_OUTLINE_SVG + "\n" + FISH_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
-export const FISH_OUTLINE_LESSON: Lesson = { level: "early-beginner", sublevel: 11, slug: "fish-outline", title: "Fish · Outline", subject: "a fish outline", emoji: "🐟", intro: "Let's draw the outline of a fish, one line at a time. Watch each line, then trace it!", badgeKey: "", badgeName: "Fish Friend", phase: "outline", subjectKey: "fish", subjectName: "Fish", subjectEmoji: "🐟", order: 1, steps: FISH_OUTLINE_STEPS };
-export const FISH_DETAIL_LESSON: Lesson = { level: "early-beginner", sublevel: 12, slug: "fish-detail", title: "Fish · Details", subject: "fish details", emoji: "🐟", intro: "Now add the details that make it a fish — the eye, mouth, gill, and stripes.", badgeKey: "early-beginner-1-fish", badgeName: "Fish Friend", phase: "detail", baseSvg: FISH_OUTLINE_SVG, subjectKey: "fish", subjectName: "Fish", subjectEmoji: "🐟", order: 1, steps: FISH_DETAIL_STEPS };
-export const FISH_EXTRA_LESSON: Lesson = { level: "early-beginner", sublevel: 13, slug: "fish-extra", title: "Fish · Color it!", subject: "color the fish", emoji: "🎨", intro: "Bring your fish to life! Color it in, and try shading and layering.", badgeKey: "", badgeName: "Fish Friend", phase: "extra", baseSvg: FISH_DETAIL_SVG, subjectKey: "fish", subjectName: "Fish", subjectEmoji: "🐟", order: 1, steps: [] };
+export const FISH_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:11, slug:"fish-outline", title:"Fish \u00b7 Outline", subject:"fish outline", emoji:"🐟", intro:"Let\u2019s draw Fish\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Fish Friend", phase:"outline", subjectKey:"fish", subjectName:"Fish", subjectEmoji:"🐟", order:1, steps: FISH_OUTLINE_STEPS };
-const PANDA_STEPS: LessonStep[] = [
- { n: 1, kind: "construct", title: "The head", instruction: "Draw one big round face.",
- tip: "Nice and round.",
- svg: `` },
- { n: 2, kind: "outline", title: "The ears", instruction: "Add two round ears in the top corners.",
- svg: `` },
- { n: 3, kind: "outline", title: "Eye patches", instruction: "Draw a dark leaf-shaped patch where each eye will go.",
- tip: "Pandas have big patches around their eyes.",
- svg: `` },
- { n: 4, kind: "detail", title: "The eyes", instruction: "Add a white circle, a pupil, and a sparkle inside each patch.",
- svg: `` },
- { n: 5, kind: "detail", title: "Nose and mouth", instruction: "Draw a rounded nose, a short line down, and two little smile curves.",
- svg: `` },
- { n: 6, kind: "detail", title: "Rosy cheeks", instruction: "Add soft pink cheeks. Your panda is done!",
- tip: "🎉",
- svg: `` },
+export const FISH_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:12, slug:"fish-detail", title:"Fish \u00b7 Details", subject:"fish details", emoji:"🐟", intro:"Now add the details that bring your fish to life.", badgeKey:"early-beginner-1-fish", badgeName:"Fish Friend", phase:"detail", baseSvg: FISH_OUTLINE_SVG, subjectKey:"fish", subjectName:"Fish", subjectEmoji:"🐟", order:1, steps: FISH_DETAIL_STEPS };
+
+export const FISH_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:13, slug:"fish-extra", title:"Fish \u00b7 Color it!", subject:"color the fish", emoji:"\u{1F3A8}", intro:"Bring your fish to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Fish Friend", phase:"extra", baseSvg: FISH_DETAIL_SVG, subjectKey:"fish", subjectName:"Fish", subjectEmoji:"🐟", order:1, steps: [] };
+
+const PANDA_OUTLINE_STEPS: LessonStep[] = [
+ { n: 1, title: "The head", instruction: "Draw one big round face.", tip: "Nice and round.", lines: [``] },
+ { n: 2, title: "The ears", instruction: "Add two round ears on top.", lines: [``, ``] },
+ { n: 3, title: "Eye patches", instruction: "Draw a leaf-shaped patch for each eye.", lines: [``, ``] },
];
-export const PANDA_LESSON: Lesson = { level: "early-beginner", sublevel: 2, slug: "panda", title: "Draw a Panda", subject: "a cuddly panda", emoji: "🐼", intro: "A panda is just circles and ovals. Let's make a cuddly friend!", badgeKey: "early-beginner-2-panda", badgeName: "Panda Pal", mode: "draw", steps: PANDA_STEPS };
-
-const FLOWER_STEPS: LessonStep[] = [
- { n: 1, kind: "construct", title: "The middle", instruction: "Draw a circle in the center of the page.",
- tip: "Leave room all around for petals.",
- svg: `` },
- { n: 2, kind: "outline", title: "First petals", instruction: "Add four petals: one on top, bottom, left, and right.",
- tip: "Petals are like rounded raindrops.",
- svg: `` },
- { n: 3, kind: "outline", title: "More petals", instruction: "Tuck four more petals into the gaps so the flower is full.",
- svg: `` },
- { n: 4, kind: "outline", title: "The stem", instruction: "Draw a curvy green stem going down from the flower.",
- svg: `` },
- { n: 5, kind: "outline", title: "The leaves", instruction: "Add a leaf on each side of the stem.",
- svg: `` },
- { n: 6, kind: "detail", title: "Seeds", instruction: "Dot some little seeds in the middle.",
- svg: `` },
- { n: 7, kind: "detail", title: "Leaf veins", instruction: "Add a line down each leaf, then color your flower!",
- tip: "🌸",
- svg: `` },
+const PANDA_DETAIL_STEPS: LessonStep[] = [
+ { n: 1, title: "The eyes", instruction: "Add a circle and a dot inside each patch.", lines: [``, ``, ``, ``] },
+ { n: 2, title: "The nose", instruction: "Draw a little rounded nose.", lines: [``] },
+ { n: 3, title: "The mouth", instruction: "Add a line down and two smile curves.", lines: [``, ``, ``] },
];
-export const FLOWER_LESSON: Lesson = { level: "early-beginner", sublevel: 3, slug: "flower", title: "Draw a Flower", subject: "a cheerful flower", emoji: "🌸", intro: "A circle in the middle and petals all around — then a stem and leaves.", badgeKey: "early-beginner-3-flower", badgeName: "Flower Power", mode: "draw", steps: FLOWER_STEPS };
+const PANDA_OUTLINE_SVG = PANDA_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
-const UNICORN_STEPS: LessonStep[] = [
- { n: 1, kind: "construct", title: "The head", instruction: "Draw a rounded head that's a little narrower at the chin.",
- svg: `` },
- { n: 2, kind: "outline", title: "The ears", instruction: "Add a pointy ear on each side with a pink inside.",
- svg: `` },
- { n: 3, kind: "outline", title: "The magic horn", instruction: "Draw a tall horn in the middle with little swirl lines.",
- svg: `` },
- { n: 4, kind: "detail", title: "Eyes and cheeks", instruction: "Add two big eyes with sparkles and soft rosy cheeks.",
- svg: `` },
- { n: 5, kind: "detail", title: "Nose and smile", instruction: "Add two tiny nostril dots and a friendly smile.",
- svg: `` },
- { n: 6, kind: "color", title: "The rainbow mane", instruction: "Add flowing locks of color down one side of the head.",
- tip: "Use lots of colors!",
- svg: `` },
- { n: 7, kind: "detail", title: "Forelock and sparkles", instruction: "Add a curl between the ears and a few sparkles. 🦄",
- svg: `` },
+const PANDA_DETAIL_SVG = PANDA_OUTLINE_SVG + "\n" + PANDA_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+export const PANDA_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:21, slug:"panda-outline", title:"Panda \u00b7 Outline", subject:"panda outline", emoji:"🐼", intro:"Let\u2019s draw Panda\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Panda Pal", phase:"outline", subjectKey:"panda", subjectName:"Panda", subjectEmoji:"🐼", order:2, steps: PANDA_OUTLINE_STEPS };
+
+export const PANDA_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:22, slug:"panda-detail", title:"Panda \u00b7 Details", subject:"panda details", emoji:"🐼", intro:"Now add the details that bring your panda to life.", badgeKey:"early-beginner-2-panda", badgeName:"Panda Pal", phase:"detail", baseSvg: PANDA_OUTLINE_SVG, subjectKey:"panda", subjectName:"Panda", subjectEmoji:"🐼", order:2, steps: PANDA_DETAIL_STEPS };
+
+export const PANDA_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:23, slug:"panda-extra", title:"Panda \u00b7 Color it!", subject:"color the panda", emoji:"\u{1F3A8}", intro:"Bring your panda to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Panda Pal", phase:"extra", baseSvg: PANDA_DETAIL_SVG, subjectKey:"panda", subjectName:"Panda", subjectEmoji:"🐼", order:2, steps: [] };
+
+const FLOWER_OUTLINE_STEPS: LessonStep[] = [
+ { n: 1, title: "The center", instruction: "Draw a circle in the middle.", tip: "Leave room for petals.", lines: [``] },
+ { n: 2, title: "Petals", instruction: "Add petals on top, bottom, left, and right.", lines: [``, ``, ``, ``] },
+ { n: 3, title: "More petals", instruction: "Tuck four more petals into the gaps.", lines: [``, ``, ``, ``] },
+ { n: 4, title: "The stem", instruction: "Draw a stem going down from the flower.", lines: [``] },
+ { n: 5, title: "The leaves", instruction: "Add a leaf on each side of the stem.", lines: [``, ``] },
];
-export const UNICORN_LESSON: Lesson = { level: "early-beginner", sublevel: 4, slug: "unicorn", title: "Draw a Unicorn", subject: "a magical unicorn", emoji: "🦄", intro: "A rounded head, a sparkly horn, and a rainbow mane. Let's make magic!", badgeKey: "early-beginner-4-unicorn", badgeName: "Unicorn Magic", mode: "draw", steps: UNICORN_STEPS };
-
-const TREE_STEPS: LessonStep[] = [
- { n: 1, kind: "construct", title: "The trunk", instruction: "Draw a trunk that's a little wider at the bottom.",
- tip: "Stand it up tall in the middle.",
- svg: `` },
- { n: 2, kind: "outline", title: "The branches", instruction: "Add two branches reaching up from the trunk.",
- svg: `` },
- { n: 3, kind: "outline", title: "Leafy clumps", instruction: "Draw a big round clump of leaves up top and one on the left.",
- tip: "Treetops are nice and lumpy.",
- svg: `` },
- { n: 4, kind: "outline", title: "More leaves", instruction: "Add clumps on the right and middle to fill out the top.",
- svg: `` },
- { n: 5, kind: "detail", title: "Apples", instruction: "Dot a few red apples in the leaves.",
- svg: `` },
- { n: 6, kind: "detail", title: "Grass", instruction: "Add a wavy line of grass along the bottom.",
- svg: `` },
- { n: 7, kind: "detail", title: "Bark", instruction: "Add a couple of bark lines on the trunk, then color your tree!",
- tip: "🌳",
- svg: `` },
+const FLOWER_DETAIL_STEPS: LessonStep[] = [
+ { n: 1, title: "Seeds", instruction: "Dot some seeds in the middle.", lines: [``, ``, ``, ``, ``] },
+ { n: 2, title: "Leaf veins", instruction: "Add a line down each leaf.", lines: [``, ``] },
+ { n: 3, title: "Center ring", instruction: "Draw a little ring inside the middle.", lines: [``] },
];
-export const TREE_LESSON: Lesson = { level: "early-beginner", sublevel: 5, slug: "tree", title: "Draw a Tree", subject: "a leafy tree", emoji: "🌳", intro: "A trunk, some branches, and big clumps of leaves make a leafy tree.", badgeKey: "early-beginner-5-tree", badgeName: "Tree Top", mode: "draw", steps: TREE_STEPS };
+const FLOWER_OUTLINE_SVG = FLOWER_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
-const DINO_STEPS: LessonStep[] = [
- { n: 1, kind: "construct", title: "The body", instruction: "Draw a big rounded body.",
- tip: "A long-neck dino is nice and round.",
- svg: `` },
- { n: 2, kind: "outline", title: "The long neck", instruction: "Sweep a long neck up from the left of the body.",
- tip: "Curve it gently.",
- svg: `` },
- { n: 3, kind: "detail", title: "The head", instruction: "Add a small rounded head on top with a dot for the eye.",
- svg: `` },
- { n: 4, kind: "outline", title: "The tail", instruction: "Draw a long tail swooping out to the right.",
- svg: `` },
- { n: 5, kind: "outline", title: "The legs", instruction: "Add two sturdy legs underneath.",
- svg: `` },
- { n: 6, kind: "detail", title: "Back plates", instruction: "Add little triangle plates along the back.",
- svg: `` },
- { n: 7, kind: "detail", title: "Spots", instruction: "Dot a few spots on the body.",
- svg: `` },
- { n: 8, kind: "detail", title: "Smile", instruction: "Add a friendly smile, then color your dino any color you like!",
- tip: "🦕",
- svg: `` },
+const FLOWER_DETAIL_SVG = FLOWER_OUTLINE_SVG + "\n" + FLOWER_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+export const FLOWER_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:31, slug:"flower-outline", title:"Flower \u00b7 Outline", subject:"flower outline", emoji:"🌸", intro:"Let\u2019s draw Flower\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Flower Power", phase:"outline", subjectKey:"flower", subjectName:"Flower", subjectEmoji:"🌸", order:3, steps: FLOWER_OUTLINE_STEPS };
+
+export const FLOWER_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:32, slug:"flower-detail", title:"Flower \u00b7 Details", subject:"flower details", emoji:"🌸", intro:"Now add the details that bring your flower to life.", badgeKey:"early-beginner-3-flower", badgeName:"Flower Power", phase:"detail", baseSvg: FLOWER_OUTLINE_SVG, subjectKey:"flower", subjectName:"Flower", subjectEmoji:"🌸", order:3, steps: FLOWER_DETAIL_STEPS };
+
+export const FLOWER_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:33, slug:"flower-extra", title:"Flower \u00b7 Color it!", subject:"color the flower", emoji:"\u{1F3A8}", intro:"Bring your flower to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Flower Power", phase:"extra", baseSvg: FLOWER_DETAIL_SVG, subjectKey:"flower", subjectName:"Flower", subjectEmoji:"🌸", order:3, steps: [] };
+
+const UNICORN_OUTLINE_STEPS: LessonStep[] = [
+ { n: 1, title: "The head", instruction: "Draw a rounded head.", lines: [``] },
+ { n: 2, title: "The ears", instruction: "Add a pointy ear on each side.", lines: [``, ``] },
+ { n: 3, title: "The horn", instruction: "Draw a tall horn on top.", lines: [``] },
+ { n: 4, title: "The mane", instruction: "Draw the flowing mane and a curl on the forehead.", lines: [``, ``] },
];
-export const DINO_LESSON: Lesson = { level: "early-beginner", sublevel: 6, slug: "dinosaur", title: "Draw a Dinosaur", subject: "a friendly dinosaur", emoji: "🦕", intro: "A round body, a long neck, a small head, and a swooshy tail!", badgeKey: "early-beginner-6-dinosaur", badgeName: "Dino Master", mode: "draw", steps: DINO_STEPS };
+const UNICORN_DETAIL_STEPS: LessonStep[] = [
+ { n: 1, title: "The eyes", instruction: "Add two big eyes.", lines: [``, ``] },
+ { n: 2, title: "Nose & mouth", instruction: "Add two nostril dots and a smile.", lines: [``, ``, ``] },
+ { n: 3, title: "Horn swirls", instruction: "Add little swirl lines on the horn.", lines: [``, ``, ``] },
+ { n: 4, title: "Mane lines", instruction: "Add flowing lines in the mane.", lines: [``, ``] },
+];
+
+const UNICORN_OUTLINE_SVG = UNICORN_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+const UNICORN_DETAIL_SVG = UNICORN_OUTLINE_SVG + "\n" + UNICORN_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+export const UNICORN_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:41, slug:"unicorn-outline", title:"Unicorn \u00b7 Outline", subject:"unicorn outline", emoji:"🦄", intro:"Let\u2019s draw Unicorn\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Unicorn Magic", phase:"outline", subjectKey:"unicorn", subjectName:"Unicorn", subjectEmoji:"🦄", order:4, steps: UNICORN_OUTLINE_STEPS };
+
+export const UNICORN_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:42, slug:"unicorn-detail", title:"Unicorn \u00b7 Details", subject:"unicorn details", emoji:"🦄", intro:"Now add the details that bring your unicorn to life.", badgeKey:"early-beginner-4-unicorn", badgeName:"Unicorn Magic", phase:"detail", baseSvg: UNICORN_OUTLINE_SVG, subjectKey:"unicorn", subjectName:"Unicorn", subjectEmoji:"🦄", order:4, steps: UNICORN_DETAIL_STEPS };
+
+export const UNICORN_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:43, slug:"unicorn-extra", title:"Unicorn \u00b7 Color it!", subject:"color the unicorn", emoji:"\u{1F3A8}", intro:"Bring your unicorn to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Unicorn Magic", phase:"extra", baseSvg: UNICORN_DETAIL_SVG, subjectKey:"unicorn", subjectName:"Unicorn", subjectEmoji:"🦄", order:4, steps: [] };
+
+const TREE_OUTLINE_STEPS: LessonStep[] = [
+ { n: 1, title: "The trunk", instruction: "Draw a tall trunk, wider at the bottom.", lines: [``] },
+ { n: 2, title: "Branches", instruction: "Add two branches reaching up.", lines: [``, ``] },
+ { n: 3, title: "The treetop", instruction: "Draw a big bumpy treetop.", tip: "Nice and lumpy!", lines: [``] },
+];
+
+const TREE_DETAIL_STEPS: LessonStep[] = [
+ { n: 1, title: "Apples", instruction: "Add a few round apples in the leaves.", lines: [``, ``, ``] },
+ { n: 2, title: "Grass", instruction: "Add wavy grass along the bottom.", lines: [``] },
+ { n: 3, title: "Bark", instruction: "Add a couple of bark lines on the trunk.", lines: [``, ``] },
+];
+
+const TREE_OUTLINE_SVG = TREE_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+const TREE_DETAIL_SVG = TREE_OUTLINE_SVG + "\n" + TREE_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+export const TREE_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:51, slug:"tree-outline", title:"Tree \u00b7 Outline", subject:"tree outline", emoji:"🌳", intro:"Let\u2019s draw Tree\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Tree Top", phase:"outline", subjectKey:"tree", subjectName:"Tree", subjectEmoji:"🌳", order:5, steps: TREE_OUTLINE_STEPS };
+
+export const TREE_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:52, slug:"tree-detail", title:"Tree \u00b7 Details", subject:"tree details", emoji:"🌳", intro:"Now add the details that bring your tree to life.", badgeKey:"early-beginner-5-tree", badgeName:"Tree Top", phase:"detail", baseSvg: TREE_OUTLINE_SVG, subjectKey:"tree", subjectName:"Tree", subjectEmoji:"🌳", order:5, steps: TREE_DETAIL_STEPS };
+
+export const TREE_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:53, slug:"tree-extra", title:"Tree \u00b7 Color it!", subject:"color the tree", emoji:"\u{1F3A8}", intro:"Bring your tree to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Tree Top", phase:"extra", baseSvg: TREE_DETAIL_SVG, subjectKey:"tree", subjectName:"Tree", subjectEmoji:"🌳", order:5, steps: [] };
+
+const DINO_OUTLINE_STEPS: LessonStep[] = [
+ { n: 1, title: "The body", instruction: "Draw a big round body.", lines: [``] },
+ { n: 2, title: "The neck", instruction: "Sweep a long neck up from the left.", lines: [``] },
+ { n: 3, title: "The head", instruction: "Add a small head on top of the neck.", lines: [``] },
+ { n: 4, title: "The tail", instruction: "Draw a long tail swooping to the right.", lines: [``] },
+ { n: 5, title: "The legs", instruction: "Add two sturdy legs underneath.", lines: [``, ``] },
+];
+
+const DINO_DETAIL_STEPS: LessonStep[] = [
+ { n: 1, title: "Back plates", instruction: "Add triangle plates along the back.", lines: [``, ``, ``, ``] },
+ { n: 2, title: "Spots", instruction: "Add a few spots on the body.", lines: [``, ``, ``] },
+ { n: 3, title: "The face", instruction: "Add an eye and a friendly smile.", lines: [``, ``] },
+];
+
+const DINO_OUTLINE_SVG = DINO_OUTLINE_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+const DINO_DETAIL_SVG = DINO_OUTLINE_SVG + "\n" + DINO_DETAIL_STEPS.flatMap((s) => s.lines || []).join("\n");
+
+export const DINO_OUTLINE_LESSON: Lesson = { level:"early-beginner", sublevel:61, slug:"dinosaur-outline", title:"Dinosaur \u00b7 Outline", subject:"dinosaur outline", emoji:"🦕", intro:"Let\u2019s draw Dinosaur\u2019s outline, one line at a time. Watch each line, then trace it!", badgeKey:"", badgeName:"Dino Master", phase:"outline", subjectKey:"dinosaur", subjectName:"Dinosaur", subjectEmoji:"🦕", order:6, steps: DINO_OUTLINE_STEPS };
+
+export const DINO_DETAIL_LESSON: Lesson = { level:"early-beginner", sublevel:62, slug:"dinosaur-detail", title:"Dinosaur \u00b7 Details", subject:"dinosaur details", emoji:"🦕", intro:"Now add the details that bring your dinosaur to life.", badgeKey:"early-beginner-6-dinosaur", badgeName:"Dino Master", phase:"detail", baseSvg: DINO_OUTLINE_SVG, subjectKey:"dinosaur", subjectName:"Dinosaur", subjectEmoji:"🦕", order:6, steps: DINO_DETAIL_STEPS };
+
+export const DINO_EXTRA_LESSON: Lesson = { level:"early-beginner", sublevel:63, slug:"dinosaur-extra", title:"Dinosaur \u00b7 Color it!", subject:"color the dinosaur", emoji:"\u{1F3A8}", intro:"Bring your dinosaur to life! Color it in, and try shading and layering.", badgeKey:"", badgeName:"Dino Master", phase:"extra", baseSvg: DINO_DETAIL_SVG, subjectKey:"dinosaur", subjectName:"Dinosaur", subjectEmoji:"🦕", order:6, steps: [] };
const SHADE_STEPS: LessonStep[] = [
- { n: 1, kind: "shade", title: "How to hold your pencil", instruction: "Watch the demo above. Holding near the tip and pressing hard makes DARK shades; holding high up and pressing soft makes LIGHT shades.",
- tip: "Try it in the air first!",
- svg: `` },
- { n: 2, kind: "shade", title: "Find the light", instruction: "The sun is up and to the left. The side of the ball facing the sun stays the brightest. That bright spot is the highlight.",
- svg: `` },
- { n: 3, kind: "shade", title: "Soft shade all over", instruction: "Pick a light tone and, with soft gentle passes, shade the whole ball — but leave the bright highlight spot white.",
- tip: "Hold high and go easy.",
- svg: `` },
- { n: 4, kind: "shade", title: "Build up the shadow", instruction: "Pick a darker tone and press a little harder on the side AWAY from the sun. Go over it a few times to build it up slowly.",
- tip: "More passes = darker.",
- svg: `` },
- { n: 5, kind: "shade", title: "Cast shadow & finish", instruction: "Shade the ground just under the ball on the shadow side. Keep that highlight bright and clean. You did it!",
- tip: "🌗",
- svg: `` },
+ { n: 1, kind: "shade", title: "How to hold your pencil", instruction: "Watch the demo above. Near the tip + press hard = DARK; high up + soft = LIGHT.", tip: "Try it in the air first!", svg: `` },
+ { n: 2, kind: "shade", title: "Find the light", instruction: "The sun is up-left. The side facing it stays brightest — that bright spot is the highlight.", svg: `` },
+ { n: 3, kind: "shade", title: "Soft shade all over", instruction: "Pick a light tone and softly shade the whole ball — leave the bright spot white.", tip: "Hold high and go easy.", svg: `` },
+ { n: 4, kind: "shade", title: "Build up the shadow", instruction: "Pick a darker tone and press harder on the side away from the sun. Build it up slowly.", tip: "More passes = darker.", svg: `` },
+ { n: 5, kind: "shade", title: "Cast shadow & finish", instruction: "Shade the ground under the ball on the shadow side. Keep the highlight clean!", tip: "🌗", svg: `` },
];
-export const SHADE_BALL_LESSON: Lesson = { level: "learner", sublevel: 1, slug: "shade-ball", title: "Light & Shadow: Shade a Ball", subject: "a shaded ball", emoji: "\u{1F317}", intro: "Time to make a flat circle look like a round ball — using light and shadow! First, learn how to hold your pencil.", badgeKey: "learner-1-shading", badgeName: "Shading Star", mode: "shade", steps: SHADE_STEPS };
+export const SHADE_BALL_LESSON: Lesson = { level:"learner", sublevel:1, slug:"shade-ball", title:"Light & Shadow: Shade a Ball", subject:"a shaded ball", emoji:"\u{1F317}", intro:"Make a flat circle look like a round ball using light and shadow!", badgeKey:"learner-1-shading", badgeName:"Shading Star", mode:"shade", subjectKey:"shade-ball", subjectName:"Shade a Ball", subjectEmoji:"\u{1F317}", order:1, steps: SHADE_STEPS };
-export const LESSONS: Lesson[] = [FISH_OUTLINE_LESSON, FISH_DETAIL_LESSON, FISH_EXTRA_LESSON, PANDA_LESSON, FLOWER_LESSON, UNICORN_LESSON, TREE_LESSON, DINO_LESSON, SHADE_BALL_LESSON];
+export const LESSONS: Lesson[] = [FISH_OUTLINE_LESSON, FISH_DETAIL_LESSON, FISH_EXTRA_LESSON, PANDA_OUTLINE_LESSON, PANDA_DETAIL_LESSON, PANDA_EXTRA_LESSON, FLOWER_OUTLINE_LESSON, FLOWER_DETAIL_LESSON, FLOWER_EXTRA_LESSON, UNICORN_OUTLINE_LESSON, UNICORN_DETAIL_LESSON, UNICORN_EXTRA_LESSON, TREE_OUTLINE_LESSON, TREE_DETAIL_LESSON, TREE_EXTRA_LESSON, DINO_OUTLINE_LESSON, DINO_DETAIL_LESSON, DINO_EXTRA_LESSON, SHADE_BALL_LESSON];
export function getLesson(level: string, sublevel: number): Lesson | undefined { return LESSONS.find((l) => l.level === level && l.sublevel === sublevel); }
export function getLessonBySlug(slug: string): Lesson | undefined { return LESSONS.find((l) => l.slug === slug); }
export function cumulativeSvg(lesson: Lesson, upTo: number): string { return lesson.steps.filter((s) => s.n <= upTo).map((s) => s.svg || "").join("\n"); }
export function cumulativeLines(lesson: Lesson, upTo: number): string { return lesson.steps.filter((s) => s.n <= upTo).flatMap((s) => s.lines || []).join("\n"); }
-
-/** Subjects in a level, in order, each with its phase lessons (or a single legacy lesson). */
export function getSubjects(level: string): { key: string; name: string; emoji: string; order: number; lessons: Lesson[] }[] {
const inLevel = LESSONS.filter((l) => l.level === level);
const map = new Map();
@@ -198,7 +185,7 @@ export function getSubjects(level: string): { key: string; name: string; emoji:
if (!map.has(key)) map.set(key, { key, name: l.subjectName || l.title, emoji: l.subjectEmoji || l.emoji, order: l.order ?? l.sublevel, lessons: [] });
map.get(key)!.lessons.push(l);
}
- const phaseRank: Record = { outline: 0, detail: 1, extra: 2 };
- for (const s of map.values()) s.lessons.sort((a, b) => (phaseRank[a.phase ?? ""] ?? 0) - (phaseRank[b.phase ?? ""] ?? 0));
+ const rank: Record = { outline: 0, detail: 1, extra: 2 };
+ for (const s of map.values()) s.lessons.sort((a, b) => (rank[a.phase ?? ""] ?? 0) - (rank[b.phase ?? ""] ?? 0));
return [...map.values()].sort((a, b) => a.order - b.order);
}