Slide Creator — HTML → PDF Presentations
Build slide decks as HTML, export to pixel-perfect 16:9 PDF via headless Chromium.
Output format: PDF — not Microsoft PowerPoint (.pptx). The PDF preserves exact layout, fonts, and colors across all devices.
Why HTML → PDF
- CSS layout (Grid/Flexbox) is far more flexible than any PPT editor
- Full web typography, gradients, SVG, animations (print degrades gracefully)
- Git-friendly, reproducible, scriptable
- One command → PDF with exact 16:9 page dimensions
Workflow
0. Identify Scenario (new)
Before any other step, identify the presentation scenario. Read references/content-scaffolding.md for full templates.
| Scenario keyword |
Template to use |
| pitch / investor / fundraising |
pitch-deck |
| conference / keynote / summit / talk |
conference-keynote |
| product launch / launch event |
product-launch |
| report / research / analysis |
research-report |
| (none of the above) |
ask user which scenario fits best |
Each template defines: slide count, page titles, required content per page.
0.5 Bilingual Layout (if needed)
If the audience is bilingual (e.g. HK, Singapore, global Chinese conference), or the user mentions Chinese + English:
- Use the
bilingual layout mode from references/content-scaffolding.md
- Heading: English (large) + Chinese subtitle (smaller, --text-muted)
- Body bullets: Chinese first, English parenthetical optional
- Avoid pure English-only decks for HK/TW/SG audiences
1. Plan the Deck
Define slide count and content per slide based on the scenario template. Each slide = one <section class="slide">.
1.5 Art Direction (run this before building)
Run this step whenever the user hasn't provided a specific visual style.
Read skills/slide-creator/references/art-direction.md for the full style taxonomy,
CSS token templates, and style-brief output format.
Step A — Ask 4 questions:
- Audience & setting: who is this for, and in what context (investors / internal team / public keynote)?
- Mood keywords: how should the audience feel (authoritative / energetic / friendly / geeky-modern)?
- Brand constraints: any required brand colors, logo, or fonts?
- Reference material: any template references to align with (images, web links, existing deck screenshots)?
Step B — Generate a visual style picker page:
Do NOT present style options as text descriptions — users can't evaluate styles from words alone.
Reference handling rules:
- If user provides image files/screenshots: sample palette (primary/surface/accent), inspect layout density, corner radius, typography tone from the visual.
- If user provides web URLs: use
web_fetch to extract design cues. Critical — follow this extraction protocol to avoid misreading the style:
- Ignore the brand name / domain name — never infer visual style from the product's industry or name (e.g. "Neo" does NOT mean neon, "Opera" does NOT mean European luxury).
- Read copy tone & vocabulary — the words used on the page reveal mood (e.g. "surgical precision", "quiet confidence" → restrained; "unleash", "radically" → bold/aggressive).
- Extract explicit color vocabulary — look for CSS keywords in the fetched text, or color names mentioned in body text / alt tags. Warm vs cool, light vs dark, muted vs saturated.
- Infer layout density — count words per section; sparse = editorial/luxury, dense = technical/functional.
- Identify decorative motifs — mentioned or implied (e.g. geometry, gradients, photography, illustration, line art, brutalism).
- Cross-check against art-direction.md — find the closest matching template, then describe the delta (e.g. "Style G but warmer, replace blue with burnt orange, add subtle grid lines").
- When uncertain: be conservative — under-promise the style match and present 3 options where Option A is your best interpretation, B is safer/cleaner, C is more experimental. Never confidently assert a style that contradicts the actual visual evidence.
- If user provides both: prioritize image cues first, URL cues second.
- If no references are provided: use built-in style taxonomy defaults.
Then:
- Create
output/style-picker/index.html — a single page with 3 side-by-side mini slide previews (16:9 aspect ratio), each fully rendered with real CSS (colors, fonts, layout, decorative elements). Each preview must look like an actual slide, not a color chip.
- Build these 3 options as: (A) Reference-faithful, (B) Safer corporate variant, (C) Bolder creative variant.
preview(action='serve') the directory and show the preview URL.
- Each card has a label below: style name + one-line description.
- Add
onclick highlight so the user can click to indicate their choice.
User picks by saying "Choose A" / "I want B" / "Blend A+C" etc.
Step C — Generate style-brief.md:
Once user selects a style, write a style-brief.md (template in art-direction.md) in the project directory.
All subsequent HTML/CSS work must follow this brief.
Step D — Ask for brand assets (logo / colors):
After user picks a style, ask:
"Do you have a logo or brand color to include? You can upload an image file, and I’ll embed the logo across the slides."
If logo uploaded: embed as base64 in HTML (use base64.b64encode in bash), place in top-left or top-right corner at ≤60px height.
If brand color given: override --accent in CSS token block with user's color.
2. Choose a Theme
If Art Direction was completed, the style-brief.md is the theme spec — skip this table.
Otherwise, use as a quick fallback:
| Style |
Background |
Accent |
Font |
Mood |
| Dark tech |
#000 / #0a0a0a |
bright orange/blue/green |
Inter, Space Grotesk |
Bold, modern |
| Light clean |
#fff / #f8f8f8 |
navy, teal, coral |
Inter, DM Sans |
Professional, minimal |
| Gradient |
dark gradient |
vibrant accent |
Any sans-serif |
Creative, energetic |
| Corporate |
#1a1a2e / white |
brand color |
system fonts |
Trustworthy, formal |
| Playful |
soft pastels |
warm pop colors |
Nunito, Poppins |
Friendly, casual |
3. Build HTML + CSS
Create a project directory with index.html + styles.css.
Start from assets/base.css — structural skeleton (slide dimensions, print rules, layout helpers) with NO colors or fonts. Layer your theme on top:
/* Example theme layer — customize freely */
body {
font-family: 'Inter', sans-serif;
color: #fff;
background: #000;
}
.slide { background: #0a0a0a; }
.slide-tag { background: rgba(0,120,255,0.15); color: #0078ff; }
.card { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); }
Mandatory structural rules (in base.css — don't remove):
.slide { width: 1280px; height: 720px; page-break-after: always; overflow: hidden; }
@page { size: 1280px 720px; margin: 0; }
Key rules:
- Use
px units — never vh/vw/rem/% for slide dimensions
- Google Fonts: use
<link> in <head>, export script waits for network idle
- Viewport meta:
<meta name="viewport" content="width=1280">
- Content must fit within 720px height — overflow is clipped
4. Preview (Optional)
Use preview(action='serve') to preview in browser before exporting.
5. Export to PDF
python3 skills/slide-creator/scripts/export_pdf.py --dir <project-dir> --output output/<name>.pdf
Options:
--dir — directory containing index.html (required)
--output / -o — output PDF path (default: <dir>/deck.pdf)
--width — slide width in px (default: 1280)
--height — slide height in px (default: 720)
6. Verify
The script prints slide count and confirms output path. Extra check:
import fitz
doc = fitz.open("output/deck.pdf")
print(f"Pages: {doc.page_count}")
for p in doc:
r = p.rect
print(f" {r.width*96/72:.0f}x{r.height*96/72:.0f}px")
Style Guidelines
- No default brand — every deck gets a theme tailored to its content
- Prefer Art Direction-first workflow (questions → references → user pick →
style-brief.md)
- Ask the user for preference: dark/light, accent color, font, mood
- Each slide should have clear visual hierarchy: tag → title → content
- Keep text concise — slides are visual, not documents
- Use
.bg-glow with theme-colored radial gradients for depth
- Do not use
web_search for style exploration by default; prioritize user-provided reference images/links plus templates in art-direction.md.
- When the user provides reference links, use
web_fetch to extract design cues (color tone / voice / layout), but implement final CSS using local templates and token variables.
- When the user asks for "art-direction advice / style advice", always generate a visual style-picker preview page (3 options) — never rely on text-only descriptions.
- Build HTML strictly against chosen style brief, then export PDF (do not skip brief unless user explicitly opts out)
- After style is chosen, always ask about logo / brand assets before building
- For HK/TW/SG/bilingual audiences, default to bilingual layout unless user says English only
Style Microtweaks (after style is chosen)
If user says "change primary color to red" / "switch the font" / "increase corner radius", do NOT restart art direction.
Instead, directly patch the --accent / --font-head / --radius CSS variable in styles.css.
Only restart art direction if user wants a completely different style.
Gotchas
Chromium: pre-installed via workspace/setup.sh on container start (641 MB cached at `/.cache/ms-playwright/). Do NOT run playwright installon every export — it re-downloads the same browser. Only run it ifexport_pdf.pyfails withExecutable doesn't exist, and in that case also append the command to workspace/setup.sh` so it persists.
Fonts: Google Fonts need HTTP — the export script starts a local server automatically
Emoji rendering: headless Chromium may lack emoji fonts — use SVG icons instead
Large images: embed as base64 or use relative paths (local server serves the project dir)
Slide overflow: content exceeding 720px height is clipped — design within bounds
⚠️ PDF text not selectable (verified 2026): filter / backdrop-filter CSS on any ancestor containing text causes Chromium to rasterize that layer to bitmap during PDF export — all child text becomes pixels, not selectable. Fix: NEVER apply filter/backdrop-filter to containers holding text. Only apply to empty decorative <div> elements (e.g. .blur-layer, .glow-overlay) with no text children. Same rule applies to mix-blend-mode on text parents. Pre-export checklist: search HTML for filter/backdrop-filter on non-decorative elements and strip them.
⚠️ Footer / source attribution — use standard component + strict bottom-safe-area contract (verified 2026): ad-hoc footer markup causes inconsistent positioning across slides. Always use this .slide-footer pattern for all source citations, page numbers, and disclaimers.
Hard layout contract (do not skip):
- Every non-cover slide must have a dedicated content wrapper (e.g.
.slide-body) that reserves footer space.
- Hard rule:
.slide-body must reserve footer space with bottom-safe-area >= 96px (default 96px). Example: .slide-body { padding: 52px 72px 96px; }.
- Footer must be outside normal flow:
position: absolute; bottom: 24px, as a sibling of .slide-body directly under .slide.
- Never place source/disclaimer text inside
.slide-body.
- Cover page can be exception only when it has no
.slide-footer.
This enforces physical separation: body content area ends above a reserved footer lane, and footer stays in the canvas-bottom lane, so they never overlap regardless of content density.
<footer class="slide-footer">
<span class="footer-source">Source: CoinGecko · Coinglass · DefiLlama</span>
<span class="footer-page">03 / 12</span>
</footer>
.slide-footer {
position: absolute;
bottom: 24px; left: 48px; right: 48px;
display: flex; justify-content: space-between; align-items: center;
font-size: 11px; color: rgba(255,255,255,0.35);
border-top: 1px solid rgba(255,255,255,0.08);
padding-top: 8px;
z-index: 2;
}
.slide > *:not(.bg-glow):not(.slide-footer) {
position: relative;
z-index: 1;
}
.slide-body { padding-bottom: 96px; }
Never use in-flow / position: relative footers — they shift when slide content height changes. Also exclude .slide-footer from generic .slide > * stacking rules, or CSS order can accidentally override footer layering.
Validation checklist (required before export):
- every non-cover slide has
.slide-body and .slide-footer as siblings;
.slide-body bottom padding is >=96px;
- source/disclaimer text appears only inside
.slide-footer, never in body containers.
⚠️ z-index / decorative overlay bug (verified 2026): .bg-glow and other decorative pseudo-layers MUST be positioned with z-index: 0 and all real slide content given z-index: 1 explicitly. If .bg-glow is a sibling of .slide > * (not a ::before/::after pseudo-element), add this rule to ensure content is never visually buried:
.slide > *:not(.bg-glow) { position: relative; z-index: 1; }
.bg-glow { position: absolute; z-index: 0; pointer-events: none; }
Failure mode: PDF exports show content pushed to the bottom or invisible, even though browser preview looks fine (browser compositing handles z-order more forgivingly than Chromium's print path).
1---2name: slide-creator3description: Build 16:9 slide decks as HTML, exported to PDF (not PowerPoint format). Use when making a deck, presentation, or pitch (e.g. 10-slide pitch deck for X, training course on Y, quarterly results presentation).4---56# Slide Creator — HTML → PDF Presentations78Build slide decks as HTML, export to pixel-perfect 16:9 PDF via headless Chromium.910**Output format: PDF** — not Microsoft PowerPoint (.pptx). The PDF preserves exact layout, fonts, and colors across all devices.1112## Why HTML → PDF1314- CSS layout (Grid/Flexbox) is far more flexible than any PPT editor15- Full web typography, gradients, SVG, animations (print degrades gracefully)16- Git-friendly, reproducible, scriptable17- One command → PDF with exact 16:9 page dimensions1819## Workflow2021### 0. Identify Scenario (new)2223Before any other step, identify the presentation scenario. Read `references/content-scaffolding.md` for full templates.2425| Scenario keyword | Template to use |26|-----------------|----------------|27| pitch / investor / fundraising | `pitch-deck` |28| conference / keynote / summit / talk | `conference-keynote` |29| product launch / launch event | `product-launch` |30| report / research / analysis | `research-report` |31| (none of the above) | ask user which scenario fits best |3233Each template defines: slide count, page titles, required content per page.3435### 0.5 Bilingual Layout (if needed)3637If the audience is bilingual (e.g. HK, Singapore, global Chinese conference), or the user mentions Chinese + English:38- Use the `bilingual` layout mode from `references/content-scaffolding.md`39- Heading: English (large) + Chinese subtitle (smaller, --text-muted)40- Body bullets: Chinese first, English parenthetical optional41- Avoid pure English-only decks for HK/TW/SG audiences4243### 1. Plan the Deck4445Define slide count and content per slide based on the scenario template. Each slide = one `<section class="slide">`.4647### 1.5 Art Direction (run this before building)4849> Run this step whenever the user hasn't provided a specific visual style.50> Read `skills/slide-creator/references/art-direction.md` for the full style taxonomy,51> CSS token templates, and style-brief output format.5253**Step A — Ask 4 questions:**541. Audience & setting: who is this for, and in what context (investors / internal team / public keynote)?552. Mood keywords: how should the audience feel (authoritative / energetic / friendly / geeky-modern)?563. Brand constraints: any required brand colors, logo, or fonts?574. Reference material: any template references to align with (images, web links, existing deck screenshots)?5859**Step B — Generate a visual style picker page:**60Do NOT present style options as text descriptions — users can't evaluate styles from words alone.6162Reference handling rules:63- If user provides **image files/screenshots**: sample palette (primary/surface/accent), inspect layout density, corner radius, typography tone from the visual.64- If user provides **web URLs**: use `web_fetch` to extract design cues. **Critical — follow this extraction protocol to avoid misreading the style:**65 1. **Ignore the brand name / domain name** — never infer visual style from the product's industry or name (e.g. "Neo" does NOT mean neon, "Opera" does NOT mean European luxury).66 2. **Read copy tone & vocabulary** — the words used on the page reveal mood (e.g. "surgical precision", "quiet confidence" → restrained; "unleash", "radically" → bold/aggressive).67 3. **Extract explicit color vocabulary** — look for CSS keywords in the fetched text, or color names mentioned in body text / alt tags. Warm vs cool, light vs dark, muted vs saturated.68 4. **Infer layout density** — count words per section; sparse = editorial/luxury, dense = technical/functional.69 5. **Identify decorative motifs** — mentioned or implied (e.g. geometry, gradients, photography, illustration, line art, brutalism).70 6. **Cross-check against art-direction.md** — find the closest matching template, then describe the delta (e.g. "Style G but warmer, replace blue with burnt orange, add subtle grid lines").71 7. **When uncertain**: be conservative — under-promise the style match and present 3 options where Option A is your best interpretation, B is safer/cleaner, C is more experimental. **Never confidently assert a style that contradicts the actual visual evidence.**72- If user provides both: prioritize image cues first, URL cues second.73- If no references are provided: use built-in style taxonomy defaults.7475Then:761. Create `output/style-picker/index.html` — a single page with 3 side-by-side mini slide previews (16:9 aspect ratio), each fully rendered with real CSS (colors, fonts, layout, decorative elements). Each preview must look like an actual slide, not a color chip.772. Build these 3 options as: **(A) Reference-faithful**, **(B) Safer corporate variant**, **(C) Bolder creative variant**.783. `preview(action='serve')` the directory and show the preview URL.794. Each card has a label below: style name + one-line description.805. Add `onclick` highlight so the user can click to indicate their choice.8182User picks by saying "Choose A" / "I want B" / "Blend A+C" etc.8384**Step C — Generate style-brief.md:**85Once user selects a style, write a `style-brief.md` (template in art-direction.md) in the project directory.86All subsequent HTML/CSS work must follow this brief.8788**Step D — Ask for brand assets (logo / colors):**89After user picks a style, ask:90> "Do you have a logo or brand color to include? You can upload an image file, and I’ll embed the logo across the slides."9192If logo uploaded: embed as base64 in HTML (use `base64.b64encode` in bash), place in top-left or top-right corner at ≤60px height.93If brand color given: override `--accent` in CSS token block with user's color.9495### 2. Choose a Theme9697If Art Direction was completed, the `style-brief.md` is the theme spec — skip this table.98Otherwise, use as a quick fallback:99100| Style | Background | Accent | Font | Mood |101|-------|-----------|--------|------|------|102| Dark tech | `#000` / `#0a0a0a` | bright orange/blue/green | Inter, Space Grotesk | Bold, modern |103| Light clean | `#fff` / `#f8f8f8` | navy, teal, coral | Inter, DM Sans | Professional, minimal |104| Gradient | dark gradient | vibrant accent | Any sans-serif | Creative, energetic |105| Corporate | `#1a1a2e` / white | brand color | system fonts | Trustworthy, formal |106| Playful | soft pastels | warm pop colors | Nunito, Poppins | Friendly, casual |107108### 3. Build HTML + CSS109110Create a project directory with `index.html` + `styles.css`.111112**Start from `assets/base.css`** — structural skeleton (slide dimensions, print rules, layout helpers) with NO colors or fonts. Layer your theme on top:113114```css115/* Example theme layer — customize freely */116body {117 font-family: 'Inter', sans-serif;118 color: #fff;119 background: #000;120}121.slide { background: #0a0a0a; }122.slide-tag { background: rgba(0,120,255,0.15); color: #0078ff; }123.card { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); }124```125126**Mandatory structural rules** (in base.css — don't remove):127128```css129.slide { width: 1280px; height: 720px; page-break-after: always; overflow: hidden; }130@page { size: 1280px 720px; margin: 0; }131```132133**Key rules:**134- Use `px` units — never `vh/vw/rem/%` for slide dimensions135- Google Fonts: use `<link>` in `<head>`, export script waits for network idle136- Viewport meta: `<meta name="viewport" content="width=1280">`137- Content must fit within 720px height — overflow is clipped138139### 4. Preview (Optional)140141Use `preview(action='serve')` to preview in browser before exporting.142143### 5. Export to PDF144145```bash146python3 skills/slide-creator/scripts/export_pdf.py --dir <project-dir> --output output/<name>.pdf147```148149Options:150- `--dir` — directory containing `index.html` (required)151- `--output` / `-o` — output PDF path (default: `<dir>/deck.pdf`)152- `--width` — slide width in px (default: 1280)153- `--height` — slide height in px (default: 720)154155### 6. Verify156157The script prints slide count and confirms output path. Extra check:158159```python160import fitz161doc = fitz.open("output/deck.pdf")162print(f"Pages: {doc.page_count}")163for p in doc:164 r = p.rect165 print(f" {r.width*96/72:.0f}x{r.height*96/72:.0f}px")166```167168## Style Guidelines169170- **No default brand** — every deck gets a theme tailored to its content171- Prefer Art Direction-first workflow (questions → references → user pick → `style-brief.md`)172- Ask the user for preference: dark/light, accent color, font, mood173- Each slide should have clear visual hierarchy: tag → title → content174- Keep text concise — slides are visual, not documents175- Use `.bg-glow` with theme-colored radial gradients for depth176- Do not use `web_search` for style exploration by default; prioritize user-provided reference images/links plus templates in `art-direction.md`.177- When the user provides reference links, use `web_fetch` to extract design cues (color tone / voice / layout), but implement final CSS using local templates and token variables.178- When the user asks for "art-direction advice / style advice", always generate a visual style-picker preview page (3 options) — never rely on text-only descriptions.179- Build HTML strictly against chosen style brief, then export PDF (do not skip brief unless user explicitly opts out)180- After style is chosen, always ask about logo / brand assets before building181- For HK/TW/SG/bilingual audiences, default to bilingual layout unless user says English only182183## Style Microtweaks (after style is chosen)184185If user says "change primary color to red" / "switch the font" / "increase corner radius", do NOT restart art direction.186Instead, directly patch the `--accent` / `--font-head` / `--radius` CSS variable in `styles.css`.187Only restart art direction if user wants a completely different style.188189## Gotchas190191- **Chromium**: pre-installed via `workspace/setup.sh` on container start (~641 MB cached at `~/.cache/ms-playwright/`). Do NOT run `playwright install` on every export — it re-downloads the same browser. Only run it if `export_pdf.py` fails with `Executable doesn't exist`, and in that case also append the command to `workspace/setup.sh` so it persists.192- **Fonts**: Google Fonts need HTTP — the export script starts a local server automatically193- **Emoji rendering**: headless Chromium may lack emoji fonts — use SVG icons instead194- **Large images**: embed as base64 or use relative paths (local server serves the project dir)195- **Slide overflow**: content exceeding 720px height is clipped — design within bounds196- **⚠️ PDF text not selectable (verified 2026)**: `filter` / `backdrop-filter` CSS on any ancestor containing text causes Chromium to rasterize that layer to bitmap during PDF export — all child text becomes pixels, not selectable. Fix: NEVER apply `filter`/`backdrop-filter` to containers holding text. Only apply to empty decorative `<div>` elements (e.g. `.blur-layer`, `.glow-overlay`) with no text children. Same rule applies to `mix-blend-mode` on text parents. **Pre-export checklist**: search HTML for `filter`/`backdrop-filter` on non-decorative elements and strip them.197- **⚠️ Footer / source attribution — use standard component + strict bottom-safe-area contract (verified 2026)**: ad-hoc footer markup causes inconsistent positioning across slides. Always use this `.slide-footer` pattern for all source citations, page numbers, and disclaimers.198 199 **Hard layout contract (do not skip):**200 - Every non-cover slide must have a dedicated content wrapper (e.g. `.slide-body`) that reserves footer space.201 - **Hard rule:** `.slide-body` must reserve footer space with bottom-safe-area `>= 96px` (default 96px). Example: `.slide-body { padding: 52px 72px 96px; }`.202 - Footer must be outside normal flow: `position: absolute; bottom: 24px`, as a sibling of `.slide-body` directly under `.slide`.203 - Never place source/disclaimer text inside `.slide-body`.204 - Cover page can be exception only when it has no `.slide-footer`.205206 This enforces physical separation: body content area ends above a reserved footer lane, and footer stays in the canvas-bottom lane, so they never overlap regardless of content density.207 ```html208 <footer class="slide-footer">209 <span class="footer-source">Source: CoinGecko · Coinglass · DefiLlama</span>210 <span class="footer-page">03 / 12</span>211 </footer>212 ```213 ```css214 .slide-footer {215 position: absolute;216 bottom: 24px; left: 48px; right: 48px;217 display: flex; justify-content: space-between; align-items: center;218 font-size: 11px; color: rgba(255,255,255,0.35);219 border-top: 1px solid rgba(255,255,255,0.08);220 padding-top: 8px;221 z-index: 2;222 }223 .slide > *:not(.bg-glow):not(.slide-footer) {224 position: relative;225 z-index: 1;226 }227 .slide-body { padding-bottom: 96px; }228 ```229 Never use in-flow / `position: relative` footers — they shift when slide content height changes. Also exclude `.slide-footer` from generic `.slide > *` stacking rules, or CSS order can accidentally override footer layering.230 **Validation checklist (required before export):**231 1) every non-cover slide has `.slide-body` and `.slide-footer` as siblings;232 2) `.slide-body` bottom padding is `>=96px`;233 3) source/disclaimer text appears only inside `.slide-footer`, never in body containers.234- **⚠️ z-index / decorative overlay bug (verified 2026)**: `.bg-glow` and other decorative pseudo-layers MUST be positioned with `z-index: 0` and all real slide content given `z-index: 1` explicitly. If `.bg-glow` is a sibling of `.slide > *` (not a `::before`/`::after` pseudo-element), add this rule to ensure content is never visually buried:235 ```css236 .slide > *:not(.bg-glow) { position: relative; z-index: 1; }237 .bg-glow { position: absolute; z-index: 0; pointer-events: none; }238 ```239 Failure mode: PDF exports show content pushed to the bottom or invisible, even though browser preview looks fine (browser compositing handles z-order more forgivingly than Chromium's print path).