A few weeks ago I wrote about Pannonico, the static site generator I've been building in Go. At that point I mostly focused on its architecture and performance: Pannonico handles pages, templates and data, while Vite remains responsible for the frontend asset pipeline.
Pannonico 0.6.0 is now out, and since that first post the project has started to feel much more complete as a development environment, not just as a fast generator.
The largest change is probably the editor tooling.
Editor support beyond VS Code
The Pannonico language server has improved significantly. It now provides completion and hover information for partials, layouts, object keys, page names, translation fallback languages and date format tokens. Compiler diagnostics cover configuration, data, frontmatter and template syntax, including cases where a broken project cannot finish loading normally.
More importantly, the language server is no longer something you can use only through VS Code.
Pannonico now has editor integrations for:
All three use the same Pannonico language server, so project-aware completion and diagnostics aren't tied to one editor.
The completion data comes from the actual project. In this example, .page knows which values exist and where they originate.
The same applies to Pannonico's own runtime data, including Vite information, page metadata, translations and build properties.
The JetBrains plugin exposes the same functionality:
And the LSP can also be used from Neovim:
This is closer to what I wanted from the beginning. Syntax highlighting is useful, but I'd rather have tooling that actually understands the project I'm editing.
The language server also knows when something that looks like Pannonico syntax shouldn't be interpreted as such. Template examples inside CommonMark code blocks are ignored, for example, so documentation doesn't fill with false diagnostics.
Version 0.6 adds a related CLI feature called pannonico-verbatim. Content inside a verbatim wrapper stays outside template execution, Pannonico directives, HTML transforms and HTML validation, and is emitted literally. The compiler and the language server agree on those boundaries.
Performance after 0.6
I also reran the benchmark suite. These are complete clean production builds of 10,000 HTML pages on the same machine:
| Workload | Pannonico | Hugo | Eleventy | Astro | Nuxt Content |
|---|---|---|---|---|---|
| Raw | 4.80 s | 4.92 s | 7.71 s | N/A | N/A |
| Layout | 4.80 s | 5.21 s | 8.59 s | N/A | N/A |
| Layout + partials | 4.78 s | 5.15 s | 8.74 s | N/A | N/A |
| Layout + partials + data | 5.31 s | 5.23 s | 12.16 s | N/A | N/A |
| Realistic Vite build | 5.58 s | N/A | N/A | 104.85 s | 124.82 s |
The N/A entries are intentional. Hugo and Eleventy don't provide the equivalent Vite-oriented workflow, while Astro and Nuxt are measured in the realistic frontend-build scenario.
Pannonico and Hugo are close enough that I don't think declaring a benchmark winner is particularly useful. Pannonico was slightly faster in raw, layout and partial-heavy tests, while Hugo had a small advantage once structured data was added.
For me, reaching roughly Hugo-class native performance is already the interesting result.
There is another number in the benchmark that I find even more useful, though: startup time.
A native Pannonico build of a small 10-page project generally completes in about 22–33 ms. Comparable Hugo and Eleventy runs are generally around 190–225 ms.
For a single build, both are fast enough. During development, however, the generator isn't started once. Builds, tests, CI tasks, validation scripts and coding agents can invoke it repeatedly. Every invocation pays that fixed startup cost again.
That's why I've become increasingly interested in small-build latency rather than only in how many thousands of pages can be rendered per second. A command-line tool that starts almost immediately is easier to use as one small part of a larger development workflow.
Vite is still a separate tool
The other architectural decision that continues to work well is keeping Vite separate from Pannonico's rendering engine.
A realistic clean production build of 10,000 HTML pages with layouts, partials, data and Vite takes about 5.6 seconds. The Vite build itself contributes only around a quarter of a second in that workload.
Pannonico doesn't need to reimplement JavaScript, TypeScript, CSS, asset processing or the Vite plugin ecosystem. It generates the site, Vite builds the frontend resources, and the two meet through the generated manifest.
That also explains the large difference in the final benchmark row. Astro and Nuxt solve broader problems, so I wouldn't describe Pannonico as universally "20× faster". But for this particular kind of static-site workload, keeping content generation native and treating Vite as a separate build step has a very different performance profile.
Pannonico 0.6 also updates generated Vite projects to Vite 8.3.0 and is built with Go 1.27.1.
When I started the project I mostly wanted the simplicity of a small static generator combined with modern frontend tooling. The goal is becoming clearer with each release: keep the feedback loop short.
Fast builds are part of that, but so are fast startup, useful diagnostics, project-aware completion and editor support that isn't limited to a single IDE.
Dedicated site with tutorials and documentation is on its way, but until then only documentation is available here: https://github.com/vx-rs/pannonico/tree/master/docs
From start I wanted to make a tool similar to Zurb Panini, as I like that simple workflow where it's easy to start and see results straight away, but also to build something more complex later. Pannonico 0.6 is a fairly big step in that direction and I'm very satisfied how it's shaping up to be. Everything that I missed in Panini, that I used in my workflows throughout all these years, will eventually be here. :)





Top comments (0)