Static Site Generators

51 readers
1 users here now

This is a community to share ideas, ask questions and troubleshoot static site generators.

Popular SSGs

More info about SSGs on Jamstack.


If you run your website on an SSG then join the Static Quest web ring!

founded 5 months ago
MODERATORS
1
 
 

Here is how one could do a blogroll in Hugo:

We need a template dedicated to this particular blogroll page in layouts/blogroll.html

{{- define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content -}}

  {{- with hugo.Data.blogroll }}
    <ul>
      {{- range sort . "blog" -}}
        <li>
          <a href="{{ .url }}" rel="external" class="wt-500">{{ .blog }}</a>
          {{ with .rss }}
            <a href="{{ . }}" class="fgshade3">[RSS]</a>
          {{ end }}
          {{ with .atom }}
            <a href="{{ . }}" class="fgshade3">[Atom]</a>
          {{- end -}}
        </li>
      {{- end }}
    </ul>
  {{- end }}
{{- end }}

And then set the layout in the corresponding page frontmatter:

+++
title = "Blogroll"
description = "The awesome blogs I read"
date = "2025-04-04T00:00:00-03:00"
layout = "blogroll"
+++

Blogs I follow that one may want to visit.

And finally place the data file in data/blogroll.json:

[
  {
    "blog": "Example One",
    "url": "https://example1.com/",
    "rss": "https://example1.com/index.xml"
  },
  {
    "blog": "Example Two",
    "url": "https://example2.com/",
    "rss": "https://example2.com/index.xml",
    "atom": "https://example2.com/atom.xml"
  },
  {
    "blog": "Example Three",
    "url": "https://example3.com/",
    "rss": "https://example3.com/index.xml"
  }
]

To make a blogroll template in Zine we define a template for the specific page in layouts/blogroll.shtml:

<extend template="footer.shtml">
<head id="head"></head>
<header id="header"></header>
<main id="main">
	<h1 :text="$page.title"></h1>
	<ctx :html="$page.content()"></ctx>
	<ul :loop="$page.asset('blogroll.json').ziggy()">
		<li>
			<a
				class="wt-500"
				href="$loop.it.get('url')"
				:text="$loop.it.get('blog')">
			</a>
			<ctx :if="$loop.it.has('rss')">
				<a class="fgshade3" href="$loop.it.get('rss')">[rss]</a>
			</ctx>
			<ctx :if="$loop.it.has('atom')">
				<a class="fgshade3" href="$loop.it.get('atom')">[atom]</a>
			</ctx>
		</li>
	</ul>
</main>
<footer id="footer"></footer>

This template chains through other common repeated elements footer -> header -> head(More on that on another post). Unfortunately I still haven't figured out how to sort the list.

And then set the layout in the corresponding's page (content/blogroll/index.smd frontmatter:

***
.title = "Blogroll",
.date = @date("2026-06-10T22:11:54-04:00"),
.author = "Alec Sargent",
.layout = "blogroll.shtml",
.tags = ["web", "blogroll"],
***

These are blog I actually read and I'm subscribed to.

We use the same data file from the previous Hugo example and place it in content/blogroll/blogroll.json

Optionally one could use $site.asset in favour of $page.asset and place the file in the assets directory.

Other formats like YAML and TOML may be used in Hugo as long as they have the same structure.


That is all, cheers.

2
 
 

Long time ago I made this partial so that I can list the note pages of my blog in a tidy manner. I though it might be useful for someone. This partial walks through every children page and renders them in nested unordered lists.

recursive-page-list.html

{{- /* Get Arguments */}}
{{- $ctx := . }}
{{- $fold := false }}
{{- $open := false }}
{{- $sectionsFirst := false }}
{{- $singleLevelOpen := false }}
{{- $opts := dict }}
{{- $anchor := "§" }}

{{- if reflect.IsMap . }}
  {{- $opts = . }}
  {{- $ctx = .page }}
  {{- $open = .open }}
  {{- $fold = .fold }}
  {{- $sectionsFirst = .sectionsFirst }}
  {{- $singleLevelOpen = .singleLevelOpen }}

  {{- if or (isset $opts "singleLevelOpen") (isset $opts "open") }}
     {{ $fold = true }}
  {{- end }}
{{- end -}}

{{- $detailsAttrs := "" }}
{{- if $singleLevelOpen }}
  {{- $detailsAttrs = add $detailsAttrs " " (anchorize $ctx.LinkTitle) }}
{{- else if $open }}
  {{- $detailsAttrs = add $detailsAttrs " open" }}
{{- end }}

{{- $liClass := "yourClassesHere" }}

{{- /* Render */}}
<ul>
  {{- if and $fold $sectionsFirst }}
    {{- range $ctx.Sections }}
      <li class="{{ add $liClass " no_bullet_align" }}">
        <details{{ $detailsAttrs }}>
          <summary>
            {{ .LinkTitle }}
            <a href="{{ .RelPermalink }}">{{ $anchor }}</a>
          </summary>
            {{ partial "page-list-recursive" (merge $opts (dict "page" . )) }}
        </details>
      </li>
    {{- end }}

    {{- range $ctx.Pages -}}
      <li class="{{ $liClass }}">
        <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
      </li>
    {{- end }}

  {{- else if and $fold (not $sectionsFirst) }}
    {{- range $ctx.Pages.ByTitle }}
      {{- if .IsPage }}
        <li class="{{ $liClass }}">
          <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
        </li>
      {{- else }}
        <li class="{{ add $liClass " no_bullet_align"}}">
          <details{{ $detailsAttrs }}>
            <summary>
              {{ .LinkTitle }}
              <a href="{{ .RelPermalink }}">{{ $anchor }}</a>
            </summary>
            {{ partial "page-list-recursive" (merge $opts (dict "page" .)) }}
          </details>
        </li>
      {{- end }}
    {{- end }}

  {{- else if $sectionsFirst }}
    {{- range $ctx.Sections.ByTitle }}
      <li class="{{ $liClass }}">
        <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
        {{ partial "page-list-recursive" . }}
      </li>
    {{- end }}

    {{- range $ctx.Pages.ByTitle }}
      <li class="{{ $liClass }}">
        <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
      </li>
    {{- end }}

  {{- else }}
    {{- range $ctx.Pages.ByTitle }}
      <li class="{{ $liClass }}">
        <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
        {{- if .IsSection }}
          {{- partial "page-list-recursive" . -}}
        {{- end -}}
      </li>
    {{- end }}
  {{- end }}
</ul>

One can use it on any page template:

  {{ partial "page-list-recursive" . }}

And one can pass options:

  {{ partial "page-list-recursive" (dict
    "sectionsFirst" true
    "fold" true
    "page" .
    )
  }}

You will want to add this CSS rule to your stylesheet if your are going to use the folding option to make it look nice:

.no_bullet_align {
  list-style-type: none;
  margin-left: -0.9rem;
}

To add the left border when the details are open add this:

[open]::details-content {
  border-left: 1px dotted var(--fg);
  margin-left: 0.2rem;
  padding-left: 0.8rem;
}

I do not use Hugo anymore, but I share it anyway because when I needed a template like this I could not find any and it was a pain in the ass to make it on my own being a noob.

If you to test a live version then you could clone my old repo and then use hugo serve.

3
4
submitted 1 month ago* (last edited 1 month ago) by alecsargent@lemmy.zip to c/ssgs@lemmy.zip
 
 

I will be setting up the Zippy bot to fetch the latest updates on the most popular SSG's. You may request to add feeds of your favorite SSG's if they are not listed already. I will also post some tips on the SSG's I have tried out, and you may share yours.