ZigCC Website Migration to Zine: A Practical Review

This article reviews the entire process of migrating the ZigCC community website from Hugo to Zine, aiming to share experiences and insights to provide reference for friends with similar needs.

ZigCC Website Migration to Zine: A Practical Review

1. Why Choose Zine?

We initially built the website using Hugo and its Docsy theme, but encountered some pain points during use, prompting us to seek new solutions. The decision to migrate to Zine was primarily based on the following considerations:

  1. Addressing Existing Issues with Hugo: Hugo is powerful, but there are issues in certain details, such as the parsing behavior of Markdown in the footer not meeting expectations.
  2. Pursuing Modern Design Aesthetics: The Docsy theme and some aspects of Hugo’s ecosystem appear somewhat outdated in terms of technology and aesthetics. We wanted a more modern and minimalist style for the website.
  3. More Refined Code Highlighting: Among mainstream highlighting libraries like <span>highlight.js</span>, <span>prism.js</span>, and <span>shiki.js</span>, <span>shiki.js</span> provides the best results. However, Zine offers more detailed syntax highlighting for Zig code than they do, providing stronger customization control (at the cost of Zine’s support for other languages being less complete, as it seems to rely on tree-sitter for implementation).
  4. Flexible Content Format Generation: Zine’s layout and Scripty API provide great flexibility in project structure, making it feasible to generate PDFs or other formats in the future, and the generation of RSS feeds also benefits from this.
  5. Significant Performance Improvement: After migration, both the backend build speed and frontend rendering performance have significantly improved. This is partly due to the simplified project structure brought by Zine’s architecture.

Of course, there is one crucial reason: Embracing and Contributing Back to the Zig Ecosystem. As ZigCC founder Liu Jiacai said:

“If we don’t use it ourselves, then others certainly won’t either.”

As a part of the Zig community, we have a responsibility to participate in ecosystem building. Indeed, this migration process also revealed some unresolved issues and potential improvements in Zine.

2. Understanding Zine’s Core Concepts

Zine is a modern, efficient static site generator. To understand it, one must first grasp its core design philosophy and file structure.

Project Structure and Configuration

A basic Zine project structure is similar to mainstream generators like Hugo, mainly consisting of content, layouts, and static resources directories:

.├── assets/      # Stores static resources like CSS and images├── content/     # Stores website content, usually .smd files│   ├── about.smd│   └── index.smd├── layouts/     # Stores layout templates, each .smd file corresponds to an .shtml layout│   ├── index.shtml│   ├── page.shtml│   └── templates/ # Templates can be inherited by other layouts for code reuse│       └── base.shtml└── zine.ziggy   # Global configuration file for the Zine project

The core of the project is the <span>zine.ziggy</span> configuration file, which defines the website’s metadata and directory paths. For example, ZigCC’s configuration is as follows:

Site {    .title = "Zig Language Chinese Community",    .host_url = "https://ziglang.cc",    .content_dir_path = "content",    .layouts_dir_path = "layouts",    .assets_dir_path = "assets",    .static_assets = [],}

Content Rendering: SuperMD, SuperHTML, and Scripty

Zine adopts a philosophy of content rendering that is starkly different from Hugo. It does not directly use standard Markdown and HTML, but introduces three core concepts:

  • SuperMD: An extended version of Markdown. It addresses the pain point of native Markdown’s difficulty in expressing complex structures (which require inline HTML), allowing developers to embed resources and define richer semantic structures.
  • SuperHTML: An extended version of HTML designed specifically for templates. Its design goal is to “fundamentally eliminate the generation of syntactically incorrect HTML,” catching many potential runtime errors at build time.
  • Scripty: A micro-expression language that drives the first two.

Essentially, SuperMD and SuperHTML are Markdown and HTML embedded with Scripty’s dynamic capabilities. Scripty’s syntax is concise and designed for string embedding, making it key to implementing dynamic content in Zine.

Scripty Quick Start

  • All expressions start with the ` symbol.
  • Supports chained field access: <span>$foo.bar.baz</span>
  • Supports function calls: <span>$foo.bar.qux('arg1', "arg2")</span>
  • Supports basic literals like strings, numbers, and booleans.

Here is a simple example demonstrating how Scripty works in SuperHTML and SuperMD:

SuperHTML Example:

&lt;ctx about="$site.page('about')"&gt;  &lt;a href="$ctx.about.link()" text="$ctx.about.title"&gt;&lt;/a&gt;&lt;/ctx&gt;

SuperMD Example:

Check out our [about page]($link.page('about' "about page")).

Scripty, as an expression language, showcases its power in conditions and nested logic:

&lt;h1 class="{$page.title.len().gt(25).then('long-title')}"&gt;...&lt;/h1&gt;

In the above code, if the page title length exceeds 25 characters, the <span><h1></span> tag will be assigned the class <span>long-title</span>.

Through the combination of these three, Zine provides high flexibility and security while ensuring separation of content and layout. For more detailed usage, it is recommended to read the official Zine documentation.

3. Detailed Migration Steps

The entire migration process can be divided into several key steps: content conversion, layout design, preview debugging, and final deployment.

Content Format Conversion

The core task of migration is to convert the existing content (mainly Markdown and Org Mode files in this article) into the SuperMarkdown (<span>.smd</span>) format supported by Zine.

Initially, I tried to have AI write a script to convert <span>md</span> to <span>smd</span>, which worked reasonably well. However, for the more complex Org Mode files, the script struggled, so I ultimately turned to using Pandoc.

Below is a Fish script for batch converting <span>.org</span> files to Markdown format (and renaming them to <span>.smd</span>), which also applies to <span>.md</span> files:

# Note: This actually converts to GitHub Flavored Markdown (gfm) format# Further manual adjustments are still needed to fully adapt to smd syntaxfor f in *.org  pandoc -s $f -t gfm -o (path change-extension "smd" $f)end

Key Points for Manual Adaptation:

After Pandoc completes the initial conversion, manual adjustments are still needed to adapt to the exclusive syntax of <span>.smd</span> and <span>.shtml</span>. Common differences include:

  1. HTML Embedding: <span>.smd</span> does not recommend directly embedding HTML. Related code needs to be wrapped in <span>```=html</span> code blocks.
  2. Section Title Links: Titles do not automatically generate IDs and anchor links, requiring manual addition using <span>$section.id("custom-id")</span> (note that IDs cannot contain spaces).
  3. Resource References: Resources can be referenced using the Scripty API or placed in the <span>public</span> directory and referenced via absolute paths (<span>/path/to/resource</span>).

