summary refs log tree commit diff stats
path: root/src/themes/serene/USAGE.md
blob: 1b91d88539c1e814b41cce8cae9041b147d6011f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
This is the detailed guide on how to use zola-theme-serene. You should also check zola's [documentation](https://www.getzola.org/documentation/getting-started/overview/).

## Installation

Create a zola site and add serene theme (assuming your site is called `myblog`):

```sh
zola init myblog
cd myblog
git init
git submodule add -b latest https://github.com/isunjn/serene.git themes/serene
```

Copy the content of `myblog/themes/serene/config.example.toml` to `myblog/config.toml`.

## Sections and Pages

There is a `sections` config option in your `config.toml`, which enumerates the sections your site has. You should have at least one `blog` section.

The name and path can be changed, be noticed that if you changed the blog section path (e.g. from `/posts` to `/blog`), then you should also change `blog_section_path` option.

For home page, create `myblog/content/_index.md`:

```
+++
template = 'home.html'

[extra]
lang = 'en'

# Show footer in home page
footer = false

# If you don't want to display id/bio/avatar, simply comment out that line
name = "Serene Demo"
id = "serene"
bio = "programmer, he/him, we are young and life is fun"
avatar = "img/avatar.webp"
links = [
    { name = "GitHub", icon = "github", url = "https://github.com/<your-username>" },
    { name = "Twitter", icon = "twitter", url = "https://twitter.com/<your-username>" },
    { name = "Email", icon = "email", url = "mailto:<your-email-address>" },
]

# Show a few recent posts in home page
recent = false
recent_max = 15
recent_more_text = "more »"
date_format = "%b %-d, %Y"
+++

Hi, I'm ...
```

For blog section, create `myblog/content/posts/_index.md`:

```
+++
title = "My Blog"
description = "My blog site."
sort_by = "date"
template = "blog.html"
page_template = "post.html"
insert_anchor_links = "right"
generate_feeds = true

[extra]
lang = "en"

title = "Posts"
subtitle = "I write about ...."

date_format = "%b %-d, %Y"

categorized = false # posts can be categorized
back_to_top = true # show back-to-top button
toc = true # show table-of-contents
comment = false # enable comment
copy = true # show copy button in code block

outdate_alert = false
outdate_alert_days = 12
outdate_alert_text_before = "This article was last updated "
outdate_alert_text_after = " days ago and may be out of date."
+++
```

Blog section is defined by `blog.html` and `post.html`. Serene also has a special template called `prose.html`, it applies the same styles of blog post page. You can use it as a section template for a custom section page, for example if you want a separate `about` page, you can add a `{ name = "about", path = "/about", is_external = false }` to the `sections` and create a `myblog/content/about/_index.md`:

```
+++
title = "About me"
description = "About page of ..."
template = "prose.html"
insert_anchor_links = "none"

[extra]
lang = 'en'

title = "Posts"
subtitle = "I write about ...."

math = false
mermaid = false
copy = false
comment = false
reaction = false
+++

Hi, My name is ....
```

