From 53647baed421f3efc446f57f7fbd6424d63319a7 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Fri, 5 Apr 2024 19:19:24 +0200 Subject: [PATCH 01/29] added tutorials page and blog tutorial --- docs/tutorials.md | 59 +++ docs/tutorials/blogs.md | 1087 +++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 3 files changed, 1147 insertions(+) create mode 100644 docs/tutorials.md create mode 100644 docs/tutorials/blogs.md diff --git a/docs/tutorials.md b/docs/tutorials.md new file mode 100644 index 00000000000..720b661fccb --- /dev/null +++ b/docs/tutorials.md @@ -0,0 +1,59 @@ +# Tutorials + +In addition to the basic getting started guides, we offer tutorials that aim to +show how Material for MkDocs can be used in different use cases. In contrast to +the getting started guides or the reference documentation, the tutorials show +the breadth of functionality available with Material for MkDocs but also within +the wider MkDocs ecosystem. + +* [Blogs](tutorials/blogs.md) + +## Tutorial Structure + +The tutorials guide you through worked examples, so following them you should +gain not only and understanding of how Material for MkDocs can be used but also +a template for your own projects. For convenience, these templates are also +available as [template repositories on GitHub]. + + +[template repositories on GitHub]: templates.md + +Each tutorial is a single page, so use the Table of Contents navigation to move +between numbered steps. They start by mentioning prerequisites and giving an +overview of the content as well as describing the outcomes. + +### Instructions + +Tutorials contain a mix of explanation, demonstrations, and instructions that you +should follow as you work your way through the individual steps. Those instructions +are shown in the form of admonitions to separate them from the rest of the +tutorial: + +!!! example "Instructions to follow" + + Whenever you see a box like this you know it is time to get hands on and + apply material just covered as well as reflect on how you would it in your + work work. + +### Tips and warnings + +Likewise, helpful tips and warnings appear in boxes of their own: + +!!! tip "A hot tip!" + + Tips look like this... + +!!! warning "Warning!" + + ...and warnings like this! + +## Feeback wanted + +The tutorials are a recent addition to our documentation and we are still +working out what shape they should have in the end. Please contact us if you +want to provide feedback. + +Note, however, that suggestions should be specific and feasible. We want to +focus on creating more content instead of developing a specific styling or +behaviour for the tutorials. If there are worthwhile improvements that can +be made through simple customization we are happy to consider those. diff --git a/docs/tutorials/blogs.md b/docs/tutorials/blogs.md new file mode 100644 index 00000000000..382d2f2f932 --- /dev/null +++ b/docs/tutorials/blogs.md @@ -0,0 +1,1087 @@ +# Blog tutorial + +## 1. Overview +__Content:__ The tutorial guides you through the process of configuring the +[blog plugin], creating posts, setting up authors, providing secondary navigation +with tags and producing an RSS feed. + +[blog plugin]: ../plugins/blog.md + +__Prerequisites:__ This tutorial assumes that you have installed either the +[public version] or the [Insiders edition] of Material for MkDocs and that you have +worked through the [Creating your site] setup guide. Note that where the features +we use the Insiders edition, we mark these with the heart icon: + If you are using the public version then you can skip these +steps. Sometimes there will be ways of achieving the same goal that differ +between the public version and the Insider edition. In that case, we will show +them in a tabbed view so you can see one or the other. + +[public version]: ../getting-started.md +[Insiders edition]: ../insiders/getting-started.md +[Creating your site]: ../creating-your-site.md + + +__Outcomes:__ After working through the tutorial, you will have learned how to +produce a professional or personal blog to engage with your audience. You will +know and have experienced how you can use the blog plugin in combination with +other features and third-party plugins to achieve this. + +__Time required:__ To run through this tutorial in full you will typically need +to have about XX minutes of time. Note that the time it takes depends on a +number of factors, so this is only a rough estimation based on our experience +and testing. + +## 2. Introduction + +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. It becomes even more powerful when used in combination with +other features of Material for MkDocs such as the [tags plugin] or with third +party plugins such as the [RSS plugin]. + +[tags plugin]: ../../plugins/tags +[RSS plugin]: https://guts.github.io/mkdocs-rss-plugin/ + +!!! example "Explore the Material for MkDocs Blog" + + Take a moment to look at the [Material for MkDocs blog] to see what elements + a blog consists of before moving on to the next section. What makes the blog + different from the rest of the site? + +[Material for MkDocs blog]: https://squidfunk.github.io/mkdocs-material/blog/ + +## 3. Key concepts + +A blog consists of a number of self-contained _posts_ (also often called +articles). + +An index page shows the posts in reverse chronological order, with the most +recent post at the top. It usually shows only a short _excerpt_ and a link that +the user can click to navigate to the full post. + +Both the index page and the post itself usually list information such as +when you published the post, when you updated it, who the author is and what the +expected reading time is. + +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 usually +contains a shortened description, the _slug_, which is usually derived from +the first heading in the post. + +The main navigation structure is the timeline, which you can subdivide into +_categories_. In addition, posts can be _tagged_ to provide an additional +navigation structure based on content. + +The navigation elements in the blog are the timeline, with the main index page +showing a given number of posts and an _archive_ section allowing access to +older posts, organized by year. The _categories_ section provides access to +index pages for the categories. In addition, when using tagging, you can also +create tag index pages. + +Navigation by _author_ helps users to find posts by a specific user when there +are more than one. Each author index page lists posts by that author in reverse +chronological order and can provide more information about them. + +Finally, an _RSS feed_ allows users to subscribe to a blog so that they get +notified when you publish new posts. RSS Feed readers are often used to access +blogs that a user follows. They usually support downloading the blog content for +offline consumption. + +## 4. 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: + + === "MacOS/Linux" + ```bash + $ mkdocs new myblog + $ cd myblog + ``` + + === "Windows" + TODO + + Then edit the `mkdocs.yml` file in the newly created directory 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 a MkDocs build: + +!!! example "Create directory structure" + + === "MacOS/Linux" + ```bash + $ mkdocs build + $ ls -R docs + blog index.md + + docs/blog: + index.md posts + + docs/blog/posts: + ``` + === "Windows" + TODO + +Now you can 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, however, that it is important +to have a level one heading as the plugin uses it to produce the _slug_. Also, +by adding `` 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: 2023-12-31 + --- + + # Happy new years eve! + + We hope you are all having fun and wish you all the best for the new year! + + + 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`. + + Observe how the blog plugin automatically creates navigation elements for + the blog. Later on we will see how this can be integrated into navigation + for a site that contains not just a blog. Note the other elements of a blog + are present and only an extract is shown. 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. + +## 5. Post metadata + +### 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. You can 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: + + ``` + --- + date: 2024-01-01 + draft: true + --- + + # Happy new year! + + Happy 2024 to everyone. Wishing you all the best! + + + 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: + + === "MacOS/Linux" + ``` + $ mkdocs build + $ ls site/blog + 2023 archive index.html + ``` + + === "Windows" + TODO + + 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. We will cover the +Meta plugin later on. + +[Meta plugin]: ../plugins/meta.md + +### Edits + +Sometimes, bloggers need to update a post. This might happen when they have made +a mistake or when something changes they need to reflect in the post. To +indicate you have edited a post, you can include an edit 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" + --- + date: 2023-12-31 + updated: 2024-01-02 + --- + ``` + +### Reading time + +To give the reader some idea of how long it might take them to read a post, +you can specify a reading time. Of course, reading times vary by individual as +well as by the subject matter and writing style. So, how do you set a reading +time for your content? Absent any other data, it seems sensible to start with +a reading speed used by big blogging platforms and adjust downward somewhat +if the content is fairly technical. [Medium use] a reading speed of 265 words +per minute. So, count the number of words in a post and divide by your reading +speed value to get the time, then round to the nearest minute. For content +in Chinese, Korean, and Japanese, use the value of 500 characters per minute +instead of words per minute. + +[Medium use]:https://help.medium.com/hc/en-us/articles/214991667-Read-time + +!!! example "Setting reading time" + + Add a reading time + + ``` + --- + date: 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: 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. + +### Custom slugs + +Another useful header attribute is `slug`, which allows you to define the slug +for your post instead of having it auto-generated by the Blog plugin from the +first heading. + +!!! example "Change slug" + + If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat + lengthy 'happy-new-years-eve', you could add the following: + + ```hl_lines="6" + --- + date: 2023-12-31 + updated: 2024-01-02 + readtime: 15 + pin: true + slug: ny-eve + --- + ``` + + The URL for this post should now be + `http://localhost:8000/blog/2023/01/31/ny-eve/`. + +### 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. The blog plugin creates 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="4-6" + --- + date: 2023-12-31 + ... + links: + - index.md + - tags.md + --- + ``` + +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="4-6" + --- + date: 2023-12-31 + ... + links: + - Homepage: index.md + - Explore tags: tags.md + - External links: + - Material documentation: https://squidfunk.github.io/mkdocs-material + --- + ``` + +As you can see, subsections are rendered in a way similar to mobile navigation +menus. + +## 6. Defining authors + +If your blog has more than one author then you may want to identify the author +for each blog post. The blog plugin allows you to create a file that contains +the author information and to then reference the authors of a particular post in +the page header. + +!!! example "Create author info" + + Create a file `docs/blog/.authors.yml` with this content: + + ```yaml + authors: + material: + name: Material Team + description: Creator + avatar: https://simpleicons.org/icons/materialformkdocs.svg + quidfunk: + name: Martin Donath + description: Creator + avatar: https://github.com/squidfunk.png + ``` + + and then add a line to the header of the first post: + + + ```hl_lines="4-5" + --- + date: 2023-12-31 + updated: 2024-01-02 + authors: + - material + --- + ``` + + Note that `authors` is a list, so you can specify multiple authors. + +With the Insiders edition, you can create custom author index pages that +can highlight the contributions of an author as well as provide additional +information about them. + +!!! example "Add author page " + + First, you need to enable author profiles in the `mkdocs.yml`: + + ```yaml hl_lines="4" + plugins: + - search + - blog: + authors_profiles: true + ``` + + Check your blog to see that there is now an extra entry in the main + navigation next to `archive` and `categories` that lists the authors and + their contributions. + + To customize the author page, you can create a page that overrides the one + generated by default. First, create the `author` directory that the profile + pages will live in: + + === "MacOS/Linux" + ``` + $ mkdir docs/blog/author + ``` + + === "Windows" + TODO + + Then create a page `docs/blog/author/material.md`: + + ``` + # The Material Team + + A small group of people dedicated to making writing documentation easy, if + not outright fun! Here are some of the things we have blogged about: + ``` + + As you can see, the author index gets appended to the content you have + written in the Markdown file. + +## 7. Integrating navigation + +So far, you have let the Blog plugin and MkDocs worry about navigation. For some +use cases, this might be enough and it is simply sufficient to not declare a +`nav` section in the `mkdocs.yml`. + +However, you may want to integrate a blog with other content and a navigation +structure that you have defined in the `nav` section of the configuration. +In such cases, you need to provide a place where the Blog plugin should +attach the blog navigation to the rest of the navigation structure. + +!!! example "Integrate with site navigation" + + Add the following to your `mkdocs.yml` to see how the Blog plugin can + integrate the blog navigation with the overall navigation structure. + Note that you do not need to add the individual blog posts to the navigation + structure, nor placeholders for index pages. The Blog plugin will take care + of that. + + ```yaml hl_lines="5" + nav: + - Home: index.md + - Install: install.md + - Usage: usage.md + - Blog: + - blog/index.md + ``` + + You will notice that "Blog" is duplicated in the navigation structure. To + avoid this, you can use the `navigation.indexes` feature: + + ```yaml hl_lines="3 4" + theme: + name: material + features: + - navigation.indexes + ``` + +!!! tip "Stand-alone blog" + + If what you need is a stand-alone blog instead of one that is integrated with + a larger site, this can be done by using the `blog_dir` configuration option. + To see how this is done, see [setting up a blog]. + The rest of the tutorial assumes that you are integrating the blog with + a wider site. + +[Setting up a blog]: ../setup/setting-up-a-blog.md#blog-only + +!!! tip "Adding pages" + + You can add pages to the blog section by putting them into `docs/blog` + and adding them to the navigation. The generated blog index pages + (archive and categories) will be added to the navigation after these + pages. We will see this below when we add a tag index. + + +## 8. Using categories + +Categories are a way to make blog posts accessible by topic while retaining +the navigation structure based on chronology within each category listing. +Use categories when there is a limited set of non-overlapping categories that +you can categorize your posts into. + +Categories appear in the main navigation, so are directly accessible from there. +This implies that there are relatively few categories as otherwise the +`categories` section in your main navigation will become too crowded. + + +!!! tip "Single or multiple categories?" + + While it is traditionally the case that a blog post would belong to only + one category, Material for MkDocs actually allows you to assign multiple + categories. While this gives you a degree of freedom, you should + probably not use this too much, not least because you can use tags to + deal with multiple classifications. We will cover them in the next step. + + +!!! example "Add a category" + + Add a category to your first blog post by adding it to the page header: + + ``` hl_lines="6 7"" + --- + date: 2023-12-31 + updated: 2024-01-02 + authors: + - material + categories: + - Holidays + --- + ``` + + Now that the blog post has been categorised, the `Holidays` category appears + under `Categories` in the main navigation and the blog post appears in the + index page for this category. + +Material allows you to control what categories can be used by declaring them in +the `mkdocs.yml`. This way you can make sure that authors stick to agreed +categories and that the plugin detects typos. + +!!! example "Control your categories" + + Add a `categories_allowed` entry to the configuration of the Blog plugin + with the entries "Holidays" and "News": + + ```yaml hl_lines="5-7" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + ``` + + Now, then you add a category to a blog post that does not match one of these + two, you should get a build error. + +## 8. Using tags + +The [Tags plugin] provides another way to classify blog posts and to make +them accessible independently of the main navigation structure. Tags are useful +for making related content easily discoverable even if it is in different parts +of the navigation hierarchy. + +[Tags plugin]: https://squidfunk.github.io/mkdocs-material/plugins/tags/ + +You may have a tutorial, like this one, showcasing features, a more +comprehensive setup guide, as well as reference documentation. Adding the same +tag to all three shows that they are related. As you will see, it is possible to +navigate from a tagged page to the tag index and, from there, to other +pages that carry the same tag. + +!!! example "Enable the plugin and add tags" + + First, you need to add the plugin to your `mkdocs.yml`: + + ```yaml hl_lines="8" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + - tags + ``` + + Once this is done, you can add tags to posts in the page header: + + ``` hl_lines="8-11"" + --- + date: 2023-12-31 + updated: 2024-01-02 + authors: + - material + categories: + - Holidays + tags: + - new year + - hogmanay + - festive season + --- + ``` + +You should see the tags that you defined at the top of the post. However, at the +moment that is it. While the blog plugin automatically creates an index page for +categories, the tags plugin does not do the same for tags. This is because the +tags plugin is not specific for blogs. You can use it for any site content, so +it is not obvious were the tag index should go. + +You can configure a basic tag index using the public version of Material for +MkDocs. The Insider Edition supports this as well, of course, but also provides +an alternative index mechanism that allows for an arbitrary number of tag +indexes, scoped listings, shadow tags, nested tags, and much more. + +!!! example "Adding a tags index" + === "Basic tag index" + + To configure a tag index using the public version, add a `tags_file` entry + to your configuration of the tags plugin and configure it in your `nav` + section. Remember to add a colon at the end of the existing `tags` entry. + + ```yaml hl_lines="8-9 17" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + - tags: + tags_file: blog/tags.md + + nav: + - Home: index.md + - Install: install.md + - Usage: usage.md + - Blog: + - blog/index.md + Tags: blog/tags.md + ``` + + The tag index will be appended to the configured page, which you should + now create at the location specified. + + Note that you can put the tag index page anywhere in your primary + navigation, so if you are using tags elsewhere instead of just in your + blog then you may want to have the tag index outside the blog section + of the navigation. + + + === "Insider Edition" + + To add a tag index, you add a placeholder in a Markdown file to tell + the plugin to insert an index at that point. This means that you + can add content before and after the index. Crucially, you can add + placeholders in multiple pages, each with a configuration of what + subset of tags should be displayed in the index. + + The simplest index page looks like this. Create it under `docs/tags.md`. + + ```markdown + # Tag index + + ``` + + Now, you may want to keep the tags for your blog separate from tags + you use in the rest of your page. You can achieve this by assigning + the tag index a scope. Put the following under `docs/blog/tags.md`: + + ```markdown + # Tag index for the blog + + ``` + + You now have two index pages. One that covers the whole site and one + that covers only the blog. + + The tags plugin in the Insider Edition is an incredibly powerful tool + and we can only scratch the surface of what is possible with it. If you + want to explore more after you have worked for this part of the tutorial, + have a look at the [tags plugin reference]. + +[tags plugin reference]: ../plugins/tags.md + +## 10. Pagination + +Once your blog starts growing, you may not want to pay attention to the number +of posts displayed per page. By default, the plugin displays up to 10 posts on +the archive and + + + + +## 11. Social Media + +The blog plugin works well with the social plugin, which creates social cards +for all pages, including blog posts. Social cards are images that other systems +such as social media can display as a preview for content linked to. +It is easy to get started with the social plugin, true to the motto of +Material with MkDocs: "batteries included." + +!!! example "Add social cards" + + To add social cards to your blog you need to install some dependencies. + These differ depending on what operating system you use. + + TODO: paste in installation instructions here - use snippets since this is + a lot of duplicated material? + + Once these prerequisites are fulfilled, you can simply add the social plugin + to your list of plugins: + + ```yaml hl_lines="10" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + - tags: + tags_file: blog/tags.md + - social + ``` + + Now, then you run `mkdocs build` and look at the `site` directory, you will + see that it contains subfolders under `assets/images/social` that reflect + the structure of your Markdown files. Each page has a corresponding PNG file + that contains the social card image. Of interest here are the social cards + for the blog posts, so have a look at them. + + TODO: posting them to social media - demo with Mastodon? + +Now, the social plugin provides a number of default layouts and configuration +options for changing aspects such as colors, images, fonts, logos, the title, +even the description. + + +!!! example "Changing background color" + + For example, to set the background color to an attention-grabbing hot pink, + you might add: + + ```yaml hl_lines="4 5" + plugins: + ... + - social: + cards_layout_options: + background_color: "#ff1493" + ``` + +!!! tip "Override card layout in page header " + + With the Insider Edition, you can customize the card layout for each + page by adding settings to the page header. So, you want only certain + cards to be in hot pink: + + ```yaml + --- + social: + cards_layout_options: + background_color: "#ff1493" + --- + ``` + +### Custom cards + +In the context of a blog, you may want to have more than just the blog post +title on the card. In the Insiders Edition, the social plugin allows you not +just to configure the existing layouts but also to develop your own from scratch +that contain the content that you need. + +!!! example "Custom layout for events " + + For example, you may want to include the date of an event on the social + card as well as a calendar icon to indicate that the card leads to an + event page when clicked on. + + First, copy the default social card layout from your installation of Material + for MkDocs to a new directory `layouts`. The instructions below assume you + are in your project root and have a virtual environment within this. The + path on your machine, of course may differ. + + ``` + $ mkdir layouts + $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default.yml \ + layouts/event.yml + ``` + + Have a look at the file contents. You will see that there are: + + * a number of definitions of content that is pulled from the site, + * definitions of tags that end up in the `meta` elements in the page header + of each page when it is generated, + * a specification that consists of a number of layers that are applied on + top of each other in the order in which they are defined. + + Before configuring the social cards, you need to tell the plugin where to + find them, so add the following to the plugin configuration in your + `mkdocs.yml`: + + ``` yaml hl_lines="2" + - social: + cards_layout_dir: layouts + ``` + + To include an event date and location, it makes sense to use information in + the header of a post, also specifying that the new event layout is to be + used. Create a new blog post: + + ```yaml + --- + date: 2024-04-03 + tags: + - events + social: + cards_layout: event + event: + date: 2024-04-08 + location: Online + --- + + # Introduction to Material for MkDocs + ``` + + Given this data, we can add some code to the layout that pulls it out and + makes it available to be rendered later on. Add the following at the top + of the layout file: + + ```yaml hl_lines="2-99" + definitions: + - &event >- + {%- if 'event' in page.meta %} + {%- if 'date' in page.meta['event'] %} + {{ "%s - " | format(page.meta['event']['date'].strftime('%d %B %Y')) }} + {%- else -%} + Date is undefined! + {%- endif -%} + {%- if 'location' in page.meta['event'] -%} + {{ page.meta['event']['location'] }} + {%- else -%} + Location is undefined! + {%- endif -%} + {%- else -%} + No event data defined! + {%- endif -%} + ``` + + Now, add a new layer to te ones already present that renders the date and + location: + + ```yaml + - size: { width: 990, height: 50 } + offset: { x: 50, y: 360 } + typography: + content: *event + align: start + color: *color + ``` + +!!! tip "Debugging layout files" + + Should you find that your layouts are causing your MkDocs build to fail, + there are a number of things you can do: + + 1. Run Mkdocs with the `--verbose` option to get more detailed reporting. + 2. Comment out things you recently added or that you suspect are the cause + 3. Install the `jinja2` command-line tool with `pip install Jinja2` and + run it over your layout file, for example: `jinja2 event.yml`. + +## 12. 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 that reside 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 contents will be merged into the +headers of all the pages contained. + +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.) + +!!! 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/`. + +Another example of the use of the Meta plugin is setting the metadata for the +social plugin. Imagine you have a custom layout for events and need to apply +this to specific blog posts. You can simply keep all posts that are event +announcements in a subdirectory `events` and add a `.meta.yml` that contains +the necessary metadata: + +!!! example "Creating event social cards with the Meta plugin " + + First, create the folder for the events: + + === "MacOS/Linux" + + ```bash + $ mkdir docs/blog/posts/events + ``` + + === "Windows" + + TODO + + Now, add a `.meta.yaml` file with content to configure the social cards + for these posts. You may also want to add the `event` tag while you are at + it: + + ```yaml + social: + cards_layout: event + tags: + - events + ``` + + Now, create a post in `docs/blog/posts/events` with the following header: + + ```yaml + ---- + date: 2024-04-03 + tags: + - material + - documentation + - made easy + event: + date: 2024-04-08 + location: Online + ---- + ``` + + Build and inspect the result. You should see that the correct social card + layout was used and that the `events` tag was added to the list of tags + defined in the post itself. + +While merging the data from the `.meta.yml` file, settings from the page header +take precedence, so you can always override settings by adding them to the +post itself. + +## 13. RSS Feeds + +Your readers can subscribe to a blog if you configure an RSS feed for it. An +easy way to do this is with the [MkDocs RSS Plugin], which is will integrated +with Material for MkDocs. Being a third-party plugin, it needs to be installed +before it can be used. + +[MkDocs RSS Plugin]: https://guts.github.io/mkdocs-rss-plugin + +!!! example "Add an RSS feed" + + Install the RSS plugin into your project: + + ``` + $ pip install mkdocs-rss-plugin + ``` + + It is important that have the `site_name`, `site_description` and + `site_url` settings configured as instructed in [4. Setting up your blog]. + The RSS plugin makes use of this information to construct the feed, so make + sure you have configured them: + + [4. Setting up your blog]: #4-setting-up-your-blog + + Now, configure it in the `mkdocs.yml` in the `plugins` section. + + ```yaml hl_lines="9" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + - tags + - rss + ``` + + Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS + feed in all its XML glory. You can use a browser like Firefox or Chrome. + + Unfortunately, Safari will always look for an app for RSS feeds and will not + display anything itself. Alternatively, you can use `curl` to get the feed + and `xmllint` to format it: + + ``` + curl -s http://localhost:8000/feed_rss_created.xml | xmllint --format - + ``` + + You way want to try your feed with a feed reader. There are various desktop + and mobile apps as well as online services. Of course, to use the latter you + will need to deploy your project somewhere that is accessible to them. + +This minimal configuration should work well if you have not made any changes +to the default configuration of the blog plugin. + +The table below summarizes how the plugin constructs information for the feed +itself and what configuration options you can use modify the defaults. Required +RSS element are marked with an asterisk. + +| RSS element | default | configure | +| ---------------- | -------------------------- | :-------: | +| `title`* | `site_name` | | +| `description`* | `site_description` | | +| `link`* | `site_url` | | +| `atom:link` | `site_url` + feed path | | +| `managingEditor` | `site_author` | | +| `copyright` | `copyright` | | +| `language` | `theme/language` | | +| `pubDate` | MkDocs build timestamp | | +| `lastBuildDate` | MkDocs build timestamp | | +| `ttl` | 1440 | | +| `generator` | MkDocs RSS plugin - v1.8.0 | NA | + +An RSS feed can have an image associated with it. The default image that the +RSS plugin uses is the site logo. You can use the `image` option if you want +a different image associated with the feed. + +??? tip "`pubDate` vs. `lastBuildDate`" + + The RSS standard specifies to dates that can describe a feed: `pubDate` and + `lastBuildDate`. The RSS standard does not define these well as the + definitions given are largely tautological. In his book [Developing Feeds + with RSS and Atom], Ben Hammersley gives a better explanation of the values + of these fields: + + `pubDate` is the publication date and can be in the future, while the + `lastBuildDate` states when the feed was last updated, so is always in the + past. Because these fields are not well defined, it is not certain what an + RSS reader will make of them. + +[Developing Feeds with RSS and Atom]: https://learning.oreilly.com/library/view/developing-feeds-with/0596008813/ + + +## 14. Add a discussion system \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 47a5d4dbc0e..12083063ed7 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -180,6 +180,7 @@ nav: - Getting started: - Installation: getting-started.md - Creating your site: creating-your-site.md + - Tutorials: tutorials.md - Publishing your site: publishing-your-site.md - Customization: customization.md - Conventions: conventions.md From 6f61627c8896f8b931f638b1db71be87480473c2 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Wed, 10 Apr 2024 10:39:14 +0200 Subject: [PATCH 02/29] proof reading, some language improvements --- docs/tutorials.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tutorials.md b/docs/tutorials.md index 720b661fccb..dd888e22444 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -1,17 +1,17 @@ # Tutorials In addition to the basic getting started guides, we offer tutorials that aim to -show how Material for MkDocs can be used in different use cases. In contrast to +show how you can use Material for MkDocs in different use cases. In contrast to the getting started guides or the reference documentation, the tutorials show -the breadth of functionality available with Material for MkDocs but also within +the breadth of features available in Material for MkDocs but also within the wider MkDocs ecosystem. * [Blogs](tutorials/blogs.md) -## Tutorial Structure +## Tutorial structure The tutorials guide you through worked examples, so following them you should -gain not only and understanding of how Material for MkDocs can be used but also +gain not only an understanding of how to use Material for MkDocs, but also a template for your own projects. For convenience, these templates are also available as [template repositories on GitHub]. @@ -19,14 +19,14 @@ available as [template repositories on GitHub]. [template repositories on GitHub]: templates.md Each tutorial is a single page, so use the Table of Contents navigation to move -between numbered steps. They start by mentioning prerequisites and giving an +between steps. They start by mentioning prerequisites, giving an overview of the content as well as describing the outcomes. ### Instructions Tutorials contain a mix of explanation, demonstrations, and instructions that you should follow as you work your way through the individual steps. Those instructions -are shown in the form of admonitions to separate them from the rest of the +come in the form of admonitions to separate them from the rest of the tutorial: !!! example "Instructions to follow" @@ -47,13 +47,13 @@ Likewise, helpful tips and warnings appear in boxes of their own: ...and warnings like this! -## Feeback wanted +## Feedback wanted The tutorials are a recent addition to our documentation and we are still working out what shape they should have in the end. Please contact us if you -want to provide feedback. +want to provide feedback. Note, however, that suggestions should be specific and feasible. We want to -focus on creating more content instead of developing a specific styling or -behaviour for the tutorials. If there are worthwhile improvements that can -be made through simple customization we are happy to consider those. +focus on creating more content at the moment, instead of developing a specific +styling or behaviour for the tutorials. If there are worthwhile improvements +that we can make through simple customization then we are happy to consider those. From ab01ac15eef26cb60be812bfd443626a92139279 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Wed, 17 Apr 2024 21:04:50 +0200 Subject: [PATCH 03/29] split blog tutorial into parts and reworked on the basis of comments, improved language, added missing things --- docs/tutorials/blogs.md | 1087 --------------------- docs/tutorials/blogs/basic.md | 379 +++++++ docs/tutorials/blogs/navigation.md | 434 ++++++++ docs/{tutorials.md => tutorials/index.md} | 33 +- mkdocs.yml | 6 +- 5 files changed, 843 insertions(+), 1096 deletions(-) delete mode 100644 docs/tutorials/blogs.md create mode 100644 docs/tutorials/blogs/basic.md create mode 100644 docs/tutorials/blogs/navigation.md rename docs/{tutorials.md => tutorials/index.md} (57%) diff --git a/docs/tutorials/blogs.md b/docs/tutorials/blogs.md deleted file mode 100644 index 382d2f2f932..00000000000 --- a/docs/tutorials/blogs.md +++ /dev/null @@ -1,1087 +0,0 @@ -# Blog tutorial - -## 1. Overview -__Content:__ The tutorial guides you through the process of configuring the -[blog plugin], creating posts, setting up authors, providing secondary navigation -with tags and producing an RSS feed. - -[blog plugin]: ../plugins/blog.md - -__Prerequisites:__ This tutorial assumes that you have installed either the -[public version] or the [Insiders edition] of Material for MkDocs and that you have -worked through the [Creating your site] setup guide. Note that where the features -we use the Insiders edition, we mark these with the heart icon: - If you are using the public version then you can skip these -steps. Sometimes there will be ways of achieving the same goal that differ -between the public version and the Insider edition. In that case, we will show -them in a tabbed view so you can see one or the other. - -[public version]: ../getting-started.md -[Insiders edition]: ../insiders/getting-started.md -[Creating your site]: ../creating-your-site.md - - -__Outcomes:__ After working through the tutorial, you will have learned how to -produce a professional or personal blog to engage with your audience. You will -know and have experienced how you can use the blog plugin in combination with -other features and third-party plugins to achieve this. - -__Time required:__ To run through this tutorial in full you will typically need -to have about XX minutes of time. Note that the time it takes depends on a -number of factors, so this is only a rough estimation based on our experience -and testing. - -## 2. Introduction - -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. It becomes even more powerful when used in combination with -other features of Material for MkDocs such as the [tags plugin] or with third -party plugins such as the [RSS plugin]. - -[tags plugin]: ../../plugins/tags -[RSS plugin]: https://guts.github.io/mkdocs-rss-plugin/ - -!!! example "Explore the Material for MkDocs Blog" - - Take a moment to look at the [Material for MkDocs blog] to see what elements - a blog consists of before moving on to the next section. What makes the blog - different from the rest of the site? - -[Material for MkDocs blog]: https://squidfunk.github.io/mkdocs-material/blog/ - -## 3. Key concepts - -A blog consists of a number of self-contained _posts_ (also often called -articles). - -An index page shows the posts in reverse chronological order, with the most -recent post at the top. It usually shows only a short _excerpt_ and a link that -the user can click to navigate to the full post. - -Both the index page and the post itself usually list information such as -when you published the post, when you updated it, who the author is and what the -expected reading time is. - -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 usually -contains a shortened description, the _slug_, which is usually derived from -the first heading in the post. - -The main navigation structure is the timeline, which you can subdivide into -_categories_. In addition, posts can be _tagged_ to provide an additional -navigation structure based on content. - -The navigation elements in the blog are the timeline, with the main index page -showing a given number of posts and an _archive_ section allowing access to -older posts, organized by year. The _categories_ section provides access to -index pages for the categories. In addition, when using tagging, you can also -create tag index pages. - -Navigation by _author_ helps users to find posts by a specific user when there -are more than one. Each author index page lists posts by that author in reverse -chronological order and can provide more information about them. - -Finally, an _RSS feed_ allows users to subscribe to a blog so that they get -notified when you publish new posts. RSS Feed readers are often used to access -blogs that a user follows. They usually support downloading the blog content for -offline consumption. - -## 4. 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: - - === "MacOS/Linux" - ```bash - $ mkdocs new myblog - $ cd myblog - ``` - - === "Windows" - TODO - - Then edit the `mkdocs.yml` file in the newly created directory 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 a MkDocs build: - -!!! example "Create directory structure" - - === "MacOS/Linux" - ```bash - $ mkdocs build - $ ls -R docs - blog index.md - - docs/blog: - index.md posts - - docs/blog/posts: - ``` - === "Windows" - TODO - -Now you can 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, however, that it is important -to have a level one heading as the plugin uses it to produce the _slug_. Also, -by adding `` 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: 2023-12-31 - --- - - # Happy new years eve! - - We hope you are all having fun and wish you all the best for the new year! - - - 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`. - - Observe how the blog plugin automatically creates navigation elements for - the blog. Later on we will see how this can be integrated into navigation - for a site that contains not just a blog. Note the other elements of a blog - are present and only an extract is shown. 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. - -## 5. Post metadata - -### 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. You can 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: - - ``` - --- - date: 2024-01-01 - draft: true - --- - - # Happy new year! - - Happy 2024 to everyone. Wishing you all the best! - - - 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: - - === "MacOS/Linux" - ``` - $ mkdocs build - $ ls site/blog - 2023 archive index.html - ``` - - === "Windows" - TODO - - 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. We will cover the -Meta plugin later on. - -[Meta plugin]: ../plugins/meta.md - -### Edits - -Sometimes, bloggers need to update a post. This might happen when they have made -a mistake or when something changes they need to reflect in the post. To -indicate you have edited a post, you can include an edit 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" - --- - date: 2023-12-31 - updated: 2024-01-02 - --- - ``` - -### Reading time - -To give the reader some idea of how long it might take them to read a post, -you can specify a reading time. Of course, reading times vary by individual as -well as by the subject matter and writing style. So, how do you set a reading -time for your content? Absent any other data, it seems sensible to start with -a reading speed used by big blogging platforms and adjust downward somewhat -if the content is fairly technical. [Medium use] a reading speed of 265 words -per minute. So, count the number of words in a post and divide by your reading -speed value to get the time, then round to the nearest minute. For content -in Chinese, Korean, and Japanese, use the value of 500 characters per minute -instead of words per minute. - -[Medium use]:https://help.medium.com/hc/en-us/articles/214991667-Read-time - -!!! example "Setting reading time" - - Add a reading time - - ``` - --- - date: 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: 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. - -### Custom slugs - -Another useful header attribute is `slug`, which allows you to define the slug -for your post instead of having it auto-generated by the Blog plugin from the -first heading. - -!!! example "Change slug" - - If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat - lengthy 'happy-new-years-eve', you could add the following: - - ```hl_lines="6" - --- - date: 2023-12-31 - updated: 2024-01-02 - readtime: 15 - pin: true - slug: ny-eve - --- - ``` - - The URL for this post should now be - `http://localhost:8000/blog/2023/01/31/ny-eve/`. - -### 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. The blog plugin creates 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="4-6" - --- - date: 2023-12-31 - ... - links: - - index.md - - tags.md - --- - ``` - -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="4-6" - --- - date: 2023-12-31 - ... - links: - - Homepage: index.md - - Explore tags: tags.md - - External links: - - Material documentation: https://squidfunk.github.io/mkdocs-material - --- - ``` - -As you can see, subsections are rendered in a way similar to mobile navigation -menus. - -## 6. Defining authors - -If your blog has more than one author then you may want to identify the author -for each blog post. The blog plugin allows you to create a file that contains -the author information and to then reference the authors of a particular post in -the page header. - -!!! example "Create author info" - - Create a file `docs/blog/.authors.yml` with this content: - - ```yaml - authors: - material: - name: Material Team - description: Creator - avatar: https://simpleicons.org/icons/materialformkdocs.svg - quidfunk: - name: Martin Donath - description: Creator - avatar: https://github.com/squidfunk.png - ``` - - and then add a line to the header of the first post: - - - ```hl_lines="4-5" - --- - date: 2023-12-31 - updated: 2024-01-02 - authors: - - material - --- - ``` - - Note that `authors` is a list, so you can specify multiple authors. - -With the Insiders edition, you can create custom author index pages that -can highlight the contributions of an author as well as provide additional -information about them. - -!!! example "Add author page " - - First, you need to enable author profiles in the `mkdocs.yml`: - - ```yaml hl_lines="4" - plugins: - - search - - blog: - authors_profiles: true - ``` - - Check your blog to see that there is now an extra entry in the main - navigation next to `archive` and `categories` that lists the authors and - their contributions. - - To customize the author page, you can create a page that overrides the one - generated by default. First, create the `author` directory that the profile - pages will live in: - - === "MacOS/Linux" - ``` - $ mkdir docs/blog/author - ``` - - === "Windows" - TODO - - Then create a page `docs/blog/author/material.md`: - - ``` - # The Material Team - - A small group of people dedicated to making writing documentation easy, if - not outright fun! Here are some of the things we have blogged about: - ``` - - As you can see, the author index gets appended to the content you have - written in the Markdown file. - -## 7. Integrating navigation - -So far, you have let the Blog plugin and MkDocs worry about navigation. For some -use cases, this might be enough and it is simply sufficient to not declare a -`nav` section in the `mkdocs.yml`. - -However, you may want to integrate a blog with other content and a navigation -structure that you have defined in the `nav` section of the configuration. -In such cases, you need to provide a place where the Blog plugin should -attach the blog navigation to the rest of the navigation structure. - -!!! example "Integrate with site navigation" - - Add the following to your `mkdocs.yml` to see how the Blog plugin can - integrate the blog navigation with the overall navigation structure. - Note that you do not need to add the individual blog posts to the navigation - structure, nor placeholders for index pages. The Blog plugin will take care - of that. - - ```yaml hl_lines="5" - nav: - - Home: index.md - - Install: install.md - - Usage: usage.md - - Blog: - - blog/index.md - ``` - - You will notice that "Blog" is duplicated in the navigation structure. To - avoid this, you can use the `navigation.indexes` feature: - - ```yaml hl_lines="3 4" - theme: - name: material - features: - - navigation.indexes - ``` - -!!! tip "Stand-alone blog" - - If what you need is a stand-alone blog instead of one that is integrated with - a larger site, this can be done by using the `blog_dir` configuration option. - To see how this is done, see [setting up a blog]. - The rest of the tutorial assumes that you are integrating the blog with - a wider site. - -[Setting up a blog]: ../setup/setting-up-a-blog.md#blog-only - -!!! tip "Adding pages" - - You can add pages to the blog section by putting them into `docs/blog` - and adding them to the navigation. The generated blog index pages - (archive and categories) will be added to the navigation after these - pages. We will see this below when we add a tag index. - - -## 8. Using categories - -Categories are a way to make blog posts accessible by topic while retaining -the navigation structure based on chronology within each category listing. -Use categories when there is a limited set of non-overlapping categories that -you can categorize your posts into. - -Categories appear in the main navigation, so are directly accessible from there. -This implies that there are relatively few categories as otherwise the -`categories` section in your main navigation will become too crowded. - - -!!! tip "Single or multiple categories?" - - While it is traditionally the case that a blog post would belong to only - one category, Material for MkDocs actually allows you to assign multiple - categories. While this gives you a degree of freedom, you should - probably not use this too much, not least because you can use tags to - deal with multiple classifications. We will cover them in the next step. - - -!!! example "Add a category" - - Add a category to your first blog post by adding it to the page header: - - ``` hl_lines="6 7"" - --- - date: 2023-12-31 - updated: 2024-01-02 - authors: - - material - categories: - - Holidays - --- - ``` - - Now that the blog post has been categorised, the `Holidays` category appears - under `Categories` in the main navigation and the blog post appears in the - index page for this category. - -Material allows you to control what categories can be used by declaring them in -the `mkdocs.yml`. This way you can make sure that authors stick to agreed -categories and that the plugin detects typos. - -!!! example "Control your categories" - - Add a `categories_allowed` entry to the configuration of the Blog plugin - with the entries "Holidays" and "News": - - ```yaml hl_lines="5-7" - plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - ``` - - Now, then you add a category to a blog post that does not match one of these - two, you should get a build error. - -## 8. Using tags - -The [Tags plugin] provides another way to classify blog posts and to make -them accessible independently of the main navigation structure. Tags are useful -for making related content easily discoverable even if it is in different parts -of the navigation hierarchy. - -[Tags plugin]: https://squidfunk.github.io/mkdocs-material/plugins/tags/ - -You may have a tutorial, like this one, showcasing features, a more -comprehensive setup guide, as well as reference documentation. Adding the same -tag to all three shows that they are related. As you will see, it is possible to -navigate from a tagged page to the tag index and, from there, to other -pages that carry the same tag. - -!!! example "Enable the plugin and add tags" - - First, you need to add the plugin to your `mkdocs.yml`: - - ```yaml hl_lines="8" - plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - - tags - ``` - - Once this is done, you can add tags to posts in the page header: - - ``` hl_lines="8-11"" - --- - date: 2023-12-31 - updated: 2024-01-02 - authors: - - material - categories: - - Holidays - tags: - - new year - - hogmanay - - festive season - --- - ``` - -You should see the tags that you defined at the top of the post. However, at the -moment that is it. While the blog plugin automatically creates an index page for -categories, the tags plugin does not do the same for tags. This is because the -tags plugin is not specific for blogs. You can use it for any site content, so -it is not obvious were the tag index should go. - -You can configure a basic tag index using the public version of Material for -MkDocs. The Insider Edition supports this as well, of course, but also provides -an alternative index mechanism that allows for an arbitrary number of tag -indexes, scoped listings, shadow tags, nested tags, and much more. - -!!! example "Adding a tags index" - === "Basic tag index" - - To configure a tag index using the public version, add a `tags_file` entry - to your configuration of the tags plugin and configure it in your `nav` - section. Remember to add a colon at the end of the existing `tags` entry. - - ```yaml hl_lines="8-9 17" - plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - - tags: - tags_file: blog/tags.md - - nav: - - Home: index.md - - Install: install.md - - Usage: usage.md - - Blog: - - blog/index.md - Tags: blog/tags.md - ``` - - The tag index will be appended to the configured page, which you should - now create at the location specified. - - Note that you can put the tag index page anywhere in your primary - navigation, so if you are using tags elsewhere instead of just in your - blog then you may want to have the tag index outside the blog section - of the navigation. - - - === "Insider Edition" - - To add a tag index, you add a placeholder in a Markdown file to tell - the plugin to insert an index at that point. This means that you - can add content before and after the index. Crucially, you can add - placeholders in multiple pages, each with a configuration of what - subset of tags should be displayed in the index. - - The simplest index page looks like this. Create it under `docs/tags.md`. - - ```markdown - # Tag index - - ``` - - Now, you may want to keep the tags for your blog separate from tags - you use in the rest of your page. You can achieve this by assigning - the tag index a scope. Put the following under `docs/blog/tags.md`: - - ```markdown - # Tag index for the blog - - ``` - - You now have two index pages. One that covers the whole site and one - that covers only the blog. - - The tags plugin in the Insider Edition is an incredibly powerful tool - and we can only scratch the surface of what is possible with it. If you - want to explore more after you have worked for this part of the tutorial, - have a look at the [tags plugin reference]. - -[tags plugin reference]: ../plugins/tags.md - -## 10. Pagination - -Once your blog starts growing, you may not want to pay attention to the number -of posts displayed per page. By default, the plugin displays up to 10 posts on -the archive and - - - - -## 11. Social Media - -The blog plugin works well with the social plugin, which creates social cards -for all pages, including blog posts. Social cards are images that other systems -such as social media can display as a preview for content linked to. -It is easy to get started with the social plugin, true to the motto of -Material with MkDocs: "batteries included." - -!!! example "Add social cards" - - To add social cards to your blog you need to install some dependencies. - These differ depending on what operating system you use. - - TODO: paste in installation instructions here - use snippets since this is - a lot of duplicated material? - - Once these prerequisites are fulfilled, you can simply add the social plugin - to your list of plugins: - - ```yaml hl_lines="10" - plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - - tags: - tags_file: blog/tags.md - - social - ``` - - Now, then you run `mkdocs build` and look at the `site` directory, you will - see that it contains subfolders under `assets/images/social` that reflect - the structure of your Markdown files. Each page has a corresponding PNG file - that contains the social card image. Of interest here are the social cards - for the blog posts, so have a look at them. - - TODO: posting them to social media - demo with Mastodon? - -Now, the social plugin provides a number of default layouts and configuration -options for changing aspects such as colors, images, fonts, logos, the title, -even the description. - - -!!! example "Changing background color" - - For example, to set the background color to an attention-grabbing hot pink, - you might add: - - ```yaml hl_lines="4 5" - plugins: - ... - - social: - cards_layout_options: - background_color: "#ff1493" - ``` - -!!! tip "Override card layout in page header " - - With the Insider Edition, you can customize the card layout for each - page by adding settings to the page header. So, you want only certain - cards to be in hot pink: - - ```yaml - --- - social: - cards_layout_options: - background_color: "#ff1493" - --- - ``` - -### Custom cards - -In the context of a blog, you may want to have more than just the blog post -title on the card. In the Insiders Edition, the social plugin allows you not -just to configure the existing layouts but also to develop your own from scratch -that contain the content that you need. - -!!! example "Custom layout for events " - - For example, you may want to include the date of an event on the social - card as well as a calendar icon to indicate that the card leads to an - event page when clicked on. - - First, copy the default social card layout from your installation of Material - for MkDocs to a new directory `layouts`. The instructions below assume you - are in your project root and have a virtual environment within this. The - path on your machine, of course may differ. - - ``` - $ mkdir layouts - $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default.yml \ - layouts/event.yml - ``` - - Have a look at the file contents. You will see that there are: - - * a number of definitions of content that is pulled from the site, - * definitions of tags that end up in the `meta` elements in the page header - of each page when it is generated, - * a specification that consists of a number of layers that are applied on - top of each other in the order in which they are defined. - - Before configuring the social cards, you need to tell the plugin where to - find them, so add the following to the plugin configuration in your - `mkdocs.yml`: - - ``` yaml hl_lines="2" - - social: - cards_layout_dir: layouts - ``` - - To include an event date and location, it makes sense to use information in - the header of a post, also specifying that the new event layout is to be - used. Create a new blog post: - - ```yaml - --- - date: 2024-04-03 - tags: - - events - social: - cards_layout: event - event: - date: 2024-04-08 - location: Online - --- - - # Introduction to Material for MkDocs - ``` - - Given this data, we can add some code to the layout that pulls it out and - makes it available to be rendered later on. Add the following at the top - of the layout file: - - ```yaml hl_lines="2-99" - definitions: - - &event >- - {%- if 'event' in page.meta %} - {%- if 'date' in page.meta['event'] %} - {{ "%s - " | format(page.meta['event']['date'].strftime('%d %B %Y')) }} - {%- else -%} - Date is undefined! - {%- endif -%} - {%- if 'location' in page.meta['event'] -%} - {{ page.meta['event']['location'] }} - {%- else -%} - Location is undefined! - {%- endif -%} - {%- else -%} - No event data defined! - {%- endif -%} - ``` - - Now, add a new layer to te ones already present that renders the date and - location: - - ```yaml - - size: { width: 990, height: 50 } - offset: { x: 50, y: 360 } - typography: - content: *event - align: start - color: *color - ``` - -!!! tip "Debugging layout files" - - Should you find that your layouts are causing your MkDocs build to fail, - there are a number of things you can do: - - 1. Run Mkdocs with the `--verbose` option to get more detailed reporting. - 2. Comment out things you recently added or that you suspect are the cause - 3. Install the `jinja2` command-line tool with `pip install Jinja2` and - run it over your layout file, for example: `jinja2 event.yml`. - -## 12. 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 that reside 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 contents will be merged into the -headers of all the pages contained. - -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.) - -!!! 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/`. - -Another example of the use of the Meta plugin is setting the metadata for the -social plugin. Imagine you have a custom layout for events and need to apply -this to specific blog posts. You can simply keep all posts that are event -announcements in a subdirectory `events` and add a `.meta.yml` that contains -the necessary metadata: - -!!! example "Creating event social cards with the Meta plugin " - - First, create the folder for the events: - - === "MacOS/Linux" - - ```bash - $ mkdir docs/blog/posts/events - ``` - - === "Windows" - - TODO - - Now, add a `.meta.yaml` file with content to configure the social cards - for these posts. You may also want to add the `event` tag while you are at - it: - - ```yaml - social: - cards_layout: event - tags: - - events - ``` - - Now, create a post in `docs/blog/posts/events` with the following header: - - ```yaml - ---- - date: 2024-04-03 - tags: - - material - - documentation - - made easy - event: - date: 2024-04-08 - location: Online - ---- - ``` - - Build and inspect the result. You should see that the correct social card - layout was used and that the `events` tag was added to the list of tags - defined in the post itself. - -While merging the data from the `.meta.yml` file, settings from the page header -take precedence, so you can always override settings by adding them to the -post itself. - -## 13. RSS Feeds - -Your readers can subscribe to a blog if you configure an RSS feed for it. An -easy way to do this is with the [MkDocs RSS Plugin], which is will integrated -with Material for MkDocs. Being a third-party plugin, it needs to be installed -before it can be used. - -[MkDocs RSS Plugin]: https://guts.github.io/mkdocs-rss-plugin - -!!! example "Add an RSS feed" - - Install the RSS plugin into your project: - - ``` - $ pip install mkdocs-rss-plugin - ``` - - It is important that have the `site_name`, `site_description` and - `site_url` settings configured as instructed in [4. Setting up your blog]. - The RSS plugin makes use of this information to construct the feed, so make - sure you have configured them: - - [4. Setting up your blog]: #4-setting-up-your-blog - - Now, configure it in the `mkdocs.yml` in the `plugins` section. - - ```yaml hl_lines="9" - plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - - tags - - rss - ``` - - Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS - feed in all its XML glory. You can use a browser like Firefox or Chrome. - - Unfortunately, Safari will always look for an app for RSS feeds and will not - display anything itself. Alternatively, you can use `curl` to get the feed - and `xmllint` to format it: - - ``` - curl -s http://localhost:8000/feed_rss_created.xml | xmllint --format - - ``` - - You way want to try your feed with a feed reader. There are various desktop - and mobile apps as well as online services. Of course, to use the latter you - will need to deploy your project somewhere that is accessible to them. - -This minimal configuration should work well if you have not made any changes -to the default configuration of the blog plugin. - -The table below summarizes how the plugin constructs information for the feed -itself and what configuration options you can use modify the defaults. Required -RSS element are marked with an asterisk. - -| RSS element | default | configure | -| ---------------- | -------------------------- | :-------: | -| `title`* | `site_name` | | -| `description`* | `site_description` | | -| `link`* | `site_url` | | -| `atom:link` | `site_url` + feed path | | -| `managingEditor` | `site_author` | | -| `copyright` | `copyright` | | -| `language` | `theme/language` | | -| `pubDate` | MkDocs build timestamp | | -| `lastBuildDate` | MkDocs build timestamp | | -| `ttl` | 1440 | | -| `generator` | MkDocs RSS plugin - v1.8.0 | NA | - -An RSS feed can have an image associated with it. The default image that the -RSS plugin uses is the site logo. You can use the `image` option if you want -a different image associated with the feed. - -??? tip "`pubDate` vs. `lastBuildDate`" - - The RSS standard specifies to dates that can describe a feed: `pubDate` and - `lastBuildDate`. The RSS standard does not define these well as the - definitions given are largely tautological. In his book [Developing Feeds - with RSS and Atom], Ben Hammersley gives a better explanation of the values - of these fields: - - `pubDate` is the publication date and can be in the future, while the - `lastBuildDate` states when the feed was last updated, so is always in the - past. Because these fields are not well defined, it is not certain what an - RSS reader will make of them. - -[Developing Feeds with RSS and Atom]: https://learning.oreilly.com/library/view/developing-feeds-with/0596008813/ - - -## 14. Add a discussion system \ No newline at end of file diff --git a/docs/tutorials/blogs/basic.md b/docs/tutorials/blogs/basic.md new file mode 100644 index 00000000000..ec039165eff --- /dev/null +++ b/docs/tutorials/blogs/basic.md @@ -0,0 +1,379 @@ +# Blog tutorial + +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. + +This tutorial guides you through the process of configuring the +[blog plugin], setting up your blog, creating posts, and defining +post metadata. + +[blog plugin]: ../../plugins/blog.md + +__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 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 a given number of posts +and an _archive_ section allows access to older posts, 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]. + +[Material for MkDocs blog]: https://squidfunk.github.io/mkdocs-material/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 `` 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: 2023-12-31 + --- + + # Happy new years eve! + + We hope you are all having fun and wish you all the best for the new year! + + + 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. + +[tutorial on navigation]: navigation.md + +## 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: 2024-01-01 + draft: true + --- + + # Happy new year! + + Happy 2024 to everyone. Wishing you all the best! + + + 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. + +[Meta plugin]: ../../plugins/meta.md + +### Edits + +Sometimes, bloggers need to update a post. This might happen when they have made +a mistake or when something changes they need to reflect in the post. To +indicate you have edited a post, you can include an `updated` date in the page +header. Note that this means that you need to move the original publication date +to a `created` attribute of the `date` entry. + +!!! 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: 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="4-6" + --- + date: 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="5-7" + --- + date: 2023-12-31 + ... + links: + - Homepage: index.md + - Blog index: blog/index.md + - External links: + - Material documentation: https://squidfunk.github.io/mkdocs-material + --- + ``` + +As you can see, the plugin renders subsections in the left sidebar on screens +that are wide enough, and in a way similar to mobile navigation menus on +more narrow screens. + + + + + +## 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/`. + +[Insiders Edition]: ../../insiders/index.md + +## 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. + +[tutorial on navigation, pagination, and authors]: navigation.md + +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. + +[engagement and dissemination tutorial]: engage.md diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md new file mode 100644 index 00000000000..4117c687c52 --- /dev/null +++ b/docs/tutorials/blogs/navigation.md @@ -0,0 +1,434 @@ +# Navigation, authors, and pagination tutorial + +The Blog plugin provides blog-style navigation with a reverse-chronological +index page and an archive organized by year by default. This tutorial shows +how you can configure details of the default navigation, configure authors, and +add more navigation options using categories and the [Tags plugin]. + +[Tags plugin]: ../../plugins/tags.md + + +## Integrating navigation + +So far, you have let the Blog plugin and MkDocs worry about navigation. For some +use cases, this might be enough and it is simply sufficient to not declare a +`nav` section in the `mkdocs.yml`. + +However, you may want to integrate a blog with other content and a navigation +structure that you have defined in the `nav` section of the configuration. +In such cases, you need to provide a place where the Blog plugin should +attach the blog navigation to the rest of the navigation structure. + +!!! example "Integrate with site navigation" + + Add the following to your `mkdocs.yml` to see how the Blog plugin can + integrate the blog navigation with the overall navigation structure. + Note that the only thing you need to specify at this point is the + index page for the blog and its path must match the `blog_dir` setting, + which is `blog` by default: + + ```yaml hl_lines="5 6" + nav: + - Home: index.md + - Install: install.md + - Usage: usage.md + - Blog: + - blog/index.md + ``` + + You will notice that "Blog" is duplicated in the navigation structure. To + avoid this, you can use the `navigation.indexes` feature to make the blog + index the seciton index page for the blog: + + ```yaml hl_lines="3 4" + theme: + name: material + features: + - navigation.indexes + ``` + +!!! tip "Stand-alone blog" + + If what you need is a stand-alone blog instead of one that is integrated with + a larger site, this can be done by using the `blog_dir` configuration option. + To see how this is done, see [setting up a blog]. + The rest of the tutorial assumes that you are integrating the blog with + a wider site. + +[Setting up a blog]: ../../setup/setting-up-a-blog.md#blog-only + +!!! tip "Adding pages" + + You can add additional pages to the blog section by putting them into + `docs/blog` (and adding them to the navigation). The blog archive will be + added to the navigation after these pages. + +## Configuring the archive + +By default, the blog archive lists posts by year only. If you want to add +listings by month, you can configure the date format for the archive. + +!!! example "Organize posts by month" + + Add the following to your `mkdocs.yml` to get a listing with the month + name (in the language selected in the theme options): + + ```yaml hl_lines="2" + - blog: + archive_date_format: MMMM yyyy + ``` + + If you do not want the full month name, you can make the the date + configuration `MM/yyyy`, for example. + + If you want to add the day, you can add a placeholder for them. + For example, to get an American-style output, make it `MM/dd/yyyy`. + For the plugin to sort the blog posts by the full date, you will + also need to set the `archive_url_date_format` to include the month + and day, so make it `MM/dd/yyyy` as well. + +## Using categories + +Categories are a way to make blog posts accessible by topic while retaining +the navigation structure based on chronology within each category listing. +Use them when there is a limited set of non-overlapping categories that +you can sort your posts into. + +Categories appear in the main navigation, so are directly accessible from there. +This implies that there are relatively few categories as otherwise the +`categories` section in your main navigation will become too crowded. + + +!!! example "Add a category" + + Add a category to your first blog post by adding it to the page header: + + ``` hl_lines="4 5"" + --- + date: 2023-12-31 + updated: 2024-01-02 + categories: + - Holidays + --- + ``` + + Now that the blog post has been categorised, `Holidays` appears under + `Categories` in the main navigation and the blog post appears in the + index page for this category. + + +!!! tip "Single or multiple categories?" + + While it is traditionally the case that a blog post would belong to only + one category, Material for MkDocs actually allows you to assign more + than one. While this gives you a degree of freedom, you should + probably not use this too much, not least because you can use tags to + deal with multiple classifications. We will cover them in the next step. + +Material allows you to control which categories blog authors can use. You +declare them in the `mkdocs.yml`. This way you can make sure everyone sticks +to agreed categories and that the plugin detects typos. + +!!! example "Control your categories" + + Add a `categories_allowed` entry to the configuration of the Blog plugin + with the entries "Holidays" and "News": + + ```yaml hl_lines="5-7" + plugins: + - search + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + ``` + + Now, when you add a category to a blog post that does not match one of these + two, you should get a build error. + +## Using tags + +The [Tags plugin] provides another way to classify blog posts and to make +them accessible independently of the main navigation structure. Tags are useful +for making related content easily discoverable even if it is in different parts +of the navigation hierarchy. + +[Tags plugin]: https://squidfunk.github.io/mkdocs-material/plugins/tags/ + +You may have a tutorial like this one as well a more comprehensive setup guide +and reference documentation. Adding the same tag to all three shows that they +are related. As you will see, it is possible to navigate from a tagged page to +the tag index and, from there, to other pages that carry the same tag. + +!!! example "Enable the plugin and add tags" + + First, you need to add the plugin to your `mkdocs.yml`: + + ```yaml hl_lines="8" + plugins: + - search + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + - tags + ``` + + Once this is done, you can add tags to posts in the page header: + + ``` hl_lines="8-11"" + --- + date: 2023-12-31 + updated: 2024-01-02 + authors: + - material + categories: + - Holidays + tags: + - new year + - hogmanay + - festive season + --- + ``` + +You should see the tags that you defined at the top of the post. However, at the +moment that is it. While the blog plugin automatically creates an index page for +categories, the tags plugin does not do the same for tags. This is because the +tags plugin is not specific for blogs. You can use it for any site content, so +it is not obvious were the tag index should go. + +You can configure a basic tag index using the public version of Material for +MkDocs. The Insider Edition supports this as well, of course, but also provides +an alternative index mechanism that allows for an arbitrary number of tag +indexes, scoped listings, shadow tags, nested tags, and much more. + +!!! example "Adding a tags index" + === "Basic tag index" + + To configure a tag index using the public version, add a `tags_file` entry + to your configuration of the tags plugin and configure it in your `nav` + section. Remember to add a colon at the end of the existing `tags` entry. + + ```yaml hl_lines="8-9 17" + plugins: + - search + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + - tags: + tags_file: blog/tags.md + + nav: + - Home: index.md + - Install: install.md + - Usage: usage.md + - Blog: + - blog/index.md + Tags: blog/tags.md + ``` + + The tag index will be appended to the configured page, which you should + now create at the location specified. + + Note that you can put the tag index page anywhere in your primary + navigation, so if you are using tags elsewhere instead of just in your + blog then you may want to have the tag index outside the blog section + of the navigation. + + + === "Insider Edition" + + To add a tag index, you add a placeholder in a Markdown file to tell + the plugin to insert an index at that point. This means that you + can add content before and after the index. Crucially, you can add + placeholders in multiple pages, each with a configuration of what + subset of tags should be displayed in the index. + + The simplest index page looks like this. Create it under `docs/tags.md`. + + ```markdown + # Tag index + + ``` + + Now, you may want to keep the tags for your blog separate from tags + you use in the rest of your page. You can achieve this by assigning + the tag index a scope. Put the following under `docs/blog/tags.md`: + + ```markdown + # Tag index for the blog + + ``` + + You now have two index pages: one covers the whole site and one + covers only the blog. + + The tags plugin in the Insider Edition is an incredibly powerful tool + and we can only scratch the surface of what is possible with it. If you + want to explore more after you have worked for this part of the tutorial, + have a look at the [tags plugin reference]. + +[tags plugin reference]: ../../plugins/tags.md + +## Defining authors + +If your blog has more than one author then you may want to identify the author +for each blog post. The blog plugin allows you to create a file that contains +the author information and to then reference the authors of a particular post in +the page header. + +!!! example "Create author info" + + Create a file `docs/blog/.authors.yml` with this content: + + ```yaml + authors: + material: + name: Team + description: Creator + avatar: https://simpleicons.org/icons/materialformkdocs.svg + squidfunk: + name: Martin Donath + description: Creator + avatar: https://github.com/squidfunk.png + ``` + + and then add a line to the header of the first post: + + + ```hl_lines="4-5" + --- + date: 2023-12-31 + updated: 2024-01-02 + authors: + - team + --- + ``` + + Note that `authors` is a list, so you can specify multiple authors. + +With the Insiders edition, you can create custom author index pages that +can highlight the contributions of an author as well as provide additional +information about them. + +!!! example "Add author page " + + First, you need to enable author profiles in the `mkdocs.yml`: + + ```yaml hl_lines="8" + plugins: + - search + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + authors_profiles: true + ``` + + Check your blog to see that there is now an extra entry in the main + navigation next to `archive` and `categories` that lists the authors and + their contributions. + + To customize the author page, you can create a page that overrides the one + generated by default. First, create the `author` directory that the profile + pages will live in: + + ```hl_lines="3" + docs + ├── blog + │   ├── author + │   ├── index.md + │   └── posts + │   ├── draft.md + │   └── myfirst.md + └── index.md + ``` + + Then create a page `docs/blog/author/team.md`: + + ``` + # The Material Team + + A small group of people dedicated to making writing documentation easy, if + not outright fun! Here are some of the things we have blogged about: + ``` + + As you can see, the author index gets appended to the content you have + written in the Markdown file. + +## Pagination + +Once your blog starts growing, you may not want to pay attention to the number +of posts displayed per page. By default, the plugin displays up to 10 posts on +the index pages. You can change this number separately for the main index, +the archive index pages, and the category index pages. + +!!! example "Changing pagination" + + Add five more blog posts, then set the pagination setting to show five per + page only: + + ```yaml hl_lines="7" + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + authors_profiles: true + pagination_per_page: 5 + ``` + + You will see that the pagination setting for archive and category pages + are inherited from the setting you added. If you want to have different + settings for the different index pages, you can specify each setting + separately: + + ```yaml + - blog: + archive_date_format: MMMM yyyy + categories_allowed: + - Holidays + - News + authors_profiles: true + pagination_per_page: 5 + archive_pagination_per_page: 10 + categories_pagination_per_page: 10 + ``` + +## Custom slugs + +If, for some reason, you are not happy with the way that Material for MkDocs +turns headings into slugs, you can create your own slugify function or you +can manually define a slug for a post. + +!!! example "Slugify function" + + To define your own slugify function, you need to write code that... + + +Another useful header attribute is `slug`, which allows you to define the slug +for your post instead of having it auto-generated by the Blog plugin from the +first heading. + +!!! example "Change slug" + + If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat + lengthy 'happy-new-years-eve', you could add the following: + + ```hl_lines="6" + --- + date: 2023-12-31 + updated: 2024-01-02 + readtime: 15 + pin: true + slug: ny-eve + --- + ``` + + The URL for this post should now be + `http://localhost:8000/blog/2023/01/31/ny-eve/`. \ No newline at end of file diff --git a/docs/tutorials.md b/docs/tutorials/index.md similarity index 57% rename from docs/tutorials.md rename to docs/tutorials/index.md index dd888e22444..21097fffde9 100644 --- a/docs/tutorials.md +++ b/docs/tutorials/index.md @@ -6,17 +6,21 @@ the getting started guides or the reference documentation, the tutorials show the breadth of features available in Material for MkDocs but also within the wider MkDocs ecosystem. -* [Blogs](tutorials/blogs.md) + +* Blogs + * [Basics](blogs/basic.md) (20 min)
+ covers the basics of setting up a blog, including post metadata. + * [Navigation, pagination, multiple authors](blogs/navigation.md) (30 min)
+ describes how to make it easier for your readers to find content. + * [Engagement and dissemination](blogs/engage.md) (30 min)
+ walks you through ways of increasing engagement with your content ## Tutorial structure The tutorials guide you through worked examples, so following them you should gain not only an understanding of how to use Material for MkDocs, but also a template for your own projects. For convenience, these templates are also -available as [template repositories on GitHub]. - - -[template repositories on GitHub]: templates.md +available as template repositories on GitHub. Each tutorial is a single page, so use the Table of Contents navigation to move between steps. They start by mentioning prerequisites, giving an @@ -31,9 +35,8 @@ tutorial: !!! example "Instructions to follow" - Whenever you see a box like this you know it is time to get hands on and - apply material just covered as well as reflect on how you would it in your - work work. + Whenever you see a box like this you know it is time to get hands on and + apply material just covered. ### Tips and warnings @@ -47,6 +50,20 @@ Likewise, helpful tips and warnings appear in boxes of their own: ...and warnings like this! +## Prerequisites +The tutorials assumes that you have installed either the +[public version] or the [Insiders edition] of Material for MkDocs and that you have +worked through the [creating your site] setup guide. Note that where the features +we use the Insiders edition, we mark these with the heart icon: + If you are using the public version then you can skip these +steps. Sometimes there will be ways of achieving the same goal that differ +between the public version and the Insider edition. In that case, we will show +them in a tabbed view so you can see one or the other. + +[public version]: ../getting-started.md +[Insiders edition]: ../insiders/getting-started.md +[creating your site]: ../creating-your-site.md + ## Feedback wanted The tutorials are a recent addition to our documentation and we are still diff --git a/mkdocs.yml b/mkdocs.yml index 12083063ed7..314c5e5edd0 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -174,13 +174,15 @@ markdown_extensions: custom_checkbox: true - pymdownx.tilde +not_in_nav: | + /tutorials/**/*.md + # Page tree nav: - Home: index.md - Getting started: - Installation: getting-started.md - Creating your site: creating-your-site.md - - Tutorials: tutorials.md - Publishing your site: publishing-your-site.md - Customization: customization.md - Conventions: conventions.md @@ -189,6 +191,8 @@ nav: - Philosophy: philosophy.md - Alternatives: alternatives.md - License: license.md + - Tutorials: + - tutorials/index.md - Changelog: - changelog/index.md - How to upgrade: upgrade.md From c9925f461c461dcd6b76b24594342d1944c39b1e Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Thu, 18 Apr 2024 15:19:27 +0200 Subject: [PATCH 04/29] + custom slugify function example --- docs/tutorials/blogs/navigation.md | 61 +++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index 4117c687c52..5bc2ec0ccd1 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -404,18 +404,67 @@ the archive index pages, and the category index pages. If, for some reason, you are not happy with the way that Material for MkDocs turns headings into slugs, you can create your own slugify function or you -can manually define a slug for a post. +can manually define a slug for a specific post. !!! example "Slugify function" - To define your own slugify function, you need to write code that... + To define your own slugify function, you need to write a Python function + that converts text into a slug given additional arguments from the + configuration. You also need to write a function that returns that + function. + + Say you want to define two slugify functions that you can switch between. + The first one returns a slug similar to what the default slugify function + produces. The second one cuts the result of that up into words and returns + a slug based on a maximum of five of them: + + ```python + import re, functools, unicodedata + + RE_HTML_TAGS = re.compile(r']*>', re.UNICODE) + RE_INVALID_SLUG_CHAR = re.compile(r'[^\w\- ]', re.UNICODE) + RE_WHITESPACE = re.compile(r'\s', re.UNICODE) + + def _make_slug(text, sep, **kwargs): + slug = unicodedata.normalize('NFC', text) + slug = RE_HTML_TAGS.sub('', slug) + slug = RE_INVALID_SLUG_CHAR.sub('', slug) + slug = slug.strip().lower() + slug = RE_WHITESPACE.sub(sep, slug) + return slug + + def _make_slug_short(text, sep, **kwargs): + words = _make_slug(text, sep, **kwargs).split(sep) + return sep.join(words[:5]) + + def slugify(**kwargs): + if 'short' in kwargs and kwargs['short']: + return functools.partial(_make_slug_short, **kwargs) + return functools.partial(_make_slug, **kwargs) + ``` + Save this code in `code/slugs.py` and also add an (empty) `__init__.py`` + file to indicate that the directory is a module. Now you can configure + your custome slugify code like this: + + ```yaml hl_lines="4-6" + plugins: + - blog: + # other entries omitted + post_slugify: !!python/object/apply:code.slugs.slugify + kwds: + short: true + ``` + Change the heading of a blog post to be longer than five words and observe + how the slugify function shortens the URL. Change the `short` attribute to + `false` and you can turn this off again. -Another useful header attribute is `slug`, which allows you to define the slug -for your post instead of having it auto-generated by the Blog plugin from the -first heading. +If you want to influence the slug only for a single blog post, you can define +it manually by specifying it in the header of the post. Note that this is meant +as a last resort option. Specifying a custom slug manually for every post would +be tedious. -!!! example "Change slug" +!!! example "Manually define slug" If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat lengthy 'happy-new-years-eve', you could add the following: From e0a5b293bdb55f607f5ea417e9185d0893bd43a6 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Thu, 18 Apr 2024 16:06:30 +0200 Subject: [PATCH 05/29] +blog tutorial on engagement --- docs/tutorials/blogs/engage.md | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/tutorials/blogs/engage.md diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md new file mode 100644 index 00000000000..8f2f60597b3 --- /dev/null +++ b/docs/tutorials/blogs/engage.md @@ -0,0 +1,72 @@ +# Engagement and dissemination + +You can foster reader engagement and improve the dissemination of content +on your blog by providing an RSS feed that people can subscribe to and by +integrating a discussion system. To learn more about who is or is not reading +your posts, you may want to integrate an analytics system. You may also want +to post on social media when you public a new blog post. This tutorial gives +you a leg up on all of these topics. + +## RSS feeds + +An _RSS feed_ allows users to subscribe to a blog so that they get notified when +you publish new posts. RSS Feed readers are often used to access blogs that a +user follows. They usually support downloading the blog content for offline +consumption. + +An easy way to create an RSS feed for your blog is to use the +[MkDocs RSS Plugin], which is well integrated with Material for MkDocs. +Since it is a third-party plugin, you need to install it before using it. + +[MkDocs RSS Plugin]: https://guts.github.io/mkdocs-rss-plugin + + +!!! example "Add an RSS feed" + + Install the RSS plugin into your project: + + ``` + $ pip install mkdocs-rss-plugin + ``` + + It is important that have the `site_name`, `site_description` and + `site_url` settings configured as [instructed in the basic blog tutorial]. + The RSS plugin makes use of this information to construct the feed, so make + sure you have configured them. + + [instructed in the basic blog tutorial]: basic.md#setting-up-your-blog + + Now, configure the plugin in the `mkdocs.yml`: + + ```yaml hl_lines="9" + plugins: + - search + - blog: + authors_profiles: true + categories_allowed: + - Holidays + - News + - tags + - rss + ``` + + Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS + feed in all its XML glory. You can use a browser like Firefox or Chrome that + can display the raw RSS feed or use `curl` to get the feed and `xmllint` to + format it. You may need to install these tools: + + ``` + curl -s http://localhost:8000/feed_rss_created.xml | xmllint --format - + ``` + + You may also want to try your feed with a feed reader. There are various desktop + and mobile apps as well as online services. Of course, to use the latter you + will need to deploy your project somewhere that is accessible to them. + +This minimal configuration should work well if you have not made any changes +to the default configuration of the blog plugin. For more information on +adapting the feed to your needs, see [the RSS plugin's documentation]. + +[the RSS plugin's documentation]: https://guts.github.io/mkdocs-rss-plugin/ + +## Add a discussion system \ No newline at end of file From 5de5a4f21c5b19d7b279da8be0219c1bb4d2b780 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Fri, 19 Apr 2024 10:08:57 +0200 Subject: [PATCH 06/29] + section blog ToC --- docs/tutorials/blogs/navigation.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index 5bc2ec0ccd1..b42d2a944a9 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -400,6 +400,26 @@ the archive index pages, and the category index pages. categories_pagination_per_page: 10 ``` +## Blog table of contents + +Another thing you may want to do once you have a large enough number of posts +is to turn on the function that produces a table of contents for the blog +index pages, giving your readers the opportunity to quickly scan the content +of each page for something that interests them without having to scroll +(assuming that the number of post per page is not too big). + +!!! example "Turn on the table of contents feature" + + To produce a table of contents for the blog index pages, add the following + to the configuration of the blog plugin: + + ```yaml hl_lines="2" + - blog: + blog_toc: true + archive_date_format: MMMM yyyy + # ... + ``` + ## Custom slugs If, for some reason, you are not happy with the way that Material for MkDocs From 186c1c13451e46f51c1b0555671fcf77950291d3 Mon Sep 17 00:00:00 2001 From: Alex Voss Date: Thu, 25 Apr 2024 14:40:24 +0200 Subject: [PATCH 07/29] + instructions for X/FB share buttons and started discussion system --- docs/tutorials/blogs/engage.md | 215 ++++++++++++++++++++++++++++++++- 1 file changed, 213 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md index 8f2f60597b3..5df96be0fce 100644 --- a/docs/tutorials/blogs/engage.md +++ b/docs/tutorials/blogs/engage.md @@ -53,7 +53,7 @@ Since it is a third-party plugin, you need to install it before using it. Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS feed in all its XML glory. You can use a browser like Firefox or Chrome that can display the raw RSS feed or use `curl` to get the feed and `xmllint` to - format it. You may need to install these tools: + format it. (You may need to install these tools.) ``` curl -s http://localhost:8000/feed_rss_created.xml | xmllint --format - @@ -69,4 +69,215 @@ adapting the feed to your needs, see [the RSS plugin's documentation]. [the RSS plugin's documentation]: https://guts.github.io/mkdocs-rss-plugin/ -## Add a discussion system \ No newline at end of file +## Social media buttons + +Social media buttons can serve two purposes: to allow your readers to navigate +to your social media profiles or to share content you have published via their +own accounts. + +### Profile links + +Links to social media profiles a usually provided in the footer of pages and +Material for MkDocs makes this easy. All you need to do is to provide the +necessary links and define the icons to use. + +!!! example "Adding social media profile links" + + Add an `extra` section to your `mkdocs.yml` and, within it, a `social` + section to contain a list of link definitions. These consist of the logo + to use and the link to the profile. + + ```yaml + extra: + social: + - icon: fontawesome/brands/mastodon + name: squidfunk on Mastodon + link: https://fosstodon.org/@squidfunk + ``` + + For the `icon`, you can choose any valid path to an icon bundled with the + theme. The `name` will be used as the title attribute for the icon and + including this improves accessibility. + For popular social media systems, the link needs to be absolute and + needs to include the scheme, most likely `https://`. + + You can also use other schemes. For example, to cerate an icon that allows + people to create an email, add this: + + ```yaml + extra: + social: + - icon: /fontawesome/regular/envelope + name: send me an email + link: mailto: + ``` + + Finally, you can specify a URL within your side, such as to your contact + page. It is possible to specify only the path to the page: + + ```yaml + extra: + social: + - icon: /material/mailbox + name: contact us + link: /contact + ``` + +### Share and like buttons + +Adding buttons that let people share your content on social media is a bit +more involved, which is why there are companies offering components for this. + + +!!! tip "Data Protection" + + "Share" and "Like" buttons that use integrations provided by social media + companies often leave copious data traces even when the user does not + interact with these buttons. If you choose to integate such feature on + your site please be aware of the data protection implications and your + duties as a provider to ensure that processing occurs only once the user + has granted consent. + +The implementation of share buttons deliberately does not use third party code +to practice data minimization. It supports sharing to Twitter/X and +Facebook without causing a data flow to these companies whenever someone views +the pages. Only when someone clicks a share button will there be interactions +with those companies' servers. + +!!! example "Add share buttons" + + In order to add the share buttons, you can add a hook that appends buttons + for sharing the current page. + + Create a directory `hooks` in your project root and configure it + in your `mkdocs.yml`: + + ```yaml + hooks: + - hooks/socialmedia.py + ``` + + Add the file `hooks/socialmedia.py` with the following Python code: + + ```python + from textwrap import dedent + import urllib.parse + import re + + x_intent = "https://twitter.com/intent/tweet" + fb_sharer = "https://www.facebook.com/sharer/sharer.php" + include = re.compile(r"blog/[1-9].*") + + def on_page_markdown(markdown, **kwargs): + page = kwargs['page'] + config = kwargs['config'] + if not include.match(page.url): + return markdown + + page_url = config.site_url+page.url + page_title = urllib.parse.quote(page.title+'\n') + + return markdown + dedent(f""" + [Share on :simple-x:]({x_intent}?text={page_title}&url={page_url}){{ .md-button }} + [Share on :simple-facebook:]({fb_sharer}?u={page_url}){{ .md-button }} + """) + ``` + + The hook first checks if the current page is a blog post and then appends + Markdown code for the share buttons. + + +## Add a discussion system + +Allowing your readers to comment on your posts is a great way of receiving +feedback, learning something, as well as giving readers the opportunity to +discuss the content and the topic it is about. + +There are plenty of discussion system out there and you will need to consider +your audience when choosing one appropriate for your blog. In this tutorial, +we will be using [Giscus] because it is free, open source, and uses [GitHub +Discussions] as a backend. Because a lot of users of Material for MkDocs use +GitHub, this seems like an obvious choice. + +[Giscus]: https://giscus.app/ +[GitHub Discussions]: https://docs.github.com/en/discussions + +To add Giscuss to your blog you will need to go through a number of steps: + +1. Create a GitHub repository if there is not already one +2. Turn on discussions and install the [Giscus app] +3. Configure the code needed to embed Giscus into your blog +4. Add the code to your MkDocs project + +!!! example "Create a GitHub repository" + + You may want to create a test repository for this tutorial that you an + scap later on. The instructions below assume that you are user "example" + and that you create a repository "giscus-test". The repository will need + to be public for people to be able to use the discussions. + + In the instructions given, you will need to replace at least the username + but also the repository name if you chose another name such as when you + want to work directly on an existing repository. + +!!! example "Turn on discussions and install the Giscus app" + + Once the repository is set up, go to its settings page and find the + `Features` section. Tick the checkbox for `Discussions`. You will see that + `Discussions` appears in the top navigation for the repository. If you + are using a live repository then you may want to add some minimal content + to the dicussions section at this point and come back to the tutorial. + + Next, you need to [install the Giscus app] by following the link in this + sentence, and choosing `Install`, then following the instructions to choose + where the Giscus app is to be installed: + + + 1. Choose the account or organization for the repository you want to use. + 2. Choose to install only on select repositories and select the one you + want to use. Note that you can choose more than one repository here. + 3. Select `Install` at the end. You may need to authenticate to give + permission for this to happen. + 4. You will end up on the `Applications` page in your settings, where you + can control the Gicsus app and uninstall it if so desired. + +!!! example "Configure the code needed to embed Giscus into your blog" + + Now it is time to go back to the [Giscus homepage] and configure the + embedding code. There are a number of settings: + + 1. Choose the language + 2. Enter the username / organization name and repository name + 3. Choose how the discussions are to be mapped to the page on your blog. + Because for a blog post the title is the basis of the URL, it makes + sense to use the `Discussion title contains page ` option. + 4. Under `Discussion Category` choose `Announcements` to limit the creation + of new + + 5. Under `Features`, select the following: + 1. Enable reactions for the main post + 2. Emit discussion metadata + 3. + + + The resulting code snippet should look like this: + + ```html + <script + src="https://giscus.app/client.js" + data-repo="<username>/<repository>" + data-repo-id="..." + data-category="..." + data-category-id="..." + data-mapping="pathname" + data-reactions-enabled="1" + data-emit-metadata="1" + data-theme="preferred_color_scheme" + data-lang="en" + crossorigin="anonymous" + async + > + </script> + ``` + +[Giscus homepage]: https://giscus.app/ \ No newline at end of file From cc19431c5c0e7fee9b2954d505f6e6f62127a899 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Tue, 30 Apr 2024 14:30:03 +0200 Subject: [PATCH 08/29] fix: module name `code` shadowed Python standard library module --- docs/tutorials/blogs/navigation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index b42d2a944a9..0ea286030ad 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -462,15 +462,15 @@ can manually define a slug for a specific post. return functools.partial(_make_slug_short, **kwargs) return functools.partial(_make_slug, **kwargs) ``` - Save this code in `code/slugs.py` and also add an (empty) `__init__.py`` + Save this code in `ext/slugs.py` and also add an (empty) `__init__.py`` file to indicate that the directory is a module. Now you can configure - your custome slugify code like this: + your custom slugify code like this: ```yaml hl_lines="4-6" plugins: - blog: # other entries omitted - post_slugify: !!python/object/apply:code.slugs.slugify + post_slugify: !!python/object/apply:ext.slugs.slugify kwds: short: true ``` From 876e7c68a93b32b1de55d78a09cb068c4e35f740 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Wed, 1 May 2024 21:51:06 +0200 Subject: [PATCH 09/29] added What's next section --- docs/tutorials/blogs/navigation.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index 0ea286030ad..6a26e89bdfc 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -287,7 +287,7 @@ the page header. ```yaml authors: - material: + team: name: Team description: Creator avatar: https://simpleicons.org/icons/materialformkdocs.svg @@ -500,4 +500,13 @@ be tedious. ``` The URL for this post should now be - `http://localhost:8000/blog/2023/01/31/ny-eve/`. \ No newline at end of file + `http://localhost:8000/blog/2023/01/31/ny-eve/`. + +## What's next? + +You may want to increase engagement with your blog by allowing people to +subscribe to an RSS feed, by providing links to your social media profiles, by +providing share and like buttons, or by setting up a comment system. +The [engagement and dissemination tutorial] walks you through setting these up. + +[engagement and dissemination tutorial]: engage.md \ No newline at end of file From cd15b11057be7a93a0a1301b0f0699c5c5c4c6b1 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Thu, 2 May 2024 11:22:44 +0200 Subject: [PATCH 10/29] +blog tutorial engagement part --- docs/tutorials/blogs/engage.md | 159 ++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 43 deletions(-) diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md index 5df96be0fce..2eaf1e968c3 100644 --- a/docs/tutorials/blogs/engage.md +++ b/docs/tutorials/blogs/engage.md @@ -194,10 +194,17 @@ feedback, learning something, as well as giving readers the opportunity to discuss the content and the topic it is about. There are plenty of discussion system out there and you will need to consider -your audience when choosing one appropriate for your blog. In this tutorial, -we will be using [Giscus] because it is free, open source, and uses [GitHub -Discussions] as a backend. Because a lot of users of Material for MkDocs use -GitHub, this seems like an obvious choice. +your audience when choosing one appropriate for your blog. Likewise, you will +also need to consider existing commitments to communication channels. If you +are a heavy user Slack, for example, you may have a string preference for this +system. Consider that when you add a communication channel, you will need to +be prepared to use it regularly and to moderate discussions. + +### Giscus integration + +In this tutorial, we will be using [Giscus] because it is free, open source, +and uses [GitHub Discussions] as a backend. Because a lot of users of Material +for MkDocs use GitHub, this seems like an obvious choice. [Giscus]: https://giscus.app/ [GitHub Discussions]: https://docs.github.com/en/discussions @@ -209,30 +216,30 @@ To add Giscuss to your blog you will need to go through a number of steps: 3. Configure the code needed to embed Giscus into your blog 4. Add the code to your MkDocs project -!!! example "Create a GitHub repository" +[Giscus app]: https://github.com/apps/giscus - You may want to create a test repository for this tutorial that you an - scap later on. The instructions below assume that you are user "example" - and that you create a repository "giscus-test". The repository will need - to be public for people to be able to use the discussions. +You may want to create a test repository for this tutorial that you can +scrap later on. The instructions below assume that you are user "example" +and that you create a repository "giscus-test." The repository will need +to be public for people to be able to use the discussions. - In the instructions given, you will need to replace at least the username - but also the repository name if you chose another name such as when you - want to work directly on an existing repository. +In the instructions given below, you will need to replace at least the username +but also the repository name if you chose another name such as when you +want to work directly on an existing repository. !!! example "Turn on discussions and install the Giscus app" - Once the repository is set up, go to its settings page and find the - `Features` section. Tick the checkbox for `Discussions`. You will see that - `Discussions` appears in the top navigation for the repository. If you - are using a live repository then you may want to add some minimal content - to the dicussions section at this point and come back to the tutorial. + Once the repository is set up, go to its settings page and find + `Features` in the `General` section. Tick the checkbox for `Discussions`. + You will see that `Discussions` appears in the top navigation for the + repository. If you are using a live repository then you may want to add some + minimal content to the dicussions section at this point and come back to the + tutorial. - Next, you need to [install the Giscus app] by following the link in this + Next, you need to install the [Giscus app] by following the link in this sentence, and choosing `Install`, then following the instructions to choose where the Giscus app is to be installed: - 1. Choose the account or organization for the repository you want to use. 2. Choose to install only on select repositories and select the one you want to use. Note that you can choose more than one repository here. @@ -241,10 +248,32 @@ To add Giscuss to your blog you will need to go through a number of steps: 4. You will end up on the `Applications` page in your settings, where you can control the Gicsus app and uninstall it if so desired. +That is all the preparation you will need for the repository. Next, it is time +to generate a piece of code that embeds Giscuss in your site. The resulting code +snippet will look something like this: + +```html +<script + src="https://giscus.app/client.js" + data-repo="<username>/<repository>" + data-repo-id="..." + data-category="..." + data-category-id="..." + data-mapping="pathname" + data-reactions-enabled="1" + data-emit-metadata="1" + data-theme="preferred_color_scheme" + data-lang="en" + crossorigin="anonymous" + async +> +</script> +``` + !!! example "Configure the code needed to embed Giscus into your blog" - Now it is time to go back to the [Giscus homepage] and configure the - embedding code. There are a number of settings: + Go to the [Giscus homepage] and configure the embedding code. There are a + number of settings: 1. Choose the language 2. Enter the username / organization name and repository name @@ -252,32 +281,76 @@ To add Giscuss to your blog you will need to go through a number of steps: Because for a blog post the title is the basis of the URL, it makes sense to use the `Discussion title contains page <title>` option. 4. Under `Discussion Category` choose `Announcements` to limit the creation - of new - + of new discussions to Giscuss and people with maintainer or admin + permissions. 5. Under `Features`, select the following: - 1. Enable reactions for the main post - 2. Emit discussion metadata - 3. + 1. Enable reactions for the main post + 2. Emit discussion metadata + 3. Place the comment box above the comments + 6. Under `Theme`, select `Preferred color scheme` so that Giscus matches + the color scheme selected by the user for your site. + +[Giscus homepage]: https://giscus.app/ +With these settings in place, you now need to integrate the code into your +site. There is a partial `partials/comments.html` that exists for this purpose +and is empty be default. It is included by the `content.html` partial, so will +be included for every page on your site. You may or may not want this. In this +tutorial, you will limit the Giscus integration to only blog posts but it is +easy enough to leave out the code that achieves this if you want to have Giscus +discussions active for every page. + +!!! example "Add Giscus integration code" + + First, you need to create an `overrides` directory that will contain the + templates and partials you want to override. + + ``` + mkdir -p overrides/partials + ``` - The resulting code snippet should look like this: + You need to declare it in your `mkdocs.yaml`: + + ```yaml hl_lines="3" + theme: + name: material + custom_dir: overrides + ``` + + Now add a file `overrides/partials/comments.html` and paste in the code + snippet you obtained from the Giscus homepage. Look at the result locally + and you will see that the integration is active on all pages of the site. + If you want to restrict it to your blog posts, you need to add a conditional + around the Giscus script that tests if comments should be included. A simple + way of doing this is to test for a metadata flag: + + ```html + {% if page.meta.comments %} + <script>...</script> + {% endif %} + ``` + + The disadvantage is that you now need to manually turn on comments for each + blog post - unless you want to turn them off on some. To get the comments + section on all blog posts, use code like this: ```html - <script - src="https://giscus.app/client.js" - data-repo="<username>/<repository>" - data-repo-id="..." - data-category="..." - data-category-id="..." - data-mapping="pathname" - data-reactions-enabled="1" - data-emit-metadata="1" - data-theme="preferred_color_scheme" - data-lang="en" - crossorigin="anonymous" - async - > - </script> + {% if page.file.src_uri.startswith('blog/posts') %} + <script>...</script> + {% endif %} ``` -[Giscus homepage]: https://giscus.app/ \ No newline at end of file + You should see now that the Giscus comments are added at the bottom of your + blog posts but not on other pages. + +## What's next? + +This is the end of the blog tutorial. We hope you have enjoyed it and manage to +set up your blog the way you like it. There are numerous other features and +options that we have not been able to cover here. The [blog plugin reference] +provides comprehensive documentation for the plugin. You may also want to +look at the [social plugin tutorial] to generate social cards for your blog +posts that get displayed when you post links to social media systems. + +[blog plugin reference]: https://squidfunk.github.io/mkdocs-material/plugins/blog/ +[social plugin tutorial]: ../social.md From 790ff4dd9e0fbd852c843c2b65306b73a60a2427 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Thu, 2 May 2024 11:28:22 +0200 Subject: [PATCH 11/29] fix: updated Giscus code snippet --- docs/tutorials/blogs/engage.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md index 2eaf1e968c3..56b24f4247e 100644 --- a/docs/tutorials/blogs/engage.md +++ b/docs/tutorials/blogs/engage.md @@ -253,20 +253,21 @@ to generate a piece of code that embeds Giscuss in your site. The resulting code snippet will look something like this: ```html -<script - src="https://giscus.app/client.js" - data-repo="<username>/<repository>" - data-repo-id="..." - data-category="..." - data-category-id="..." - data-mapping="pathname" - data-reactions-enabled="1" - data-emit-metadata="1" - data-theme="preferred_color_scheme" - data-lang="en" - crossorigin="anonymous" - async -> +<script src="https://giscus.app/client.js" + data-repo="<username>/<repository>" + data-repo-id="..." + data-category="Announcements" + data-category-id="..." + data-mapping="title" + data-strict="1" + data-reactions-enabled="1" + data-emit-metadata="1" + data-input-position="top" + data-theme="preferred_color_scheme" + data-lang="en" + data-loading="lazy" + crossorigin="anonymous" + async> </script> ``` From 3a3ae8dd34951e213d37163962a48c3317233cb8 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Thu, 2 May 2024 20:31:35 +0200 Subject: [PATCH 12/29] trying multiple tutorials with headings for each group --- docs/tutorials/index.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index 21097fffde9..ca9e9c68a70 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -7,13 +7,20 @@ the breadth of features available in Material for MkDocs but also within the wider MkDocs ecosystem. <!-- TODO: add links to template repos --> -* Blogs - * [Basics](blogs/basic.md) (20 min) <br/> - covers the basics of setting up a blog, including post metadata. - * [Navigation, pagination, multiple authors](blogs/navigation.md) (30 min)<br/> - describes how to make it easier for your readers to find content. - * [Engagement and dissemination](blogs/engage.md) (30 min)<br/> - walks you through ways of increasing engagement with your content +## Blogs +* [Basics](blogs/basic.md) (20 min) <br/> + covers the basics of setting up a blog, including post metadata. +* [Navigation, pagination, multiple authors](blogs/navigation.md) (30 min)<br/> + describes how to make it easier for your readers to find content. +* [Engagement and dissemination](blogs/engage.md) (30 min)<br/> + walks you through ways of increasing engagement with your content + +## Social cards +* [Basics](social/basic.md) (20 min) <br/> + shows you how to configure Material for MkDocs to create social cards for + your content. +* [Custom cards](social/custom.md) (xx min)<br/> + shows you how to design your own custom social cards. ## Tutorial structure From 4c16ada0dfe03ebee46d960bf9eef94748c328a0 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sun, 5 May 2024 18:03:34 +0200 Subject: [PATCH 13/29] + basic social cards tutorial --- docs/tutorials/social/basic.md | 196 +++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 docs/tutorials/social/basic.md diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md new file mode 100644 index 00000000000..00fb5f5c7ba --- /dev/null +++ b/docs/tutorials/social/basic.md @@ -0,0 +1,196 @@ +# Social cards tutorial + +Social cards are images that other systems such as social media can display as +a preview for content linked to. It is easy to get started with the social +plugin, true to the motto of Material with MkDocs: "batteries included." + +## Basics + +Before you start, there are just a couple of [dependencies to install]. These +are libraries for image processing that the plugin needs to produce the social +cards, as well as their Python bindings. + +[dependencies to install]: https://squidfunk.github.io/mkdocs-material/plugins/requirements/image-processing/ + +With those prerequisites met, it is simply a matter of activating the plugin, +which will: + +* produce the social cards as PNG images for each page in your site; +* create page meta data in the header that will provide social media systems + with key information and tell them how to find the social card image. + +!!! example "Add social cards" + + Simply add the social plugin to your list of plugins: + + ```yaml hl_lines="3" + plugins: + - search + - social + - ... + ``` + + Now, then you run `mkdocs build` and look at the `site` directory, you will + see that it contains subfolders under `assets/images/social` that reflect + the structure of your Markdown files. Each page has a corresponding PNG file + that contains the social card image. + + Have a look at the generated HTML and you will see the metadata produced in + the `head` element, including one entry that points to the image. + +## Background color + +The social plugin configuration options for changing aspects such as colors, +images, fonts, logos, the title, even the description. You can configure them +for all social cards in the `mkdocs.yml` and, in the Insiders Edition, they can +be overridden in the page header for individual pages. + +!!! example "Change the background color" + + To change the background color to an attention-grabbing hot pink, + you might add: + + ```yaml hl_lines="4-5" + plugins: + ... + - social: + cards_layout_options: + background_color: "#ff1493" + ``` + +## Logos + +By default, the plugin uses the logo that set for the whole site, either +through the `theme.logo` or the `theme.icon.logo` setting. You can set your +own logo specific for the social cards if you want this to be different. The +path used is relative to your project root and needs to point to an SVG file +or a pixel image of appropriate size and with transparent background. + +!!! tip "Question" + **@squidfunk**, not sure about the last sentence, what are the requirements? + +!!! example "Set your own logo" + + ```yaml hl_lines="3-4" + plugins: + - social: + cards_layout_options: + logo: docs/assets/images/ourlogo.png + ``` + +## Background images + +In addition to adding your own logo, the most impactful way to personalize your +social cards is to add a background image instead of the default solid color +background. Make sure you choose one that will contrast well with the other +elements of the card. + +!!! example "Add background image" + + ```yaml hl_lines="4 5" + plugins: + - social: + cards_layout_options: + background_image: layouts/background.png + background_color: transparent + ``` + +## Additional layouts and styles <!-- md:sponsors --> + +The Insiders Edition provides additional layouts as well as the option to +configure different styles for different (kinds of) pages. + +The Insiders Edition comes with a number of additional layouts for the social +cards. For example, the `default/variant` layout adds a page icon to the card. +You can use this to distinguish social cards visually, depending on what kind +of page you are sharing. + +For example, imagine you have a set of pages that advertise events and you want +to include a calendar icon as a visual indication that a card advertises an +event. In the following, you will set up a directory for event pages and use +the meta plugin to assign them a calendar icon. + +!!! example "Social cards for event pages" + + First, create a directory in your `docs` directory to hold the event pages: + + ``` + mkdir docs/events + ``` + + Then, add a file `.meta.yml` inside this new directory with settings for + the page icon and a hot pink background color that will stand out on + social media: + + ```yaml + --- + icon: material/calendar-plus + social: + cards_layout_options: + background_color: "#ff1493" + --- + ``` + + Now add a page within the `docs/events` directoy. It does not need to have + any special content, just a top level header. + + To turn on the `default/variant` layout in `mkdocs.yml`, add the + `cards_layout` option and also add the meta plugin: + + ```yaml + plugins: + - meta + - social: + cards_layout: default/variant + ``` + + After running `mkdocs build`, you can see that the social card at + `site/assets/images/social/events/index.png` features the page icon. + +Note that the icon will also appear next to the navigation element for the +page. If that is not what you want then you will need to modify the social +card template to gets its icons from another source. You can learn how to +do this in the [custom social cards tutorial](custom.md). + +## Per-page settings <!-- md:sponsors --> + +With the Insiders Edition, you can customize the card layout for each +page by adding settings to the page header. You have effectively done this +in the previous exercise, but using the meta plugin so simplify things. +Say that in addition to regular events you also have the odd webinar and +for this you want to set a different icon and also set the description to +indicate that the event is part of the webinar series. + +!!! example "Override card style in page header" + + Add the following to the top of the page in `docs/events` or create a new + one: + + ```yaml + --- + icon: material/web + social: + cards_layout_options: + description: Our Webinar Series + --- + ``` + +## Using include and exclude + +!!! tip "Question" + + **@suidfunk**, do you have a killer use case for the `card_include` + and `cards_exclude` options? I realize that what I did above with the + meta plugin could also be done using these. + +## What's next? + +With the Insiders Edition, you can also define custom layouts if the +configuration options introduced above as not enough to meet your needs. +Continue to the [custom social cards tutorial](custom.md) if you want to +find out how to do this. + +Social cards are particularly useful for blog posts. If you have a blog, +you need to do nothing more than to turn on both plugins to create social cards +to advertise your latest blog posts. If you do not have one yet but would like +to, why not check out the [blog tutorials](../index.md#blogs)? From 5291d417e78e7adfa265e66b9422c969b5e31859 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sun, 5 May 2024 19:24:22 +0200 Subject: [PATCH 14/29] + custom social card tutorial --- docs/tutorials/social/custom.md | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/tutorials/social/custom.md diff --git a/docs/tutorials/social/custom.md b/docs/tutorials/social/custom.md new file mode 100644 index 00000000000..5753b5780a1 --- /dev/null +++ b/docs/tutorials/social/custom.md @@ -0,0 +1,99 @@ +# Custom cards <!-- md:sponsors --> + +The Insiders Edition allows you to define custom layouts for your social cards +to suit your specific needs if the configuration options are not enough. +For example, you may want to include the date of an event on the social +card as well as a calendar icon to indicate that the card leads to an +event page when clicked on. + +!!! example "Custom layout for events <!-- md:sponsors -->" + + First, copy the default social card layout from your installation of Material + for MkDocs to a new directory `layouts`. The instructions below assume you + are in your project root and have a virtual environment within this. The + path on your machine, of course may differ. + + ``` + $ mkdir layouts + $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default.yml \ + layouts/event.yml + ``` + Have a look at the file contents. You will see that there are: + + * a number of definitions of content that is pulled from the site, + * definitions of tags that end up in the `meta` elements in the page header + of each page when it is generated, + * a specification that consists of a number of layers that are applied on + top of each other in the order in which they are defined. + + Before configuring the social cards, you need to tell the plugin where to + find them, so add the following to the plugin configuration in your + `mkdocs.yml`: + + ``` yaml hl_lines="2" + - social: + cards_layout_dir: layouts + ``` + + To include an event date and location, it makes sense to use information in + the page header, where you might also specify that your custom card layout + it to be used. Create a page with the following content: + + ```yaml + --- + tags: + - events + social: + cards_layout: event + event: + date: 2024-04-08 + location: Online + --- + + # Introduction to Material for MkDocs + ``` + + Given this data, we can add some code to the layout that pulls it out and + makes it available to be rendered later on. Add the following at the top + of the layout file: + + ```yaml hl_lines="2-99" + definitions: + - &event >- + {%- if 'event' in page.meta %} + {%- if 'date' in page.meta['event'] %} + {{ "%s - " | format(page.meta['event']['date'].strftime('%d %B %Y')) }} + {%- else -%} + Date is undefined! + {%- endif -%} + {%- if 'location' in page.meta['event'] -%} + {{ page.meta['event']['location'] }} + {%- else -%} + Location is undefined! + {%- endif -%} + {%- else -%} + No event data defined! + {%- endif -%} + ``` + + Now, add a new layer to the ones already present that renders the date and + location: + + ```yaml + - size: { width: 990, height: 50 } + offset: { x: 50, y: 360 } + typography: + content: *event + align: start + color: *color + ``` + +!!! tip "Debugging layout files" + + Should you find that your layouts are causing your MkDocs build to fail, + there are a number of things you can do: + + 1. Run Mkdocs with the `--verbose` option to get more detailed reporting. + 2. Comment out things you recently added or that you suspect are the cause + 3. Install the `jinja2` command-line tool with `pip install Jinja2` and + run it over your layout file, for example: `jinja2 event.yml`. \ No newline at end of file From 6a4957dea80f33f2e3274eb980fb0695a0c62804 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sun, 5 May 2024 19:25:07 +0200 Subject: [PATCH 15/29] + estimated time for custom card tutorial --- docs/tutorials/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index ca9e9c68a70..36c995b4c15 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -19,7 +19,7 @@ the wider MkDocs ecosystem. * [Basics](social/basic.md) (20 min) <br/> shows you how to configure Material for MkDocs to create social cards for your content. -* [Custom cards](social/custom.md) (xx min)<br/> +* [Custom cards](social/custom.md) (15 min)<br/> shows you how to design your own custom social cards. ## Tutorial structure @@ -58,6 +58,7 @@ Likewise, helpful tips and warnings appear in boxes of their own: ...and warnings like this! ## Prerequisites + The tutorials assumes that you have installed either the [public version] or the [Insiders edition] of Material for MkDocs and that you have worked through the [creating your site] setup guide. Note that where the features From 5b9f7209ee7099094d00e581257529a2abf2cf82 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Wed, 8 May 2024 20:44:45 +0200 Subject: [PATCH 16/29] added tutorial sections to nav --- mkdocs.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 314c5e5edd0..a79b73a50c6 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -192,7 +192,13 @@ nav: - Alternatives: alternatives.md - License: license.md - Tutorials: - - tutorials/index.md + - "Blogs": + - tutorials/blogs/basic.md + - tutorials/blogs/navigation.md + - tutorials/blogs/engage.md + - "Social cards": + - tutorials/social/basic.md + - tutorials/social/custom.md - Changelog: - changelog/index.md - How to upgrade: upgrade.md From a41c36be6ff502f0685b35a6de193b61351e9bfb Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Wed, 8 May 2024 20:52:02 +0200 Subject: [PATCH 17/29] fixed typos, removed sponsor icon from level one heading --- docs/tutorials/social/custom.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/social/custom.md b/docs/tutorials/social/custom.md index 5753b5780a1..526c55ad59f 100644 --- a/docs/tutorials/social/custom.md +++ b/docs/tutorials/social/custom.md @@ -1,4 +1,4 @@ -# Custom cards <!-- md:sponsors --> +# Custom cards The Insiders Edition allows you to define custom layouts for your social cards to suit your specific needs if the configuration options are not enough. @@ -11,7 +11,7 @@ event page when clicked on. First, copy the default social card layout from your installation of Material for MkDocs to a new directory `layouts`. The instructions below assume you are in your project root and have a virtual environment within this. The - path on your machine, of course may differ. + path on your machine, of course, may differ. ``` $ mkdir layouts @@ -37,7 +37,7 @@ event page when clicked on. To include an event date and location, it makes sense to use information in the page header, where you might also specify that your custom card layout - it to be used. Create a page with the following content: + is to be used. Create a page with the following content: ```yaml --- From fa7540180c430b88b623bf68f9b8d4a7941aa94a Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Wed, 8 May 2024 20:53:58 +0200 Subject: [PATCH 18/29] removed "tutorial" from level one heading --- docs/tutorials/blogs/basic.md | 2 +- docs/tutorials/blogs/navigation.md | 2 +- docs/tutorials/social/basic.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/blogs/basic.md b/docs/tutorials/blogs/basic.md index ec039165eff..8a6feb74b31 100644 --- a/docs/tutorials/blogs/basic.md +++ b/docs/tutorials/blogs/basic.md @@ -1,4 +1,4 @@ -# Blog tutorial +# 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 diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index 6a26e89bdfc..bfdccb98a33 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -1,4 +1,4 @@ -# Navigation, authors, and pagination tutorial +# Navigation, authors, and pagination The Blog plugin provides blog-style navigation with a reverse-chronological index page and an archive organized by year by default. This tutorial shows diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index 00fb5f5c7ba..131f0331ba6 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -1,4 +1,4 @@ -# Social cards tutorial +# Basic social cards Social cards are images that other systems such as social media can display as a preview for content linked to. It is easy to get started with the social From 1bff14dc5cb0786551031a19cb32928d0375867b Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sat, 11 May 2024 07:26:41 -0400 Subject: [PATCH 19/29] added headings to custom layout example --- docs/tutorials/social/custom.md | 94 ++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 25 deletions(-) diff --git a/docs/tutorials/social/custom.md b/docs/tutorials/social/custom.md index 526c55ad59f..0d8c9dc7eee 100644 --- a/docs/tutorials/social/custom.md +++ b/docs/tutorials/social/custom.md @@ -6,9 +6,15 @@ For example, you may want to include the date of an event on the social card as well as a calendar icon to indicate that the card leads to an event page when clicked on. -!!! example "Custom layout for events <!-- md:sponsors -->" +## Setup - First, copy the default social card layout from your installation of Material +You can either design a custom layout from scratch or use an existing layout +as the basis that you add to or otherwise modify. In this tutorial, you will +use the default layout as the basis. + +!!! example "Copy default layout to customize <!-- md:sponsors -->" + + Copy the default social card layout from your installation of Material for MkDocs to a new directory `layouts`. The instructions below assume you are in your project root and have a virtual environment within this. The path on your machine, of course, may differ. @@ -18,31 +24,40 @@ event page when clicked on. $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default.yml \ layouts/event.yml ``` - Have a look at the file contents. You will see that there are: - * a number of definitions of content that is pulled from the site, - * definitions of tags that end up in the `meta` elements in the page header - of each page when it is generated, - * a specification that consists of a number of layers that are applied on - top of each other in the order in which they are defined. + Before customizing the social cards, you need to tell the plugin where to + find them as well as tell MkDocs to watch for any changes. Add the following + to the plugin configuration in your `mkdocs.yml`: - Before configuring the social cards, you need to tell the plugin where to - find them, so add the following to the plugin configuration in your - `mkdocs.yml`: + ``` yaml hl_lines="2-6" + plugins: + - social: + cards_layout_dir: layouts - ``` yaml hl_lines="2" - - social: - cards_layout_dir: layouts + watch: + - layouts ``` - To include an event date and location, it makes sense to use information in - the page header, where you might also specify that your custom card layout - is to be used. Create a page with the following content: +Have a look at the contents of `event.yml`. You will see that there are: + +* a number of definitions of content pulled from the site, +* definitions of tags that end up in the `meta` elements in the page header + of each page, +* a specification that consists of a number of layers that are applied on + top of each other in the order in which they are defined. + +## Define page metadata + +In the following, you will add an event date and location to the social card. +As each event will have its own date and location, it makes sense to define +these in the page header and then of this information in the custom layout. + +!!! example "Defining the event data <!-- md:sponsors -->" + + Create a page with the following content: ```yaml --- - tags: - - events social: cards_layout: event event: @@ -53,9 +68,16 @@ event page when clicked on. # Introduction to Material for MkDocs ``` - Given this data, we can add some code to the layout that pulls it out and - makes it available to be rendered later on. Add the following at the top - of the layout file: +## Extract page metadata + +With the data defined in the page header, you can now add code to the layout +that pulls it out and makes it available to render later on. This is to separate +the data manipulation from the actually layout instructions and so make the +layout file easier to read. + +!!! example "Adding data definitions" + + Add the following at the top of the layout file: ```yaml hl_lines="2-99" definitions: @@ -76,8 +98,19 @@ event page when clicked on. {%- endif -%} ``` - Now, add a new layer to the ones already present that renders the date and - location: +The code presented here checks whether the page header contains the necessary +entries and spits out a message to the social card if not. Unfortunately, there +is no straightforward way to raise an exception or log an error, so the messages +merely appear in the social card produced. + +## Add event data layer + +The next step is to use these data definitions in a new layer and add it to the +ones already present. + +!!! example "Render date and location" + + Finally, add the following to the layout template: ```yaml - size: { width: 990, height: 50 } @@ -88,6 +121,9 @@ event page when clicked on. color: *color ``` +You should now see the social plugin use the custom layout on the event page +you set up. + !!! tip "Debugging layout files" Should you find that your layouts are causing your MkDocs build to fail, @@ -96,4 +132,12 @@ event page when clicked on. 1. Run Mkdocs with the `--verbose` option to get more detailed reporting. 2. Comment out things you recently added or that you suspect are the cause 3. Install the `jinja2` command-line tool with `pip install Jinja2` and - run it over your layout file, for example: `jinja2 event.yml`. \ No newline at end of file + run it over your layout file, for example: `jinja2 event.yml`. + +## What's next? + +If you do not have a blog yet, why not check out the +[blog tutorials](../index.md#blogs) and learn how to set one up? The social +plugin will help you draw attention to your posts on social media. + +Check out the [other tutorials](../index.md) we have prepared for you. \ No newline at end of file From 66debda26ec2520b6c9d968ac71f6b4066a54379 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Tue, 14 May 2024 13:40:11 -0400 Subject: [PATCH 20/29] fixed broken link --- docs/tutorials/blogs/engage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md index 56b24f4247e..8cb3691e540 100644 --- a/docs/tutorials/blogs/engage.md +++ b/docs/tutorials/blogs/engage.md @@ -354,4 +354,4 @@ look at the [social plugin tutorial] to generate social cards for your blog posts that get displayed when you post links to social media systems. [blog plugin reference]: https://squidfunk.github.io/mkdocs-material/plugins/blog/ -[social plugin tutorial]: ../social.md +[social plugin tutorial]: ../social/basic.md From 69501b225b0a658aa61573db31a296ccd2049df4 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Thu, 16 May 2024 20:46:45 -0400 Subject: [PATCH 21/29] fixes after run-through, added links to template repos --- docs/tutorials/blogs/basic.md | 56 ++++++++--------- docs/tutorials/blogs/engage.md | 48 +++++++++------ docs/tutorials/blogs/navigation.md | 37 ++++++++---- docs/tutorials/index.md | 96 +++++++++++------------------- mkdocs.yml | 1 + 5 files changed, 116 insertions(+), 122 deletions(-) diff --git a/docs/tutorials/blogs/basic.md b/docs/tutorials/blogs/basic.md index 8a6feb74b31..16bf7c46bd6 100644 --- a/docs/tutorials/blogs/basic.md +++ b/docs/tutorials/blogs/basic.md @@ -11,9 +11,9 @@ 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. -This tutorial guides you through the process of configuring the -[blog plugin], setting up your blog, creating posts, and defining -post metadata. +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. [blog plugin]: ../../plugins/blog.md @@ -22,12 +22,12 @@ __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 shows the posts in reverse chronological order, with +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 +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, @@ -36,8 +36,8 @@ 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 a given number of posts -and an _archive_ section allows access to older posts, organized by year. +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. @@ -97,7 +97,8 @@ that the index page shows. ``` --- - date: 2023-12-31 + date: + created: 2023-12-31 --- # Happy new years eve! @@ -144,7 +145,8 @@ header to indicate that a post is still in draft form. ```hl_lines="3" --- - date: 2024-01-01 + date: + created: 2024-01-01 draft: true --- @@ -187,11 +189,10 @@ Meta plugin later on. ### Edits -Sometimes, bloggers need to update a post. This might happen when they have made -a mistake or when something changes they need to reflect in the post. To +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. Note that this means that you need to move the original publication date -to a `created` attribute of the `date` entry. +header. !!! example "Editing a post" @@ -241,8 +242,9 @@ attribute in the page header: ```hl_lines="5" --- - date: 2023-12-31 - updated: 2024-01-02 + date: + created: 2023-12-31 + updated: 2024-01-02 readtime: 15 pin: true --- @@ -264,9 +266,10 @@ header: Add the following to a blog post: - ``` hl_lines="4-6" + ``` hl_lines="5-7" --- - date: 2023-12-31 + date: + created: 2023-12-31 ... links: - index.md @@ -286,9 +289,10 @@ subsections: Change the link section to override the page titles: - ```hl_lines="5-7" + ```hl_lines="6-9" --- - date: 2023-12-31 + date: + created: 2023-12-31 ... links: - Homepage: index.md @@ -298,17 +302,9 @@ subsections: --- ``` -As you can see, the plugin renders subsections in the left sidebar on screens -that are wide enough, and in a way similar to mobile navigation menus on -more narrow screens. - - - -<!-- TODO -If you look closely, you'll realize that you can even use an anchor to link to a specific section of a document, extending the possibilities of the nav syntax in mkdocs.yml. The built-in blog plugin resolves the anchor and sets the title of the anchor as a subtitle of the related link. - -Note that all links must be relative to docs_dir, as is also the case for the nav setting. ---> +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 <!-- md:sponsors --> diff --git a/docs/tutorials/blogs/engage.md b/docs/tutorials/blogs/engage.md index 8cb3691e540..8f23b48c3d2 100644 --- a/docs/tutorials/blogs/engage.md +++ b/docs/tutorials/blogs/engage.md @@ -7,6 +7,8 @@ your posts, you may want to integrate an analytics system. You may also want to post on social media when you public a new blog post. This tutorial gives you a leg up on all of these topics. +__Time required:__ typically 30 minutes + ## RSS feeds An _RSS feed_ allows users to subscribe to a blog so that they get notified when @@ -36,18 +38,20 @@ Since it is a third-party plugin, you need to install it before using it. [instructed in the basic blog tutorial]: basic.md#setting-up-your-blog - Now, configure the plugin in the `mkdocs.yml`: + Now, configure the plugin in the `mkdocs.yml`. The options provided restrict + the pages that RSS entries are created for to the blog posts, which is + probably what you want. Also note the configuration of the date fields to + match the format that Material for MkDocs uses to accommodate both a + creation date and a date for updates. ```yaml hl_lines="9" plugins: - - search - - blog: - authors_profiles: true - categories_allowed: - - Holidays - - News - - tags - - rss + - ... + - rss: + match_path: "blog/posts/.*" + date_from_meta: + as_creation: date.created + as_update: date.updated ``` Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS @@ -64,8 +68,8 @@ Since it is a third-party plugin, you need to install it before using it. will need to deploy your project somewhere that is accessible to them. This minimal configuration should work well if you have not made any changes -to the default configuration of the blog plugin. For more information on -adapting the feed to your needs, see [the RSS plugin's documentation]. +to the default configuration of the blog plugin. For more information on adapting +the feed to your needs, see [the RSS plugin's documentation]. [the RSS plugin's documentation]: https://guts.github.io/mkdocs-rss-plugin/ @@ -112,7 +116,7 @@ necessary links and define the icons to use. link: mailto:<email-address> ``` - Finally, you can specify a URL within your side, such as to your contact + Finally, you can specify a URL within your site, such as to your contact page. It is possible to specify only the path to the page: ```yaml @@ -138,11 +142,10 @@ more involved, which is why there are companies offering components for this. duties as a provider to ensure that processing occurs only once the user has granted consent. -The implementation of share buttons deliberately does not use third party code -to practice data minimization. It supports sharing to Twitter/X and -Facebook without causing a data flow to these companies whenever someone views -the pages. Only when someone clicks a share button will there be interactions -with those companies' servers. +This implementation of share buttons deliberately does not use third party code. +It supports sharing to Twitter/X and Facebook without causing a data flow to +these companies whenever someone views the pages. Only when someone clicks a +share button will there be interactions with those companies' servers. !!! example "Add share buttons" @@ -184,7 +187,16 @@ with those companies' servers. ``` The hook first checks if the current page is a blog post and then appends - Markdown code for the share buttons. + Markdown code for the share buttons. The buttons use icons, so you also need + to configure the following markdown extensions: + + ```yaml + markdown_extensions: + - attr_list + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + ``` ## Add a discussion system diff --git a/docs/tutorials/blogs/navigation.md b/docs/tutorials/blogs/navigation.md index bfdccb98a33..4634ca250b8 100644 --- a/docs/tutorials/blogs/navigation.md +++ b/docs/tutorials/blogs/navigation.md @@ -7,6 +7,7 @@ add more navigation options using categories and the [Tags plugin]. [Tags plugin]: ../../plugins/tags.md +__Time required:__ typically 30 minutes ## Integrating navigation @@ -156,7 +157,7 @@ of the navigation hierarchy. [Tags plugin]: https://squidfunk.github.io/mkdocs-material/plugins/tags/ -You may have a tutorial like this one as well a more comprehensive setup guide +You may have a tutorial like this one as well as a more comprehensive setup guide and reference documentation. Adding the same tag to all three shows that they are related. As you will see, it is possible to navigate from a tagged page to the tag index and, from there, to other pages that carry the same tag. @@ -178,10 +179,11 @@ the tag index and, from there, to other pages that carry the same tag. Once this is done, you can add tags to posts in the page header: - ``` hl_lines="8-11"" + ``` hl_lines="9-12"" --- - date: 2023-12-31 - updated: 2024-01-02 + date: + created: 2023-12-31 + updated: 2024-01-02 authors: - material categories: @@ -265,7 +267,16 @@ indexes, scoped listings, shadow tags, nested tags, and much more. ``` You now have two index pages: one covers the whole site and one - covers only the blog. + covers only the blog. Add both to the navigation: + + ```yaml + nav: + - Home: index.md + - Tags: tags.md + - Blog: + - blog/index.md + - blog/tags.md + ``` The tags plugin in the Insider Edition is an incredibly powerful tool and we can only scratch the surface of what is possible with it. If you @@ -300,10 +311,11 @@ the page header. and then add a line to the header of the first post: - ```hl_lines="4-5" + ```hl_lines="5-6" --- - date: 2023-12-31 - updated: 2024-01-02 + date: + created: 2023-12-31 + updated: 2024-01-02 authors: - team --- @@ -462,7 +474,7 @@ can manually define a slug for a specific post. return functools.partial(_make_slug_short, **kwargs) return functools.partial(_make_slug, **kwargs) ``` - Save this code in `ext/slugs.py` and also add an (empty) `__init__.py`` + Save this code in `ext/slugs.py` and also add an (empty) `__init__.py` file to indicate that the directory is a module. Now you can configure your custom slugify code like this: @@ -489,10 +501,11 @@ be tedious. If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat lengthy 'happy-new-years-eve', you could add the following: - ```hl_lines="6" + ```hl_lines="7" --- - date: 2023-12-31 - updated: 2024-01-02 + date: + created: 2023-12-31 + updated: 2024-01-02 readtime: 15 pin: true slug: ny-eve diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index 36c995b4c15..2d52aae06c5 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -6,14 +6,45 @@ the getting started guides or the reference documentation, the tutorials show the breadth of features available in Material for MkDocs but also within the wider MkDocs ecosystem. -<!-- TODO: add links to template repos --> +The tutorials guide you through worked examples, so by following them you should +gain not only an understanding of how to use Material for MkDocs, but also +a template for your own projects. For convenience, these templates are also +available as template repositories on GitHub. + +The tutorials assume that you have installed either the [public version] or the +[Insiders edition] of Material for MkDocs and that you have worked through the +[creating your site] setup guide. + +Note that where the features we use require the Insiders edition, we mark these +with the heart icon: <!-- md:sponsors --> If you are using the public version +then you can skip these steps. Sometimes there will be ways of achieving the +same goal that differ between the public version and the Insider edition. In +that case, we will show them in a tabbed view so you can see one or the other. + +[public version]: ../getting-started.md +[Insiders edition]: ../insiders/getting-started.md +[creating your site]: ../creating-your-site.md + +!!! note "Feedback wanted!" + The tutorials are a recent addition to our documentation and we are still + working out what shape they should have in the end. Please contact us if you + want to provide feedback. <!--- TODO: how? --> + + Note, however, that suggestions should be specific and feasible. We want to + focus on creating more content at the moment, instead of developing a + specific styling or behaviour for the tutorials. If there are worthwhile + improvements that we can make through simple customization then we are happy + to consider those. + ## Blogs * [Basics](blogs/basic.md) (20 min) <br/> covers the basics of setting up a blog, including post metadata. * [Navigation, pagination, multiple authors](blogs/navigation.md) (30 min)<br/> describes how to make it easier for your readers to find content. * [Engagement and dissemination](blogs/engage.md) (30 min)<br/> - walks you through ways of increasing engagement with your content + walks you through ways of increasing engagement with your content. + +[:octicons-repo-template-24: Template Repository](https://github.com/mkdocs-material/create-blog) ## Social cards * [Basics](social/basic.md) (20 min) <br/> @@ -22,63 +53,4 @@ the wider MkDocs ecosystem. * [Custom cards](social/custom.md) (15 min)<br/> shows you how to design your own custom social cards. -## Tutorial structure - -The tutorials guide you through worked examples, so following them you should -gain not only an understanding of how to use Material for MkDocs, but also -a template for your own projects. For convenience, these templates are also -available as template repositories on GitHub. - -Each tutorial is a single page, so use the Table of Contents navigation to move -between steps. They start by mentioning prerequisites, giving an -overview of the content as well as describing the outcomes. - -### Instructions - -Tutorials contain a mix of explanation, demonstrations, and instructions that you -should follow as you work your way through the individual steps. Those instructions -come in the form of admonitions to separate them from the rest of the -tutorial: - -!!! example "Instructions to follow" - - Whenever you see a box like this you know it is time to get hands on and - apply material just covered. - -### Tips and warnings - -Likewise, helpful tips and warnings appear in boxes of their own: - -!!! tip "A hot tip!" - - Tips look like this... - -!!! warning "Warning!" - - ...and warnings like this! - -## Prerequisites - -The tutorials assumes that you have installed either the -[public version] or the [Insiders edition] of Material for MkDocs and that you have -worked through the [creating your site] setup guide. Note that where the features -we use the Insiders edition, we mark these with the heart icon: -<!-- md:sponsors --> If you are using the public version then you can skip these -steps. Sometimes there will be ways of achieving the same goal that differ -between the public version and the Insider edition. In that case, we will show -them in a tabbed view so you can see one or the other. - -[public version]: ../getting-started.md -[Insiders edition]: ../insiders/getting-started.md -[creating your site]: ../creating-your-site.md - -## Feedback wanted - -The tutorials are a recent addition to our documentation and we are still -working out what shape they should have in the end. Please contact us if you -want to provide feedback. <!--- TODO: how? --> - -Note, however, that suggestions should be specific and feasible. We want to -focus on creating more content at the moment, instead of developing a specific -styling or behaviour for the tutorials. If there are worthwhile improvements -that we can make through simple customization then we are happy to consider those. +[:octicons-repo-template-24: Template Repository](https://github.com/mkdocs-material/create-social-cards) diff --git a/mkdocs.yml b/mkdocs.yml index a79b73a50c6..1224a2a1076 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -192,6 +192,7 @@ nav: - Alternatives: alternatives.md - License: license.md - Tutorials: + - tutorials/index.md - "Blogs": - tutorials/blogs/basic.md - tutorials/blogs/navigation.md From fc26e52179fd56f9852f400ecdb8fe2e900511ef Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Thu, 16 May 2024 22:09:34 -0400 Subject: [PATCH 22/29] added comment for @squidfunk --- docs/tutorials/social/basic.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index 131f0331ba6..213adab578e 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -181,7 +181,8 @@ indicate that the event is part of the webinar series. **@suidfunk**, do you have a killer use case for the `card_include` and `cards_exclude` options? I realize that what I did above with the - meta plugin could also be done using these. + meta plugin could also be done using these. It would be good to show + both but not using the same example. ## What's next? From 3c9c6519b4646175ecbbaf68b93d11f0271d7312 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sun, 26 May 2024 17:31:16 -0400 Subject: [PATCH 23/29] clarified use of logos, some proof-reading --- docs/tutorials/social/basic.md | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index 213adab578e..77f8d038021 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -16,8 +16,9 @@ With those prerequisites met, it is simply a matter of activating the plugin, which will: * produce the social cards as PNG images for each page in your site; -* create page meta data in the header that will provide social media systems - with key information and tell them how to find the social card image. +* create meta data in the headers of your site's pages that will provide + social media systems with key information and tell them how to find the + social card image. !!! example "Add social cards" @@ -30,17 +31,17 @@ which will: - ... ``` - Now, then you run `mkdocs build` and look at the `site` directory, you will - see that it contains subfolders under `assets/images/social` that reflect - the structure of your Markdown files. Each page has a corresponding PNG file - that contains the social card image. +Now, then you run `mkdocs build` and look at the `site` directory, you will +see that it contains subfolders under `assets/images/social` that reflect +the structure of your Markdown files. Each page has a corresponding PNG file +that contains the social card image. - Have a look at the generated HTML and you will see the metadata produced in - the `head` element, including one entry that points to the image. +Have a look at the generated HTML and you will see the metadata produced in +the `head` element, including one entry that points to the image. ## Background color -The social plugin configuration options for changing aspects such as colors, +The social plugin has configuration options for changing aspects such as colors, images, fonts, logos, the title, even the description. You can configure them for all social cards in the `mkdocs.yml` and, in the Insiders Edition, they can be overridden in the page header for individual pages. @@ -60,14 +61,15 @@ be overridden in the page header for individual pages. ## Logos -By default, the plugin uses the logo that set for the whole site, either -through the `theme.logo` or the `theme.icon.logo` setting. You can set your -own logo specific for the social cards if you want this to be different. The -path used is relative to your project root and needs to point to an SVG file -or a pixel image of appropriate size and with transparent background. +By default, the plugin uses the logo that you set for the whole site, either +through the `theme.logo` or the `theme.icon.logo` setting. The difference +between the two is that the `theme.icon.logo` version will directly embed the +logo's SVG code into the HTML, allowing it to inherit CSS color settings. When +you use `theme.logo`, the Material includes the logo as an image. -!!! tip "Question" - **@squidfunk**, not sure about the last sentence, what are the requirements? +You can set your own logo specific for the social cards as well. The path used +is relative to your project root and needs to point to an SVG file or a pixel +image. It should be rectangular and have a transparent background. !!! example "Set your own logo" From da76ed7d53e436a0a8ba17e6fea1257c2cf76207 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Sun, 26 May 2024 17:40:05 -0400 Subject: [PATCH 24/29] removed question I left for @squidfunk --- docs/tutorials/social/basic.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index 77f8d038021..01b5c564dbe 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -177,15 +177,6 @@ indicate that the event is part of the webinar series. --- ``` -## Using include and exclude - -!!! tip "Question" - - **@suidfunk**, do you have a killer use case for the `card_include` - and `cards_exclude` options? I realize that what I did above with the - meta plugin could also be done using these. It would be good to show - both but not using the same example. - ## What's next? With the Insiders Edition, you can also define custom layouts if the From b77de62ff7df5b7ec632d00bdfabbe8dc064291c Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Mon, 27 May 2024 16:27:52 -0400 Subject: [PATCH 25/29] clarified relationship between background color and image --- docs/tutorials/social/basic.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index 01b5c564dbe..d616b22f77f 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -87,6 +87,10 @@ social cards is to add a background image instead of the default solid color background. Make sure you choose one that will contrast well with the other elements of the card. +Also, the background color gets rendered *on top of* the background image, +allowing you to use a transparent color to tint an image. To use just the image, +use the color value `transparent`. + !!! example "Add background image" ```yaml hl_lines="4 5" @@ -97,6 +101,11 @@ elements of the card. background_color: transparent ``` +The path to the background image is resolved from the root of your project, +so this is where you should make the `layouts` directory and place the +background image. The default site of the social cards included with the plugin +is 1200x630 pixels, so choose an image that size or one that scales well to it. + ## Additional layouts and styles <!-- md:sponsors --> The Insiders Edition provides additional layouts as well as the option to From c971fd3955ebb24d94b378f1e172d479f2fced2a Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Mon, 27 May 2024 21:41:45 -0400 Subject: [PATCH 26/29] added override for the background image --- docs/tutorials/social/basic.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index d616b22f77f..e9dc9957d28 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -126,18 +126,20 @@ the meta plugin to assign them a calendar icon. First, create a directory in your `docs` directory to hold the event pages: ``` - mkdir docs/events + $ mkdir docs/events ``` Then, add a file `.meta.yml` inside this new directory with settings for the page icon and a hot pink background color that will stand out on - social media: + social media. Note that you can override the background image by setting it + to `null` here since it is not visible anyway because of the opaque coloring. ```yaml --- icon: material/calendar-plus social: cards_layout_options: + background_image: null background_color: "#ff1493" --- ``` From 4d0b869001c5f4b50bc7d56533fe6d618345a0fe Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Mon, 27 May 2024 21:51:42 -0400 Subject: [PATCH 27/29] fixed wording and indentation --- docs/tutorials/social/basic.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/social/basic.md b/docs/tutorials/social/basic.md index e9dc9957d28..57b83278741 100644 --- a/docs/tutorials/social/basic.md +++ b/docs/tutorials/social/basic.md @@ -169,7 +169,9 @@ do this in the [custom social cards tutorial](custom.md). With the Insiders Edition, you can customize the card layout for each page by adding settings to the page header. You have effectively done this -in the previous exercise, but using the meta plugin so simplify things. +in the previous exercise, but using the meta plugin to affect a whole set of +pages. + Say that in addition to regular events you also have the odd webinar and for this you want to set a different icon and also set the description to indicate that the event is part of the webinar series. @@ -183,7 +185,7 @@ indicate that the event is part of the webinar series. --- icon: material/web social: - cards_layout_options: + cards_layout_options: description: Our Webinar Series --- ``` From 9f9299e8492039e3e7dce48b2ca3e0dcba845d74 Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Mon, 27 May 2024 22:48:33 -0400 Subject: [PATCH 28/29] changed example to be releases, not events --- docs/tutorials/social/custom.md | 77 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/docs/tutorials/social/custom.md b/docs/tutorials/social/custom.md index 0d8c9dc7eee..639578e75a8 100644 --- a/docs/tutorials/social/custom.md +++ b/docs/tutorials/social/custom.md @@ -2,9 +2,9 @@ The Insiders Edition allows you to define custom layouts for your social cards to suit your specific needs if the configuration options are not enough. -For example, you may want to include the date of an event on the social -card as well as a calendar icon to indicate that the card leads to an -event page when clicked on. +For example, you may want to define a social card to advertise a new release +of your product. It should have an icon indicating a launch announcement as +well as the version number of the release on the card. ## Setup @@ -21,8 +21,8 @@ use the default layout as the basis. ``` $ mkdir layouts - $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default.yml \ - layouts/event.yml + $ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default/variant.yml \ + layouts/release.yml ``` Before customizing the social cards, you need to tell the plugin where to @@ -38,63 +38,56 @@ use the default layout as the basis. - layouts ``` -Have a look at the contents of `event.yml`. You will see that there are: +Have a look at the contents of `release.yml`. You will see that there are: * a number of definitions of content pulled from the site, * definitions of tags that end up in the `meta` elements in the page header of each page, -* a specification that consists of a number of layers that are applied on - top of each other in the order in which they are defined. +* a specification that consists of a number of layers that the social plugin + applies on top of each other in the order in which they are defined. ## Define page metadata -In the following, you will add an event date and location to the social card. -As each event will have its own date and location, it makes sense to define -these in the page header and then of this information in the custom layout. +In the following, you will add a version number to the social card. This +assumes you have a changelog page with information about each release. +Add the version number of the latest version to the page header (so it does +not need to be parsed out of the Markdown content): -!!! example "Defining the event data <!-- md:sponsors -->" +!!! example "Defining the release data <!-- md:sponsors -->" - Create a page with the following content: + Create a page `docs/changelog.md` with the following content: ```yaml --- + icon: material/rocket-launch-outline social: - cards_layout: event - event: - date: 2024-04-08 - location: Online + cards_layout: release + cards_layout_options: + title: New release! + latest: 1.2.3 --- - # Introduction to Material for MkDocs + # Releases ``` ## Extract page metadata With the data defined in the page header, you can now add code to the layout that pulls it out and makes it available to render later on. This is to separate -the data manipulation from the actually layout instructions and so make the +the data manipulation from the actual layout instructions and so make the layout file easier to read. !!! example "Adding data definitions" Add the following at the top of the layout file: - ```yaml hl_lines="2-99" + ```yaml hl_lines="2-9" definitions: - - &event >- - {%- if 'event' in page.meta %} - {%- if 'date' in page.meta['event'] %} - {{ "%s - " | format(page.meta['event']['date'].strftime('%d %B %Y')) }} - {%- else -%} - Date is undefined! - {%- endif -%} - {%- if 'location' in page.meta['event'] -%} - {{ page.meta['event']['location'] }} - {%- else -%} - Location is undefined! - {%- endif -%} + - &latest >- + {%- if 'latest' in page.meta %} + {{ page.meta['latest']}} {%- else -%} - No event data defined! + No release version data defined! {%- endif -%} ``` @@ -103,12 +96,12 @@ entries and spits out a message to the social card if not. Unfortunately, there is no straightforward way to raise an exception or log an error, so the messages merely appear in the social card produced. -## Add event data layer +## Add release version layer The next step is to use these data definitions in a new layer and add it to the ones already present. -!!! example "Render date and location" +!!! example "Render release version" Finally, add the following to the layout template: @@ -116,14 +109,20 @@ ones already present. - size: { width: 990, height: 50 } offset: { x: 50, y: 360 } typography: - content: *event - align: start - color: *color + content: *latest + align: start + color: *color ``` -You should now see the social plugin use the custom layout on the event page +You should now see the social plugin use the custom layout on the changelog page you set up. +## Adjust layout + +Finally, the rocket icon used for the changelog page is not quite in the right +position. Find the please where the `page_icon` variable is used to create the +page icon layer and adjust the horizontal position to 600 instead of 800. + !!! tip "Debugging layout files" Should you find that your layouts are causing your MkDocs build to fail, From 25458725dd383226694783a1adf8b229dfd1a1ba Mon Sep 17 00:00:00 2001 From: Alex Voss <alex@corealisation.com> Date: Mon, 27 May 2024 22:52:53 -0400 Subject: [PATCH 29/29] being more specific where to add the last bit of code in the layout --- docs/tutorials/social/custom.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/social/custom.md b/docs/tutorials/social/custom.md index 639578e75a8..fdc08d26f2f 100644 --- a/docs/tutorials/social/custom.md +++ b/docs/tutorials/social/custom.md @@ -103,7 +103,7 @@ ones already present. !!! example "Render release version" - Finally, add the following to the layout template: + Finally, add the following to end of the custom layout: ```yaml - size: { width: 990, height: 50 }