* added tutorials page and blog tutorial * proof reading, some language improvements * split blog tutorial into parts and reworked on the basis of comments, improved language, added missing things * + custom slugify function example * +blog tutorial on engagement * + section blog ToC * + instructions for X/FB share buttons and started discussion system * fix: module name `code` shadowed Python standard library module * added What's next section * +blog tutorial engagement part * fix: updated Giscus code snippet * trying multiple tutorials with headings for each group * + basic social cards tutorial * + custom social card tutorial * + estimated time for custom card tutorial * added tutorial sections to nav * fixed typos, removed sponsor icon from level one heading * removed "tutorial" from level one heading * added headings to custom layout example * fixed broken link * fixes after run-through, added links to template repos * added comment for @squidfunk * clarified use of logos, some proof-reading * removed question I left for @squidfunk * clarified relationship between background color and image * added override for the background image * fixed wording and indentation * changed example to be releases, not events * being more specific where to add the last bit of code in the layout --------- Co-authored-by: squidfunk <martin.donath@squidfunk.com>
12 KiB
Basic blogs
Blogs are a great way to engage with your audience. Software developers can use a blog to announce new features, demonstrate their usage and provide background information. You can demonstrate competence by commenting on the state of the art or document your own work as best practice. Posts on current topics can help draw in visitors for your main website and can keep your audience engaged. Of course, you can blog about any topics close to your heart.
The blog plugin makes running a blog alongside your other content easy but you can also configure it to run a stand-alone blog if posts are the only kind of content you need.
After a brief overview of the basic concepts of a blog, this tutorial guides you through the process of configuring the blog plugin, setting up your blog, creating posts, and defining post metadata.
Time required: typically 20 minutes
Key concepts
Post, excerpt: a blog consists of a number of self-contained posts (often called articles) and an index page that shows the posts in reverse chronological order, with the most recent post at the top. The index page usually shows only a short excerpt and a link that the user can click to navigate to the full post.
Metadata: both the index page and the post itself list information such as when you published the post, when you updated it, who the author is, and what the expected reading time is.
Slug: since the blog posts are primarily arranged by time and not into a hierarchy, their URLs do not reflect such a structure. Instead, each post's URL contains a shortened description, the slug, which is usually derived from the first heading in the post.
Navigation: the main navigation structure is the timeline, which you can subdivide into categories. The main index page shows the more recent posts while an archive section allows access to older ones, organized by year. In addition, posts can be tagged and tag index pages provide an additional navigation structure based on content.
You can see all these elements on the Material for MkDocs blog.
Setting up your blog
The blog plugin is part of Material for MkDocs but you need to configure it
in the mkdocs.yml
.
!!! example "Set up a blog"
If you have not done so already, create a project for your blog,
then edit the `mkdocs.yml` file to make sure if has the following content:
```yaml
site_name: Blog Tutorial
site_description: an example blog set up following the tutorial
site_url: http://www.example.com
theme:
name: material
plugins:
- search
- blog
```
The blog plugin will create a directory structure for your blog posts if it
does not exist, so simply run `mkdocs serve` to get:
```
docs
├── blog
│ ├── index.md
│ └── posts
└── index.md
```
Now create your first blog post in docs/blog/posts
. You can use any
naming convention and directory structure you like for your posts, as long as
they are inside docs/blog/posts
.
Each post must have a page header, which appears at the top of the Markdown
code between lines with three dashes. Within this header, you need to have at
least a date
entry but you can add other data, as you will see below.
Following the header comes the page content. Note that it is important
to have a level one heading as the plugin uses it to produce the slug. Also,
by adding <!-- more -->
to the page, you can define where the excerpt will end
that the index page shows.
!!! example "Write your first post"
Create a file `docs/blog/posts/myfirst.md` with the following contents:
```
---
date:
created: 2023-12-31
---
# Happy new years eve!
We hope you are all having fun and wish you all the best for the new year!
<!-- more -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
```
Then, run `mkdocs serve` and point your web browser at
`http://localhost:8000/blog`.
The blog plugin automatically creates navigation elements for
the blog. The index page shows only the extract. When you select the
"Continue reading" link, you will get to the full blog post. Note how it
has a URL generated from the first-level heading.
!!! tip "Navigation"
We also have a [tutorial on navigation] that shows you how to change the
automatically created navigation and integrate the blog into your existing
navigation structure. It shows how to create secondary nagigation, produce
author pages, and control pagination.
Post metadata
In addition to the date, you can provide other metadata and give the plugin instructions, such as to treat a post as a draft or to pin it.
Drafts
You may want to produce a draft of a blog post and work with it locally but exclude it from the build that you publish. Simply add a field to the page header to indicate that a post is still in draft form.
!!! example "Create a draft"
Create a second blog post in `docs/blogs/posts/draft.md` with the following
contents:
```hl_lines="3"
---
date:
created: 2024-01-01
draft: true
---
# Happy new year!
Happy 2024 to everyone. Wishing you all the best!
<!-- more -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
```
Now, note how the draft appears on the index page but with a label that
indicates that it is a draft. When you run `mkdocs build`, the draft will
_not_ appear in the output:
```
$ mkdocs build
$ ls site/blog
site/blog
├── 2023
│ └── 12
│ └── 31
│ └── happy-new-years-eve
│ └── index.html
...
```
The first blog post for 2024 is not there yet because it is still in draft
stage. Remember to remove the `draft` setting in the header when it is time
to publish it.
If you are using the Insiders Edition, you can also create
a folder to keep your drafts in and use the Meta plugin to add the
draft
header setting to all the posts in that folder. This has the advantage
that it is easier to see which posts are still in draft form. We will cover the
Meta plugin later on.
Edits
Sometimes, bloggers need to update a post. This might happen when you make
a mistake or when something changes that you need to reflect in the post. To
indicate you have edited a post, you can include an updated
date in the page
header.
!!! example "Editing a post"
Make a change to your first blog post, then add an edit date to the header:
```hl_lines="3 4"
---
date:
created: 2023-12-31
updated: 2024-01-02
---
```
The Metadata section of the blog post itself will contain the edit date, though the index page omits this detail by default.
Reading time
To give the reader some idea of how long it might take them to read a post, a read time is automatically calculated. If you want to override this, you can do so in the page header by specifying the number of minutes you estimate your readers will take the read the post.
!!! example "Overriding the reading time"
Add a reading time override to your first blog post:
```hl_lines="5"
---
date:
created: 2023-12-31
updated: 2024-01-02
readtime: 15
---
```
Pinning
Sometimes, blog authors want to 'pin' a specific post so that it will always
appear at the top of the index page, no matter what else gets published. If you
are using the Insiders Edition, you can achieve this by adding the pin
attribute in the page header:
!!! example "Pin a post "
Add the `pin` attribute to your first blog post:
```hl_lines="5"
---
date:
created: 2023-12-31
updated: 2024-01-02
readtime: 15
pin: true
---
```
Observe how this makes the post appear on top of the index page even though
its publication date is prior to other posts. A small pin icon shows that the
post has been pinned.
Related links
When your blog is part of a wider site such as technical documentation, you will want to provide links from blog posts into your other content. One way you can do this is to have a related links section. In the Insiders Edition, the blog plugin can create one for you if you provide link targets in your page header:
!!! example "Add a related links section "
Add the following to a blog post:
``` hl_lines="5-7"
---
date:
created: 2023-12-31
...
links:
- index.md
- blog/index.md
---
```
The related links appear underneath the Metadata section.
The nice thing here is that you do not need to provide a page title. The plugin
will deduce the link text by applying the same logic that MkDocs uses for the
main navigation. In fact, the syntax is the same as that of the nav
section
in the mkdocs.yml
, so you can override the title if you want and even define
subsections:
!!! example "Override the page titles"
Change the link section to override the page titles:
```hl_lines="6-9"
---
date:
created: 2023-12-31
...
links:
- Homepage: index.md
- Blog index: blog/index.md
- External links:
- Material documentation: https://squidfunk.github.io/mkdocs-material
---
```
The plugin renders related links in the left sidebar on screens that are wide enough and at the bottom of the post on narrow screens. Change the size of your browser window to see this in action.
Meta plugin
The Meta plugin is available in the Insiders Edition.
It helps simplify the management of metadata that is common to a group of
files in the same subdirectory. Instead of having to repeat the
same metadata in the page headers of a number of files, you can add a
.meta.yml
file in the directory and the Meta plugin will merge its contents
into the headers of all the pages contained.
Settings from the page header take precedence, so you can always override
settings by adding them to a post's header.
For example, you may want to manage drafts by keeping them in a directory together so that they are not only flagged as drafts but also easier to find. (Otherwise, you would need to inspect the page headers or trace back from the output to the files to figure out which posts are drafts.)
!!! example "Drafts using the Meta plugin "
You first need to activate the plugin in your `mkdocs.yaml`:
```yaml hl_lines="4"
plugins:
- search
- blog
- meta
```
Now create the folder for the drafts:
=== "MacOS/Linux"
```bash
$ mkdir docs/blog/posts/drafts
```
=== "Windows"
TODO
Now, within this folder, crate a file `.meta.yml` that contains:
```yaml
draft: true
```
Add another blog post and store it in `docs/blog/posts/drafts`. When you
look at it locally, you will see the label that identifies it as a draft,
while in the version built for publication it does not appear. To move a
post from draft status to published, simply move it outside `drafts/`.
What's next?
You should now have a working blog. However, as it accumulates content, you may want to make sure that people can find posts they are interested in, so you may want to add secondary navigation with tags and categories. You may have more than one author and want to attribute posts to them as well as generate author pages for them. We have a tutorial on navigation, pagination, and authors that covers these topics.
You may want to increase engagement with your blog by allowing people to subscribe to an RSS feed or by setting up a comment system. The engagement and dissemination tutorial walks you through setting these up.