# Nicolino, a static site generator

**URL:** <https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557>\
**Category:** Community\
**Tags:** announces\
**Created:** [November 25, 2025, 1:19am UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557 "2025-11-25T01:19:49Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [November 25, 2025, 1:19am UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/1 "2025-11-25T01:19:49Z")

</div>

You can see it in action at [https://nicolino.ralsina.me](https://nicolino.ralsina.me) and of course [GitHub - ralsina/nicolino: A not-quite-minimalisting SSG written in Crystal](https://github.com/ralsina/nicolino)

Yes, there are hundreds of these, and yes, there is no reason to use this specific one. I have not even migrated _my_ site!

BUT:

- It’s a single static binary
- It’s pretty fast (within 10% of Hugo in markdown benchmarks)
- It has incremental builds, parallel builds, and so on (thanks to [GitHub - ralsina/croupier: A library to create and execute tasks with dependencies](https://github.com/ralsina/croupier))
- It has image gallery support which is probably the fastest you will ever find (thanks to libvips)
- And many other niceties.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [August 20, 2026, 4:24pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/3 "2026-08-20T16:24:28Z")

</div>

After a long time I have resumed work on Nicolino.

A lot of effort was spent on making it fast and correct, which then implied a lot of fixes in `ralsina/croupier` because this exercises it _a lot_.

How did it turn out?

- Nicolino’s site, including image galleries, thumbnails, mdbook-style books, blog posts about releases and so on, builds cold in under a second in my machine.
- Same site, if there are no changes, “builds” in about 0.2 seconds
- A 4000-post benchmark site builds in roughly 0.65 seconds (optimized binary) to 1.7 seconds (normal build)
- Hugo, the “standard” for fast static site generators, builds the same 4000-post site in 0.9 seconds, so Nicolino is about 30% faster ([see benchmarks](https://github.com/ralsina/nicolino/actions/runs/32385139886/job/96477679465)

I am specially happy with the mdbook-like implementation, which you can see in the [User Guide](https://nicolino.ralsina.me/books/user-guide/) and the `import` command that lets you integrate 3rd-party feeds into your own site (in this case, it pulls GH releases feed into the main site [here](https://nicolino.ralsina.me/posts/))

I think it’s basically in good shape and more or less feature complete :-)

---

<div class="post-metadata">

**Author:** ![michaels](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@michaels](https://forum.crystal-lang.org/u/michaels)\
**Post date:** [August 21, 2026, 10:52pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/4 "2026-08-21T22:52:08Z")

</div>

This looks great - and I’m keen to try it as it seems perfect for my use case. I believe the release is for linux, and I’m on Mac, so I’ve just cloned down the project and done a `shards build` and found at the last build step, I see the following error:

Error target nicolino failed to compile:  
Showing last frame. Use --error-trace for full trace.

In src/commands/auto.cr:60:19

60 | watcher = Inotify::Watcher.new(recursive: true)  
^---------------  
Error: undefined constant Inotify::Watcher

--

edit: I’ve found a fix, and made a pull request.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [August 22, 2026, 9:21am UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/5 "2026-08-22T09:21:48Z")

</div>

Hey, nice to hear!

Thanks for the bug reports, I am getting to them soonish :-)

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [August 29, 2026, 8:45pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/6 "2026-08-29T20:45:51Z")

</div>

After 14 years [my site](https://ralsina.me) is now migrated from [Nikola](https://getnikola.com) to [Nicolino](https://nicolino.ralsina.me)

For context, it’s over 26 years, thousands of images and posts, and _stuff_.

Nicolino builds it from scratch in about 25 seconds :-)

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [September 29, 2026, 8:30am UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/7 "2026-09-29T08:30:52Z")

</div>

I’m trying out Nicolino to create a site deployed to GitHub Pages using GitHub Actions. Of course, I could use Jekyll, but I’d prefer to use tools made with Crystal if possible.

```yml
name: guide

on:
  push:
    branches: [main]
    paths:
      - "guide/**"
      - ".github/workflows/guide.yml"
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - name: Configure GitHub Pages
        uses: actions/configure-pages@v5

      - name: Install Nicolino
        run: |
          wget https://github.com/ralsina/nicolino/releases/latest/download/nicolino-static-linux-amd64
          chmod +x nicolino-static-linux-amd64
          sudo mv nicolino-static-linux-amd64 /usr/local/bin/nicolino

      - name: Build manual
        working-directory: guide
        run: |
          nicolino theme install terminal
          nicolino build -B -p

      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v5
        with:
          path: guide/output

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v5

```

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 29, 2026, 1:51pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/8 "2026-09-29T13:51:59Z")

</div>

Neat! Would it be helpful if I hosted a reusable action for this?

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [September 29, 2026, 2:02pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/9 "2026-09-29T14:02:53Z")

</div>

No, I don’t think that’s necessary because this workflow is simple enough.  
Instead, I’d prefer it if you could expand the sample pages for each theme. For example, it would be great if we could see at a glance how the “gallery” and “books” look in each theme.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 29, 2026, 2:37pm UTC](https://forum.crystal-lang.org/t/nicolino-a-static-site-generator/8557/10 "2026-09-29T14:37:36Z")

</div>

Cool
