Skip to content
⚠️ This document is AI-translated. The Chinese version is the authoritative source.

AI-Assisted Template Development

What This Tutorial Teaches

You'll use AI to develop a Presto template from scratch — turning Markdown into beautifully formatted PDFs. In the previous tutorial, you learned to write small Python programs with AI. This time, we'll use the same approach for something even more rewarding: developing a real, usable resume template.

  • Estimated time: 60-90 minutes
  • Final deliverable: A custom resume template that works with Presto
  • Prerequisites: Completed AI Programming Basics, Presto installed

Ready? Let's begin.


Part 1: Understanding What a Template Is (10 minutes)

Template = A "Skin" for Your PDF

When you write a Word document, content and formatting are mixed together — you have to adjust fonts, colors, and margins yourself, bit by bit. In Presto, content and formatting are separated:

  • You handle the content: Write text in Markdown (like writing plain text)
  • The template handles the formatting: Decides how big headings are, which fonts to use, how much spacing to add

In other words, a template is a "skin" for your PDF. The same resume content can look completely different just by switching templates.

For a detailed explanation, see Glossary - Template

Binary Template = A Small Program

A Presto template is not a style file (unlike Word's .dotx templates) — it's a compiled small program. It works in a straightforward way:

  1. Takes in Markdown (the content you wrote)
  2. Outputs Typst typesetting instructions (telling the typesetting engine how to render the PDF)

You don't need to understand the program's internals. Just know this: you give it content, and it gives you a beautifully formatted PDF.

For a detailed explanation, see Glossary - Binary Template

Side-by-Side Comparison

The same Markdown content produces completely different PDFs when different templates are used:

This is the power of templates — write your content once, switch "skins" anytime.


Part 2: Create the Project Skeleton (5 minutes)

We'll use Presto's official scaffolding tool to generate the project in one step. Open your terminal and type:

bash
npx create-presto-template

The scaffolding tool will ask you a few questions through an interactive wizard. Just follow along:

text
? Template name (kebab-case): my-first-template
? Display name: My First Template
? Description: A simple personal resume template
? Language: Go (recommended)
? Category: Resume
? GitHub username: your-username
? License: MIT

✓ Created my-first-template/

Your screen may look slightly different (the tool gets updated), but the questions are essentially the same. Enter your own GitHub username. If you don't have a GitHub account, any name will do — it won't affect local development.

Verify

bash
ls my-first-template/

You should see these files:

text
CLAUDE.md         Makefile          example.md
main.go           manifest.json     template_head.typ

See them? The project skeleton is ready.


Part 3: Understanding the Project Structure (10 minutes)

Enter the project directory:

bash
cd my-first-template

The scaffolding tool generated 6 files, each with a clear purpose. Let's do a quick overview — no need to memorize the details. You'll encounter them repeatedly when developing with AI.

FileOne-Line Description
main.goThe template's "brain" — reads Markdown, outputs Typst typesetting instructions
manifest.jsonThe template's "ID card" — name, version, required fonts, and other metadata
template_head.typLayout style definitions — page size, fonts, spacing, and other Typst settings
example.mdSample document — a Markdown file that demonstrates the template's output
MakefileBuild command collection — compile, test, and preview in one step
CLAUDE.mdAI development config — tells the AI assistant this project's rules and constraints

For detailed descriptions of each file, see Template Developer Guide. We're just doing an overview here.

What Is CLAUDE.md?

In the previous tutorial, you chatted directly with AI. But AI didn't know your project's rules (like "no third-party libraries" or "must use goldmark to parse Markdown"). CLAUDE.md solves this — it's a configuration file placed in the project root directory that the AI assistant reads automatically every time it starts.

Think of it as a "project briefing" for AI, so it knows which rules to follow from the very beginning.

Verify

First, confirm that the project compiles and tests pass:

bash
make build && make test

You should see a successful build and all tests passing. If you get an error, check whether Go is installed (go version).


Part 4: Develop the Template with AI (30-40 minutes)

Alright, here comes the main event. We're going to transform this default template into a personal resume template.

Target design:

  • A4 portrait, with appropriate margins on all sides
  • Name displayed at the top center (large, bold)
  • Contact information on one line below the name (email, phone)
  • Body divided into sections like "Education," "Projects," "Skills"
  • Clean and professional overall, suitable for job applications

We'll use AI to do all the coding. Enter the project directory and launch Claude Code:

bash
cd my-first-template
claude

Round 1: Describe Your Requirements

You:

I want to transform this template into a personal resume template. Requirements:

  1. A4 portrait page, 2cm top/bottom margins, 2.5cm left/right margins
  2. Name displayed centered at the top (large, bold, in a sans-serif font), with contact info centered on one line below
  3. Body text in a serif font, headings in a sans-serif font
  4. Supported sections: Education, Projects, Skills, Self-Assessment
  5. A thin separator line below each section heading
  6. Please update manifest.json, template_head.typ, example.md, and main.go

AI:

Sure, I'll transform the template into a personal resume template. I'll modify 4 files in order.

First, updating manifest.json:

json
{
  "name": "my-first-template",
  "displayName": "My First Template",
  "description": "A simple personal resume template",
  "version": "0.1.0",
  "author": "your-username",
  "license": "MIT",
  "category": "Resume",
  "keywords": ["resume", "CV", "job application"],
  "minPrestoVersion": "0.1.0",
  "requiredFonts": [],
  "frontmatterSchema": {
    "name": { "type": "string", "default": "Enter Your Name" },
    "email": { "type": "string", "default": "example@email.com" },
    "phone": { "type": "string", "default": "138-0000-0000" }
  }
}

Then updating template_head.typ with page and font styles:

typst
#set page(paper: "a4", margin: (top: 2cm, bottom: 2cm, left: 2.5cm, right: 2.5cm))
#set text(font: "SimSun", size: 11pt, lang: "zh")
#set par(leading: 0.8em)

#show heading.where(level: 1): it => {
  align(center, text(font: "SimHei", size: 22pt, weight: "bold")[#it.body])
}

#show heading.where(level: 2): it => {
  v(0.6em)
  text(font: "SimHei", size: 13pt)[#it.body]
  v(0.2em)
  line(length: 100%, stroke: 0.5pt + luma(180))
  v(0.3em)
}

Next, updating example.md with a sample resume:

markdown
---
name: Jane Doe
email: janedoe@example.com
phone: 138-0000-0000
---

## Education

**Some University** | Computer Science | 2022.09 - 2026.06

- GPA 3.8/4.0, top 10% in major
- Core courses: Data Structures, Operating Systems, Computer Networks

## Projects

**Campus Marketplace Platform** | Backend Developer | 2024.03 - 2024.06

- Built RESTful APIs using Go + Gin framework
- Implemented user authentication, product search, and order management
- Deployed on university server, 200+ daily active users

## Skills

- **Languages:** Go, Python, JavaScript
- **Tools & Frameworks:** Git, Docker, MySQL, Redis
- **English:** TOEFL 100

## Self-Assessment

Passionate about programming with a love for learning new technologies. Experienced in teamwork and comfortable working under project deadlines.

Finally, updating main.go. The key change is handling the name, email, and phone fields from frontmatter, rendering them as a centered header and contact line at the top:

go
// After outputting template_head.typ, first output the name and contact info
if name, ok := frontmatter["name"]; ok {
    fmt.Fprintf(out, "#heading(level: 1)[%s]\n", typst.EscapeContent(name))
}

contacts := []string{}
if email, ok := frontmatter["email"]; ok {
    contacts = append(contacts, email)
}
if phone, ok := frontmatter["phone"]; ok {
    contacts = append(contacts, phone)
}
if len(contacts) > 0 {
    fmt.Fprintf(out, "#align(center)[%s]\n", typst.EscapeContent(strings.Join(contacts, " | ")))
    fmt.Fprintln(out, "#v(0.5em)")
}

I've modified all 4 files. You can run make build && make test to verify.

This conversation demonstrates a typical AI development process: you describe requirements, and AI modifies all the relevant files. It didn't just change the code — it also updated the configuration, example, and styles. That's the efficiency of AI programming.

Warning: Common AI Mistakes:

AI might suggest installing additional packages (like go get some-markdown-parser). But Presto templates should only use the standard library + goldmark (a Go Markdown parsing library that the scaffolding tool already configured for you). If AI suggests installing extra dependencies, tell it:

"Please only use the standard library and goldmark. Don't introduce additional dependencies."

Why this restriction? Templates run in a sandbox. Extra dependencies not only increase size but can also introduce security risks. CLAUDE.md already states this rule, but AI occasionally overlooks it.

Round 2: Build, Test, and Fix

Now let's build and test:

bash
make build && make test

If everything goes smoothly, you'll see all tests passing. But reality often isn't that smooth — build errors on the first try are par for the course. Let's look at a common fix scenario:

You:

Running make build gave me an error:

text
./main.go:42:18: undefined: typst.EscapeContent

AI:

Sorry, it looks like the typst package path is wrong. Let me check the project structure.

Found it — in the starter project, the Typst escape function is in the internal/typst package. I need to fix the import path:

go
import (
    "my-first-template/internal/typst"
)

Fixed. Please run make build again.

You:

Build succeeded. But make test has one test failure:

text
FAIL: example round-trip - output contains invalid Typst

AI:

This error means the Typst code output by the template has syntax issues. Let me test with the example document to see what the output looks like:

bash
cat example.md | ./my-first-template

I see the problem — the heading output format is wrong; there's an extra layer of nesting. The #show heading.where(level: 1) in template_head.typ already handles the level-1 heading style, but the Typst code in main.go also manually sets centering, causing a conflict.

Fix: In main.go, don't use #heading(level: 1) for the name. Instead, use centered text directly:

go
if name, ok := frontmatter["name"]; ok {
    fmt.Fprintf(out, "#align(center, text(font: \"SimHei\", size: 22pt, weight: \"bold\")[%s])\n",
        typst.EscapeContent(name))
}

Also remove the #show heading.where(level: 1) rule from template_head.typ, since the resume doesn't need a level-1 heading style anymore.

Fixed. Try make test again.

This is the real AI development process — it's not about getting it right on the first try, but about the build - error - fix cycle. This is perfectly normal. Professional developers do the same thing every day. The key point: you don't need to understand every line of Go code yourself. You just need to show the error message to AI, and AI will analyze and fix it for you.

Warning: Common AI Mistakes:

AI might assume your computer has an amd64 architecture (Intel processor), but your Mac is arm64 (Apple Silicon). If AI gives you a build command containing GOARCH=amd64, that's wrong — change it to GOARCH=arm64.

A better approach: just use make build. The Makefile automatically detects your system architecture, so you don't need to specify it manually.

Round 3: Preview and Iterate

After tests pass, install the template to Presto and preview the result:

bash
make preview

This command compiles the template, installs it to Presto's template directory, then uses example.md to generate a PDF and open a preview.

See the PDF? But you might not be happy with some details. For example:

You:

The PDF looks mostly good. But a few issues:

  1. There's too much space between the name and contact info
  2. The separator lines under section headings like "Education" are too dark — can they be lighter?
  3. Can role info like "Backend Developer" in the projects section be shown in smaller gray text?

AI:

I'll address each of these three issues.

1. Reduce spacing between name and contact info

In main.go, change the #v(0.5em) after the name to #v(0.2em):

go
fmt.Fprintln(out, "#v(0.2em)")

2. Lighten the separator line color

In template_head.typ, change the separator line's luma(180) to luma(210) (higher values = lighter):

typst
line(length: 100%, stroke: 0.5pt + luma(210))

3. Show role info in smaller gray text

This requires modifying the Markdown-to-Typst conversion logic in main.go to recognize the |-separated format. When a bold text line is followed by |-separated content, render the parts after | in smaller gray text:

go
// Recognize "**Project Name** | Role | Date" format
// Output: #strong[Project Name] #h(0.5em) #text(fill: luma(120), size: 10pt)[Role | Date]

All changes made. Run make preview to see the result.

You:

Much better! One more tweak: can there be more spacing between sections like Projects and Education? It feels too cramped right now.

AI:

In template_head.typ, increase the spacing above level-2 headings by changing v(0.6em) to v(1.2em):

typst
#show heading.where(level: 2): it => {
  v(1.2em)
  text(font: "SimHei", size: 13pt)[#it.body]
  v(0.2em)
  line(length: 100%, stroke: 0.5pt + luma(210))
  v(0.3em)
}

Run make preview to see the result.

This "preview - feedback - tweak" cycle is the norm in template development. You don't need to know Typst syntax — just look at the PDF with your eyes and tell AI what's wrong with your keyboard.

Verify

Keep running make preview until you're satisfied. The final resume PDF should have:

  • [ ] Centered name at the top (large, bold)
  • [ ] Contact information below the name (email, phone)
  • [ ] Clear section separation (Education, Projects, Skills, Self-Assessment)
  • [ ] Light separator line under each section heading
  • [ ] Clean, professional overall layout

Part 5: Testing and Publishing (10 minutes)

Run the Full Test Suite

bash
make test

make test automatically checks the following:

  1. Whether manifest.json is valid JSON
  2. Whether example.md can be correctly converted by the template (round-trip test)
  3. Whether --version, --manifest, and --example parameters work correctly
  4. Whether the category field is valid
  5. Security checks (no banned packages, no network access, etc.)

Passing all tests means your template meets Presto's quality standards.

Multi-Platform Build (Optional)

If you want to share your template with others, you'll need to build for multiple platforms:

bash
make build-all    # Build for 6 platforms (darwin/linux/windows x arm64/amd64)

But for local development, you don't need this — make build builds for the current platform only.

Publish

When you're ready to share your template, you can publish it via GitHub Release. For the complete publishing workflow (including tagging, CI auto-build, etc.), see Release Process Guide.

Verify

bash
make test

All tests passing means you're good.


Part 6: Review What You Learned

Congratulations on developing your first Presto template! Let's review the key takeaways from this process.

1. CLAUDE.md Helps AI Understand Project Context

Did you notice that AI knew from the start that it should "only use the standard library and goldmark" and that "the output format is Typst"? That's because CLAUDE.md told it in advance. For any future project, you can write a CLAUDE.md to help AI better understand the context.

2. Incremental Development: Get It Working First, Then Refine

We didn't try to achieve perfect layout from the start. Instead, we first made the template compile, pass tests, and generate a basic PDF, then gradually refined the details. This "get it working first, then refine" approach is especially effective in AI-assisted development — because every step has a clear verification point.

3. AI Makes Mistakes, but You Can Identify and Correct Them

During development, we encountered at least two types of AI mistakes:

  • Suggesting unnecessary dependencies (should only use standard library + goldmark)
  • Assuming amd64 architecture (your Mac is arm64)

These mistakes aren't scary. What matters is that you know the project's rules and can correct AI when it makes mistakes. As you gain experience, you'll get better and better at spotting these issues.

4. Build - Error - Fix Is the Normal Workflow

Getting a successful build on the first try is the exception, not the rule. Copying error messages to AI and having it analyze and fix them is something professional developers do every day — it's not a sign of "incompetence."

To learn more about AI-assisted development patterns and techniques, read AI Workflow Patterns.


Next Steps

Congratulations on developing your first Presto template! Starting from an empty project, you used AI to complete requirements analysis, code modification, build debugging, and layout fine-tuning — this is the real template development workflow.

Want to go deeper? Here are some directions:

  • Deep dive into template development: Template Developer Guide contains full technical details, including the binary protocol, Typst syntax cheat sheet, pattern recipes, and more
  • Learn the publishing process: Release Process Guide teaches you how to share your template with others

You've mastered the basics of developing Presto templates with AI. Next, try using the same approach to develop a template you actually need — maybe for a lab report, course paper, or club event poster. Practice is the best way to learn.

Presto — Markdown to PDF