diff --git a/docs/templates/notebook-cover.md b/docs/templates/notebook-cover.md
new file mode 100644
index 0000000..8c3b31b
--- /dev/null
+++ b/docs/templates/notebook-cover.md
@@ -0,0 +1,84 @@
+# Notebook Cover
+
+Notebook/study-notes carousel cover: handwritten hero, tagline banner, 6-step pipeline with inline SVG icons, dashed intro box, and a 9-row table of contents with dot leaders. Pairs with `notebook-page` for the inner slides.
+
+## Preview
+
+
+
+## Dimensions
+
+- **Width:** 1080px
+- **Height:** 1350px
+- **Aspect Ratio:** 1080:1350
+
+## Fonts
+
+- Kalam
+- Caveat
+- Inter
+
+## Brand Fields
+
+| Field | Type | Required | Max / Default |
+|---|---|---|---|
+| `accent_color` | text | - | #1e3a8a |
+| `accent_color_end` | text | - | #6d28d9 |
+| `bg_color` | text | - | #fdfcf5 |
+| `bg_color_end` | text | - | #fdfcf5 |
+| `bg_image` | image | - | - |
+| `bg_image_opacity` | number | - | 0.15 |
+| `logo` | image | - | - |
+| `show_brand` | boolean | - | false |
+| `brand_handle` | text | - | @ajianaz |
+| `brand_name` | text | yes | ajianaz |
+
+## Slide Fields
+
+| Field | Type | Required | Max / Default |
+|---|---|---|---|
+| `header_handle` | text | yes | max 30 - Left header text (e.g. IG handle). |
+| `page_label` | text | yes | max 12 - Right header label (e.g. 'cover'). |
+| `hero_title` | text | yes | max 18 - Big display title (Caveat). |
+| `hero_font_size` | number | - | Hero font size (140-170). |
+| `hero_subtitle` | text | yes | max 46 - Uppercase subtitle under hero. |
+| `tagline` | text | yes | max 60 - Italic banner line. |
+| `icon1` | text | - | Pipeline icon 1: note/phone/brain/search/spark/rocket. |
+| `icon2` | text | - | Pipeline icon 2. |
+| `icon3` | text | - | Pipeline icon 3. |
+| `icon4` | text | - | Pipeline icon 4. |
+| `icon5` | text | - | Pipeline icon 5. |
+| `icon6` | text | - | Pipeline icon 6. |
+| `label1` | text | yes | max 14 - Pipeline label 1. |
+| `label2` | text | yes | max 14 - Pipeline label 2. |
+| `label3` | text | yes | max 14 - Pipeline label 3. |
+| `label4` | text | yes | max 14 - Pipeline label 4. |
+| `label5` | text | yes | max 14 - Pipeline label 5. |
+| `label6` | text | yes | max 14 - Pipeline label 6. |
+| `intro_lead` | text | yes | max 20 - Bold lead inside dashed intro box (purple). |
+| `intro_text` | text | yes | max 150 - Intro sentence (wrapped). |
+| `toc_title` | text | yes | max 24 - Table-of-contents heading. |
+| `toc1` | text | yes | max 22 |
+| `pg1` | text | yes | max 8 |
+| `toc2` | text | yes | max 22 |
+| `pg2` | text | yes | max 8 |
+| `toc3` | text | yes | max 22 |
+| `pg3` | text | yes | max 8 |
+| `toc4` | text | yes | max 22 |
+| `pg4` | text | yes | max 8 |
+| `toc5` | text | yes | max 22 |
+| `pg5` | text | yes | max 8 |
+| `toc6` | text | yes | max 22 |
+| `pg6` | text | yes | max 8 |
+| `toc7` | text | yes | max 22 |
+| `pg7` | text | yes | max 8 |
+| `toc8` | text | yes | max 22 |
+| `pg8` | text | yes | max 8 |
+| `toc9` | text | yes | max 22 |
+| `pg9` | text | yes | max 8 |
+
+## Usage
+
+```bash
+cosy render --template notebook-cover --data input.json --output output.png
+```
diff --git a/docs/templates/notebook-page.md b/docs/templates/notebook-page.md
new file mode 100644
index 0000000..f8c9b9e
--- /dev/null
+++ b/docs/templates/notebook-page.md
@@ -0,0 +1,59 @@
+# Notebook Page
+
+Notebook/study-notes content page: chapter title box, star bullets, dashed example box (optional), cloud punchline callout, optional second dashed box, and a bottom brand line. Pairs with `notebook-cover`.
+
+## Preview
+
+
+
+## Dimensions
+
+- **Width:** 1080px
+- **Height:** 1350px
+- **Aspect Ratio:** 1080:1350
+
+## Fonts
+
+- Kalam
+- Caveat
+- Inter
+
+## Brand Fields
+
+| Field | Type | Required | Max / Default |
+|---|---|---|---|
+| `accent_color` | text | - | #1e3a8a |
+| `accent_color_end` | text | - | #6d28d9 |
+| `bg_color` | text | - | #fdfcf5 |
+| `bg_color_end` | text | - | #fdfcf5 |
+| `bg_image` | image | - | - |
+| `bg_image_opacity` | number | - | 0.15 |
+| `logo` | image | - | - |
+| `show_brand` | boolean | - | false |
+| `brand_handle` | text | - | @ajianaz |
+| `brand_name` | text | yes | ajianaz |
+
+## Slide Fields
+
+| Field | Type | Required | Max / Default |
+|---|---|---|---|
+| `header_handle` | text | yes | max 30 - Left header text (e.g. IG handle). |
+| `page_label` | text | yes | max 12 - Right header label (e.g. 'Page 1'). |
+| `chapter_title` | text | yes | max 30 - Chapter title inside the box. |
+| `lead_text` | text | yes | max 140 - Lead sentence (wrapped). |
+| `bullet1` | text | - | max 120 - Bullet point 1. |
+| `bullet2` | text | - | max 120 - Bullet point 2. |
+| `bullet3` | text | - | max 120 - Bullet point 3. |
+| `box_title` | text | - | max 30 - Dashed box title (omit to hide box). |
+| `box_text` | text | - | max 200 - Dashed box body (wrapped). |
+| `box_color` | color | - | Dashed box border/title color (default accent). |
+| `punchline` | text | yes | max 90 - Cloud callout punchline (wrapped). |
+| `extra_title` | text | - | max 30 - Second dashed box title (omit to hide). |
+| `extra_text` | text | - | max 180 - Second dashed box body (wrapped). |
+| `footer_line` | text | - | max 60 - Bottom center line (brand/CTA). |
+
+## Usage
+
+```bash
+cosy render --template notebook-page --data input.json --output output.png
+```
diff --git a/src/assets/fonts/Caveat-Bold.ttf b/src/assets/fonts/Caveat-Bold.ttf
new file mode 100644
index 0000000..d3a3f87
Binary files /dev/null and b/src/assets/fonts/Caveat-Bold.ttf differ
diff --git a/src/assets/fonts/Caveat-Medium.ttf b/src/assets/fonts/Caveat-Medium.ttf
new file mode 100644
index 0000000..d0ec399
Binary files /dev/null and b/src/assets/fonts/Caveat-Medium.ttf differ
diff --git a/src/assets/fonts/Kalam-Bold.ttf b/src/assets/fonts/Kalam-Bold.ttf
new file mode 100644
index 0000000..bedadb6
Binary files /dev/null and b/src/assets/fonts/Kalam-Bold.ttf differ
diff --git a/src/assets/fonts/Kalam-Light.ttf b/src/assets/fonts/Kalam-Light.ttf
new file mode 100644
index 0000000..600ba0a
Binary files /dev/null and b/src/assets/fonts/Kalam-Light.ttf differ
diff --git a/src/assets/fonts/Kalam-Regular.ttf b/src/assets/fonts/Kalam-Regular.ttf
new file mode 100644
index 0000000..e170f29
Binary files /dev/null and b/src/assets/fonts/Kalam-Regular.ttf differ
diff --git a/src/render.rs b/src/render.rs
index 6519dec..eb46055 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -264,8 +264,39 @@ pub fn build_font_db(custom_dir: Option<&Path>) -> anyhow::Result
+
+
+
+
+
+
+
+
+
+
+ {% if bg_image_data_uri %}
+
+
+ {% endif %}
+
+
+
+
+
+
+
+ {{ slide.header_handle }}
+ {{ slide.page_label }}
+
+
+ {% set hero_len = slide.hero_title | length %}
+ {% if hero_len > 10 %}{% set hfs = (1000 / hero_len) | round | int %}{% else %}{% set hfs = slide.hero_font_size | default(150) %}{% endif %}
+ {{ slide.hero_title }}
+ {% set slen = slide.hero_subtitle | length %}
+ {% if slen > 26 %}{% set sfs = (900 / slen) | round | int %}{% else %}{% set sfs = 34 %}{% endif %}
+ {{ slide.hero_subtitle }}
+
+
+
+ {% set tlen = slide.tagline | length %}
+ {% if tlen > 46 %}{% set tfs = (1309 / tlen) | round | int %}{% else %}{% set tfs = 26 %}{% endif %}
+ {{ slide.tagline }}
+
+
+ {% macro pipe_icon(kind, cx, cy) %}{% if not kind %}{% set kind = 'note' %}{% endif %}
+ {% if kind == 'note' %}
+ {% elif kind == 'phone' %}
+ {% elif kind == 'brain' %}
+ {% elif kind == 'search' %}
+ {% elif kind == 'spark' %}
+ {% elif kind == 'rocket' %}
+ {% endif %}
+ {% endmacro %}
+ {% for i in range(6) %}
+
+ {% set bx = 116 + i * 145 %}
+
+ {{ pipe_icon(slide.icon1 if i == 0 else slide.icon2 if i == 1 else slide.icon3 if i == 2 else slide.icon4 if i == 3 else slide.icon5 if i == 4 else slide.icon6, bx + 64, 556) }}
+ {{ slide.label1 if i == 0 else slide.label2 if i == 1 else slide.label3 if i == 2 else slide.label4 if i == 3 else slide.label5 if i == 4 else slide.label6 }}
+ {% if i < 5 %}{% endif %}
+
+ {% endfor %}
+
+
+ {{ slide.intro_lead }}
+ {% for ln in slide.intro_text|wordwrap(74)|split('
+') %}{{ ln }}{% endfor %}
+
+ {{ slide.toc_title }}
+ {% for n in range(9) %}
+ {% set ly = 848 + n * 40 %}
+ {% if n == 0 %}{% set entry = slide.toc1 %}{% set pg = slide.pg1 %}
+ {% elif n == 1 %}{% set entry = slide.toc2 %}{% set pg = slide.pg2 %}
+ {% elif n == 2 %}{% set entry = slide.toc3 %}{% set pg = slide.pg3 %}
+ {% elif n == 3 %}{% set entry = slide.toc4 %}{% set pg = slide.pg4 %}
+ {% elif n == 4 %}{% set entry = slide.toc5 %}{% set pg = slide.pg5 %}
+ {% elif n == 5 %}{% set entry = slide.toc6 %}{% set pg = slide.pg6 %}
+ {% elif n == 6 %}{% set entry = slide.toc7 %}{% set pg = slide.pg7 %}
+ {% elif n == 7 %}{% set entry = slide.toc8 %}{% set pg = slide.pg8 %}
+ {% else %}{% set entry = slide.toc9 %}{% set pg = slide.pg9 %}
+ {% endif %}
+ {{ n + 1 }}. {{ entry }}
+ {{ pg }}
+
+ {% endfor %}
+
\ No newline at end of file
diff --git a/templates/notebook-page/defaults.json b/templates/notebook-page/defaults.json
new file mode 100644
index 0000000..2534e40
--- /dev/null
+++ b/templates/notebook-page/defaults.json
@@ -0,0 +1,29 @@
+{
+ "brand": {
+ "brand_name": "ajianaz",
+ "brand_handle": "@ajianaz",
+ "bg_color": "#fdfcf5",
+ "bg_color_end": "#fdfcf5",
+ "accent_color": "#1e3a8a",
+ "accent_color_end": "#6d28d9",
+ "show_brand": false
+ },
+ "slides": [
+ {
+ "header_handle": "IG: ajianaz",
+ "page_label": "Hal. 1",
+ "chapter_title": "1. MASALAH: IDE HILANG",
+ "lead_text": "Kita menulis ratusan catatan setiap bulan. Lalu kenapa tetap kehilangan ide?",
+ "bullet1": "Ide terbaik datang di luar meja kerja: di lift, jalan, antrean.",
+ "bullet2": "Kita buru-buru mengetik tanpa mikir kata kunci besok.",
+ "bullet3": "Tiga minggu kemudian: catatannya tidak ketemu.",
+ "box_title": "Contoh nyata",
+ "box_color": "#c2387d",
+ "box_text": "Kamu menulis 'ide paket harga klien kecil'. Tiga minggu kemudian mencari 'strategi pricing UMKM'. Beda kata, satu makna.",
+ "punchline": "Masalahnya bukan kamu pelupa. Masalahnya cara aplikasi mencari.",
+ "extra_title": "Cara mengujinya",
+ "extra_text": "Matikan internet, lalu cari catatanmu berdasarkan makna. Kalau tetap ketemu, berarti semua prosesnya benar-benar di perangkatmu.",
+ "footer_line": "uteke mobile - uteke.app"
+ }
+ ]
+}
diff --git a/templates/notebook-page/schema.json b/templates/notebook-page/schema.json
new file mode 100644
index 0000000..30b4e02
--- /dev/null
+++ b/templates/notebook-page/schema.json
@@ -0,0 +1,154 @@
+{
+ "id": "notebook-page",
+ "name": "Notebook Page",
+ "description": "Notebook/study-notes content page: chapter box, bullets, dashed box, cloud punchline (1080x1350).",
+ "dimensions": {
+ "width": 1080,
+ "height": 1350
+ },
+ "fonts": [
+ "Kalam",
+ "Caveat",
+ "Inter"
+ ],
+ "brand_fields": {
+ "show_brand": {
+ "type": "boolean",
+ "required": false,
+ "default": false,
+ "description": "Show brand name/handle watermark at bottom. Default: false."
+ },
+ "brand_name": {
+ "type": "text",
+ "required": true,
+ "max": 30
+ },
+ "brand_handle": {
+ "type": "text",
+ "required": false,
+ "max": 30
+ },
+ "bg_color": {
+ "type": "bg",
+ "required": false,
+ "default": "#fdfcf5",
+ "description": "Paper base color."
+ },
+ "bg_color_end": {
+ "type": "bg",
+ "required": false,
+ "default": "#fdfcf5",
+ "description": "Second gradient stop (kept for brand-field uniformity; paper look uses solid color)."
+ },
+ "accent_color": {
+ "type": "bg",
+ "required": false,
+ "default": "#1e3a8a",
+ "description": "Primary ink color."
+ },
+ "accent_color_end": {
+ "type": "bg",
+ "required": false,
+ "default": "#6d28d9",
+ "description": "Secondary accent (purple callouts)."
+ },
+ "bg_image": {
+ "type": "image",
+ "required": false
+ },
+ "bg_image_opacity": {
+ "type": "number",
+ "required": false,
+ "default": 0.15
+ },
+ "logo": {
+ "type": "image",
+ "required": false
+ }
+ },
+ "slide_fields": {
+ "header_handle": {
+ "type": "text",
+ "required": true,
+ "max": 30,
+ "description": "Left header text (e.g. IG handle)."
+ },
+ "page_label": {
+ "type": "text",
+ "required": true,
+ "max": 12,
+ "description": "Right header label (e.g. 'Page 1')."
+ },
+ "chapter_title": {
+ "type": "text",
+ "required": true,
+ "max": 30,
+ "description": "Chapter title inside the box."
+ },
+ "lead_text": {
+ "type": "text",
+ "required": true,
+ "max": 140,
+ "description": "Lead sentence (wrapped)."
+ },
+ "bullet1": {
+ "type": "text",
+ "required": false,
+ "max": 120,
+ "description": "Bullet point 1."
+ },
+ "bullet2": {
+ "type": "text",
+ "required": false,
+ "max": 120,
+ "description": "Bullet point 2."
+ },
+ "bullet3": {
+ "type": "text",
+ "required": false,
+ "max": 120,
+ "description": "Bullet point 3."
+ },
+ "box_title": {
+ "type": "text",
+ "required": false,
+ "max": 30,
+ "description": "Dashed box title (omit to hide box)."
+ },
+ "box_text": {
+ "type": "text",
+ "required": false,
+ "max": 200,
+ "description": "Dashed box body (wrapped)."
+ },
+ "box_color": {
+ "type": "color",
+ "required": false,
+ "description": "Dashed box border/title color (default accent)."
+ },
+ "punchline": {
+ "type": "text",
+ "required": true,
+ "max": 90,
+ "description": "Cloud callout punchline (wrapped)."
+ },
+ "extra_title": {
+ "type": "text",
+ "required": false,
+ "max": 30,
+ "description": "Second dashed box title (omit to hide)."
+ },
+ "extra_text": {
+ "type": "text",
+ "required": false,
+ "max": 180,
+ "description": "Second dashed box body (wrapped)."
+ },
+ "footer_line": {
+ "type": "text",
+ "required": false,
+ "max": 60,
+ "description": "Bottom center line (brand/CTA)."
+ }
+ }
+}
diff --git a/templates/notebook-page/template.svg b/templates/notebook-page/template.svg
new file mode 100644
index 0000000..a4f195c
--- /dev/null
+++ b/templates/notebook-page/template.svg
@@ -0,0 +1,74 @@
+
\ No newline at end of file