The default date format is "%b %-d, %Y", e.g. "Dec 13, 2025", check [this page](https://docs.rs/chrono/0.4.40/chrono/format/strftime/index.html) if you want to customize it, for example change to "%Y-%-m-%-d", e.g. "2025-2-13".

Now the myblog directory may looks like this:

```
├── config.toml
├── content/
│   ├── posts/
│   │   └── _index.md
│   ├── about/
│   │   └── _index.md
│   └── _index.md
├── sass/
├── static/
├── templates/
└── themes/
    └── serene/
```

## Favicon

Create a new directory `img` under `myblog/static`, put favicon related files here, you can use tools like [favicon.io](https://favicon.io/favicon-converter/) to generate those files. If you want to display avatar in home page, also put your avatar picture file `avatar.webp` here, webp format is recommended.

```
...
├── static/
│   └── img/
│       ├── favicon-16x16.png
│       ├── favicon-32x32.png
│       ├── apple-touch-icon.png
│       └── avatar.webp
...
```

## Icon

The default icons are placed in `myblog/themes/serene/static/icon`, the `icon` value in `links` of home section is the file name of the svg file.

To customize, find the svg file you want, modify (in case you don't kown, a svg file is just a plian text file) its width and height to `18`, and the color to `currentColor`:

`... width="18" height="18" ... fill="currentColor" ...`

and then put it in `myblog/static/icon`, file in this folder with the same name will override the default one.

The default icons mostly came from [Remix Icon](https://remixicon.com/).

## Theme

By default there is theme toggle button to switch between light and dark mode, you can set `force_theme` in `config.toml` to force a specific mode only.

## Code Highlighting

Copy `myblog/themes/serene/highlight_themes` directory to `myblog/highlight_themes`.

By default serene use different highlight themes for light/dark mode, configured by `highlight_theme`, `extra_syntaxes_and_themes` and `highlight_themes_css`. The default highlight theme `serene-light` `serene-dark` is a modified version of [Tomorrow](https://github.com/ChrisKempson/Tomorrow-Theme) theme.

If you set `highlight_theme` in `config.toml` to one of zola's [built-in highlight themes](https://www.getzola.org/documentation/getting-started/configuration/#syntax-highlighting), you will get that theme used in both light and dark mode.

If you want a different theme, find the `.tmTheme` TextMate file of your theme, put it in `myblog/static/highlight_themes`, and then modify the `theme` value of `highlight_themes_css` to that file's name. This will generate a `hl-light.css` and a `hl-dark.css` file in `myblog/static/`, you may have to delete them first before you change the `theme` value, so zola can re-generate. You can find some TextMate themes on [this website](https://tmtheme-editor.glitch.me/).

## RSS

Zola's default feed file is located in the root directory of the site, set `generate_feeds = true` in `config.toml`, `feed_filenames` can be set to `["atom.xml"]` or `["rss.xml"] ` , corresponding to two different rss file standards, you should also set `generate_feeds = false` in `myblog/content/posts/_index.md`

The serene theme looks more like a personal website, the posts are in the `/posts` directory, you may want the feed file to be in the `/posts` directory instead of the root directory, this requires you to set `generate_feeds = false ` `feed_filenames = ["feed.xml"]` in `config.toml`, and set `generate_feeds = true` in `myblog/content/posts/_index.md`.

`feed.xml` uses `title` and `description` from `myblog/content/posts/_index.md`, the other two use `config.toml`'s.

## Analytics

To add scripts for analytics tools (such as Google Analytics, Umami, etc.), you can create  `myblog/templates/_head_extend.html`. The content of this file will be added to the html head of each page.

## Custom CSS

Copy `myblog/themes/serene/templates/_custom_css.html` to `myblog/templates/_custom_css.html`, variables in this file are used to control styles, such as the theme color `--primary-color`, modify them as you want.

If you want to customize more, you need to copy that file under the `templates`, `static`, `sass` directory in the corresponding `themes/serene` to the same name directory of `myblog`, and modify it. Be careful not to directly modify the files under the serene directory, because these modifications may cause conflicts if the theme is updated.

If you want to use a custom font, create a new `myblog/templates/_custom_font.html` and put the font link tags (for eample, from [google fonts](https://fonts.google.com/)) into it, and then modify `--main-font` or `--code-font` in `myblog/sass/templates/_custom_css.html`. For performance reason, you may want to self-host font files, but it's optional:

1. Open [google-webfonts-helper](https://gwfh.mranftl.com) and choose your font.
2. Modify `Customize folder prefix` of step 3 to `/font/` and then copy the css.
3. Replace the content of `myblog/templates/_custom_font.html` with a `<style> </style>` tag, with the css you just copied.
4. Download step 4 font files and put them in `myblog/static/font/` folder.

## Front Matter

The content inside the two `+++` at the top of the post markdown file is called front matter, used to provide metadata and config options of that post. Supported options:

```md
+++
title = ""
description = ""
date = 2022-01-01
updated = 2025-01-01
draft = true

[taxonomies]
categories = ["one"]
tags = ["one", "two", "three"]

[extra]
lang = "en"
toc = true
comment = false
copy = true
outdate_alert = true
outdate_alert_days = 120
math = false
mermaid = false
featured = false
reaction = false
+++

new post about something...
```

Some of these options can also be configured in `myblog/content/posts/_index.md`, as the default value for all posts.

If you set `blog_categorized = true`, posts will be sorted alphabetically by default, you can manually set the order by adding a prefix  `__[0-9]{2}__` in front of the category name, for example, `categories = ["__01__CatXXX"]`

## Table of Contents

Set `toc = true` to display of table-of-contents.

## Math & Chart

Set `math = true` to enable formula rendering with KaTeX.

Set `mermaid = true` to enable chart rendering with Mermaid.

## Featured Mark

Set `featured = true` to display an asterisk(*) mark in front of the title.

## Outdate Alert

If one of your posts has strong timeliness, you can display an outdate alert after certain days.

Set `outdate_alert` and `outdate_alert_days` to enable the alert.

In `myblog/content/posts/_index.md`, options `outdate_alert_text_before` and `outdate_alert_text_after` are the text content of the alert.

## Comment

You can use [giscus](https://giscus.app) as the comment system.

To enable it, you need to create `myblog/templates/_giscus_script.html` and put the script configured on the giscus website into it, then change the value of `data-theme` to `https://<your-domain-name>/giscus_light.css`, replace `<your-domain-name>` with you domain name, same as `base_url` in `config.toml`, if you set `force_theme` to `dark`, replace `giscus_light.css` with `giscus_dark.css`.

Then set `comment = true` to enable comment.

## Reaction

This theme supports a feature called anonymous emoji reaction, visitors of you site can react to your post with emojis, without the need to log in or register.

You need to setup a backend api endpoint to enable it. Your endpoint should handle both `GET` and `POST` request:

- `GET`

    Request query:

     `slug`: the slug of the post

    Response:

    ```jsonc
    {
      "👍": [123, true], // emoji: [count, reacted]
      "👀": [456, false]
    }
    ```

- `POST`

    Request body:

    ```json
    {
      "slug": "post-slug",
      "target": "👍",
      "reacted": true
    }
    ```

    Response:

    ```json
    {
      "success": true
    }
    ```

For conivence, you can use one template repo to to setup your own endpoint:

-  [isunjn/reaction](https://github.com/isunjn/reaction): All you need is a [Cloudflare](https://cloudflare.com) account. The free tier is good enough for a low-traffic personal blog.

- [mildronize/reaction](https://github.com/mildronize/reaction): Specific to [Azure](https://azure.microsoft.com/) platform.
- [sorokya/reaction](https://github.com/sorokya/reaction): A self-contained one, you can run it with docker.

After you setup your endpoint, set `reaction_endpoint = "<your-endpoint>"` and `reaction = true` to enable it.

Giscus also support a reaction feature, but it requires visitors to log in to GitHub, you can disable it in giscus's settings.

## Codeblock

Zola supports some [annotations for code blocks](https://www.getzola.org/documentation/content/syntax-highlighting/#annotations).

## Shortcodes

[Shortcodes](https://www.getzola.org/documentation/content/shortcodes/) are some special templates.

- Use `figure` to add caption to the image:

  ```md
  {{ figure(src="/path/to/img", alt="alt text", caption="caption text") }}
  ```

  Adding attribution information to an image is very common, you can directly use the `via` attribute, which will display a link named 'via' below the image:

  ```md
  {{ figure(src="/path/to/img", alt="some alt text", via="https://example.com") }}
  ```

- Use `quote` to display a special quote block, `cite` is optional:

  ```md
  {% quote(cite="") %}
  // content...
  {% end %}
  ```

- Use `detail` to add an expandable detail block, `default_open` is optional:

  ```md
  {% detail(title="", default_open=false) %}
  // content...
  {% end %}
  ```

- As you can see in [this page](https://serene-demo.pages.dev/posts/callouts) of the demo site, callouts are special blockquote blocks, just like [github's](https://github.com/orgs/community/discussions/16925). There are currently 5 types: `note` `tip` `important` `warning`  `caution`.

   `title` is optional:

  ```md
  {% note(title="Note") %}
  note text
  {% end %}
  ```

- Use `mermaid` to add a mermaid chart:

  ```md
  {% mermaid() %}
  flowchart LR
  A[Hard] -->|Text| B(Round)
  B --> C{Decision}
  C -->|One| D[Result 1]
  C -->|Two| E[Result 2]
  {% end %}
  ```

## Collection

This theme has several special shortcodes for creating a collection of items. These collections can be used to showcase various types of your list, such as projects, publications, blogroll, bookmarks, etc. Check [this page](http://serene-demo.pages.dev/collections) on demo site to see some examples.

Currently, there are 7 types of collection item:

- `card`

    ```toml
    [[collection]]
    type = "card"
    title = "Title"
    subtitle = "Subtitle" # optional
    date = "Date" # optional
    link = "https://example.com" # optional
    icon = "https://example.com/image.png" # optional
    content = "Content"
    tags = ["tag1", "tag2"] # optional
    featured = false  # optional
    ```

- `card_simple`

    ```toml
    [[collection]]
    type = "card_simple"
    title = "Title"
    date = "Date" # optional
    link = "https://example.com" # optional
    icon = "https://example.com/image.png" # optional
    content = "Content"
    featured = false  # optional
    ```

- `entry`

    ```toml
    [[collection]]
    type = "entry"
    title = "Title" # optional
    subtitle = "Subtitle" # optional
    link = "https://example.com" # optional
    icon = "https://example.com/image.png" # optional
    ```

- `box`

    ```toml
    [[collection]]
    type = "box"
    title = "Title"
    subtitle = "Subtitle" # optional
    link = "https://example.com" # optional
    img = "https://example.com/image.png" # optional
    ```

- `art`

    ```toml
    [[collection]]
    type = "art"
    title = "Title"
    subtitle = "Subtitle" # optional
    link = "https://example.com" # optional
    img = "https://example.com/image.png"
    content = "Content" # optional
    footer = "Footer" # optional
    ```

- `art_simple`

    ```toml
    [[collection]]
    type = "art_simple"
    title = "Title"
    subtitle = "Subtitle" # optional
    link = "https://example.com" # optional
    img = "https://example.com/image.png"
    ```


List your items in a toml file and then use a `collection` shortcode to render them.

For example, to create a "projects" section page:

1. Create `myblog/content/projects/projects.toml`:

    ```toml
    [[collection]]
    type = "card"
    title = "Tokio"
    link = "https://example.com"
    content = "Tokio is an asynchronous runtime for the Rust programming language. It provides the building blocks needed for writing network applications. It gives the flexibility to target a wide range of systems, from large servers with dozens of cores to small embedded devices."
    tags = ["rust", "async", "runtime"]

    [[collection]]
    type = "card"
    title = "Kubernetes"
    link = "https://example.com"
    content = "Kubernetes, also known as K8s, is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for the deployment, maintenance, and scaling of applications."
    tags = ["k8s", "golang"]

    [[collection]]
    type = "card"
    title = "Next.js"
    link = "https://example.com"
    content = "Next.js is a React framework for building full-stack web applications. You use React Components to build user interfaces, and Next.js for additional features and optimizations."
    tags = ["typescript", "react", "frontend"]

    ```

2. Create `myblog/content/projects/_index.md`:

    ```
    +++
    title = "My projects"
    description = "Projects page of ..."
    template = "prose.html"

    [extra]
    title = "Projects"
    subtitle = "Some cool projects I made"
    +++

    {{ collection(file="projects.toml") }}
    ```

3. Add projects section in `sections` of `config.toml`

    ```toml
    sections = [
      # ...
      { name = "projects", path = "/projects", is_external = false },
    ]
    ```

## Build & Deploy

Local preview:

```sh
zola serve
```

Build the site:

```sh
zola build
```

To deploy a static site, refer to zola's [documentation about deployment](https://www.getzola.org/documentation/deployment/overview/).

## Update

Check the [CHANGELOG.md](https://github.com/isunjn/serene/blob/main/CHANGELOG.md) on github for breaking changes before you update.

If you copied some files from `myblog/themes/serene` to `myblog/` for customization, such as `_custom_css.html` or `main.scss`, then you should record what you have modified before you update, re-copy those files and re-apply your modification after updating. The `config.toml` should be re-copied too.

You can watch (`watch > custom > releases > apply`) this project on github to be reminded of a new release.

```sh
git submodule update --remote themes/serene
```