It is recommended to complete the layout file writing first, and then perform these detailed manual adaptations in a live preview environment for higher efficiency.

Handling Frontmatter

Zine uses Ziggy syntax as the format for Frontmatter, which is highly similar to Zig syntax.

The Ziggy official website[4] provides a convenient online converter[5] that can convert Frontmatter in YAML, TOML, or JSON format to Ziggy.

A typical <span>.smd</span> file Frontmatter looks like this:

---    .title = "Zig comptime",    .date = @date("2025-01-23T12:00:00+08:00"),    .author = "xihale",    .layout = "post.shtml",    .draft = false,---

Designing Layouts

Since we wanted to adopt a brand new minimalist style, I did not use Docsy’s styles but instead redesigned a set of layouts. The current version is online, but there is still room for optimization in details like the table of contents (TOC).

Zine layouts have several key features:

  1. ID Slot: Zine uses an ID Slot[6] mechanism that is more flexible than traditional slots. For example, you can handle the <span><head></span> and content area slots separately, allowing for fine control over resource loading and other operations.
  2. <span><ctx></span> Tag: Proper use of the <span><ctx></span> tag can simplify the logic and organizational structure of templates.

Additionally, you can define a <span>.custom</span> field in the <span>.smd</span> Frontmatter to pass custom parameters to the layout for finer control.

For example, to enable math formula support in a <span>.smd</span> file:

// file: content/your-post.smd.custom = .{  .math = true,},

Then in the layout file, load the KaTeX library based on this flag:

// file: layouts/post.shtml&lt;ctx :if="$page.custom.getOr('math', false)"&gt;  &lt;link    href="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/KaTeX/0.15.2/katex.min.css"    crossorigin="anonymous"    rel="stylesheet"  /&gt;  &lt;script    defer    src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/KaTeX/0.15.2/katex.min.js"    crossorigin="anonymous"  &gt;&lt;/script&gt;  &lt;script    defer    src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/KaTeX/0.15.2/contrib/auto-render.min.js"    crossorigin="anonymous"    onload="renderMathInElement(document.body);"  &gt;&lt;/script&gt;&lt;/ctx&gt;

Preview and Debugging

After completing the layout and initial content conversion, we enter the most tedious phase: previewing, checking, and correcting.

Run the <span>zine</span> command to start a local server and preview the website in real-time. Check the rendering of each article one by one, identifying formatting errors or display anomalies, and return to the <span>.smd</span> files for modifications.

This step requires immense patience, almost equivalent to proofreading all articles again. It is important to note that Zine is still rapidly evolving, and some error messages for certain features may not be clear, requiring careful troubleshooting in conjunction with documentation and practice.

Deployment

The Zine official documentation provides detailed deployment guidelines:

  • Deploying to GitHub Pages[7]
  • Deploying to Cloudflare Pages[8]

You can refer to the GitHub Actions configuration in the zine-ssg or our site (ZigCC) repository to set up your own automated deployment process.

4. Summary and Experience Sharing

Finally, here are a few additional experiences to share:

  1. SuperHTML (<span>.shtml</span>) has strict requirements for HTML syntax; it is not just a superset of HTML. Some writing styles may conflict with personal habits, requiring adaptation to its specifications.
  2. The Scripty API uses a chain call syntax, which is very flexible.

When encountering problems during migration, do not panic. First, carefully check the error messages in the terminal, then consult the official documentation, and finally, you can refer to the source code of websites like zine-ssg and ziglang.org that also use Zine for building; they are the best learning examples.

References

[1]

SuperMD: https://zine-ssg.io/docs/supermd/

[2]

SuperHTML: https://zine-ssg.io/docs/superhtml

[3]

Scripty: https://zine-ssg.io/docs/scripty/

[4]

Ziggy Official Website: https://ziggy-lang.io/

[5]

Online Converter: https://ziggy-lang.io/documentation/ziggy-convert/

[6]

ID Slot: https://zine-ssg.io/docs/superhtml/#super

[7]

Deploying to GitHub Pages: https://zine-ssg.io/docs/deploying/github-pages/

[8]

Deploying to Cloudflare Pages: https://zine-ssg.io/docs/deploying/cloudflare-pages/

Leave a Comment