mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 02:08:36 +02:00
* feat(content-blog): allow authors list to contain images only * adjust styles * fix * fix * mention in docs * fix wording
603 lines
15 KiB
Text
603 lines
15 KiB
Text
---
|
|
id: blog
|
|
title: Blog
|
|
---
|
|
|
|
import Tabs from '@theme/Tabs';
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
The blog feature enables you to deploy in no time a full-featured blog.
|
|
|
|
:::info
|
|
|
|
Check the [Blog Plugin API Reference documentation](./api/plugins/plugin-content-blog.md) for an exhaustive list of options.
|
|
|
|
:::
|
|
|
|
## Initial setup {#initial-setup}
|
|
|
|
To set up your site's blog, start by creating a `blog` directory.
|
|
|
|
Then, add an item link to your blog within `docusaurus.config.js`:
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
themeConfig: {
|
|
// ...
|
|
navbar: {
|
|
items: [
|
|
// ...
|
|
// highlight-next-line
|
|
{to: 'blog', label: 'Blog', position: 'left'}, // or position: 'right'
|
|
],
|
|
},
|
|
},
|
|
};
|
|
```
|
|
|
|
## Adding posts {#adding-posts}
|
|
|
|
To publish in the blog, create a Markdown file within the blog directory.
|
|
|
|
For example, create a file at `website/blog/2019-09-05-hello-docusaurus-v2.md`:
|
|
|
|
```md title="website/blog/2019-09-05-hello-docusaurus-v2.md"
|
|
---
|
|
title: Welcome Docusaurus v2
|
|
description: This is my first post on Docusaurus 2.
|
|
slug: welcome-docusaurus-v2
|
|
authors:
|
|
- name: Joel Marcey
|
|
title: Co-creator of Docusaurus 1
|
|
url: https://github.com/JoelMarcey
|
|
image_url: https://github.com/JoelMarcey.png
|
|
- name: Sébastien Lorber
|
|
title: Docusaurus maintainer
|
|
url: https://sebastienlorber.com
|
|
image_url: https://github.com/slorber.png
|
|
tags: [hello, docusaurus-v2]
|
|
image: https://i.imgur.com/mErPwqL.png
|
|
hide_table_of_contents: false
|
|
---
|
|
|
|
Welcome to this blog. This blog is created with [**Docusaurus 2**](https://docusaurus.io/).
|
|
|
|
<!--truncate-->
|
|
|
|
This is my first post on Docusaurus 2.
|
|
|
|
A whole bunch of exploration to follow.
|
|
```
|
|
|
|
:::note
|
|
|
|
Docusaurus will extract a `YYYY-MM-DD` date from a file/folder name such as `YYYY-MM-DD-my-blog-post-title.md`.
|
|
|
|
This naming convention is optional, and you can provide the date as front matter.
|
|
|
|
<details>
|
|
<summary>Example supported patterns</summary>
|
|
|
|
| Pattern | Example |
|
|
| --- | --- |
|
|
| Single file | `2021-05-28-my-blog-post-title.md` |
|
|
| MDX file | `2021-05-28-my-blog-post-title.mdx` |
|
|
| Single folder + `index.md` | `2021-05-28-my-blog-post-title/index.md` |
|
|
| Folder named by date | `2021-05-28/my-blog-post-title.md` |
|
|
| Nested folders by date | `2021/05/28/my-blog-post-title.md` |
|
|
| Partially nested folders by date | `2021/05-28-my-blog-post-title.md` |
|
|
| Nested folders + `index.md` | `2021/05/28/my-blog-post-title/index.md` |
|
|
| Date in the middle of path | `category/2021/05-28-my-blog-post-title.md` |
|
|
|
|
The date will be excised from the path and appended to the beginning of the URL slug.
|
|
|
|
</details>
|
|
|
|
:::
|
|
|
|
:::tip
|
|
|
|
Using a folder can be convenient to co-locate blog post images alongside the Markdown file.
|
|
|
|
:::
|
|
|
|
The only required field in the front matter is `title`; however, we provide options to add more metadata to your blog post, for example, author information. For all possible fields, see [the API documentation](api/plugins/plugin-content-blog.md#markdown-frontmatter).
|
|
|
|
## Blog list {#blog-list}
|
|
|
|
The blog's index page (by default, it is at `/blog`) is the _blog list page_, where all blog posts are collectively displayed.
|
|
|
|
Use the `<!--truncate-->` marker in your blog post to represent what will be shown as the summary when viewing all published blog posts. Anything above `<!--truncate-->` will be part of the summary. For example:
|
|
|
|
```md
|
|
---
|
|
title: Truncation Example
|
|
---
|
|
|
|
All these will be part of the blog post summary.
|
|
|
|
Even this.
|
|
|
|
<!--truncate-->
|
|
|
|
But anything from here on down will not be.
|
|
|
|
Not this.
|
|
|
|
Or this.
|
|
```
|
|
|
|
By default, 10 posts are shown on each blog list page, but you can control pagination with the `postsPerPage` option in the plugin configuration. If you set `postsPerPage: 'ALL'`, pagination will be disabled and all posts will be displayed on the first page. You can also add a meta description to the blog list page for better SEO:
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
// ...
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-start
|
|
blogTitle: 'Docusaurus blog!',
|
|
blogDescription: 'A Docusaurus powered blog!',
|
|
postsPerPage: 'ALL',
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
## Blog sidebar {#blog-sidebar}
|
|
|
|
The blog sidebar displays recent blog posts. The default number of items shown is 5, but you can customize with the `blogSidebarCount` option in the plugin configuration. By setting `blogSidebarCount: 0`, the sidebar will be completely disabled, with the container removed as well. This will increase the width of the main container. Specially, if you have set `blogSidebarCount: 'ALL'`, _all_ posts will be displayed.
|
|
|
|
You can also alter the sidebar heading text with the `blogSidebarTitle` option. For example, if you have set `blogSidebarCount: 'ALL'`, instead of the default "Recent posts", you may rather make it say "All posts":
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-start
|
|
blogSidebarTitle: 'All posts',
|
|
blogSidebarCount: 'ALL',
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
## Blog post authors {#blog-post-authors}
|
|
|
|
Use the `authors` front matter field to declare blog post authors.
|
|
|
|
### Inline authors {#inline-authors}
|
|
|
|
Blog post authors can be declared directly inside the front matter:
|
|
|
|
````mdx-code-block
|
|
<Tabs groupId="author-frontmatter">
|
|
<TabItem value="single" label="Single author">
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors:
|
|
name: Joel Marcey
|
|
title: Co-creator of Docusaurus 1
|
|
url: https://github.com/JoelMarcey
|
|
image_url: https://github.com/JoelMarcey.png
|
|
---
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="multiple" label="Multiple authors">
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors:
|
|
- name: Joel Marcey
|
|
title: Co-creator of Docusaurus 1
|
|
url: https://github.com/JoelMarcey
|
|
image_url: https://github.com/JoelMarcey.png
|
|
- name: Sébastien Lorber
|
|
title: Docusaurus maintainer
|
|
url: https://sebastienlorber.com
|
|
image_url: https://github.com/slorber.png
|
|
---
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
````
|
|
|
|
:::tip
|
|
|
|
This option works best to get started, or for casual, irregular authors.
|
|
|
|
:::
|
|
|
|
:::info
|
|
|
|
Prefer using the `authors` front matter, but the legacy `author_*` front matter remains supported:
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
author: Joel Marcey
|
|
author_title: Co-creator of Docusaurus 1
|
|
author_url: https://github.com/JoelMarcey
|
|
author_image_url: https://github.com/JoelMarcey.png
|
|
---
|
|
```
|
|
|
|
:::
|
|
|
|
### Global authors {#global-authors}
|
|
|
|
For regular blog post authors, it can be tedious to maintain authors' information inlined in each blog post.
|
|
|
|
It is possible to declare those authors globally in a configuration file:
|
|
|
|
```yml title="website/blog/authors.yml"
|
|
jmarcey:
|
|
name: Joel Marcey
|
|
title: Co-creator of Docusaurus 1
|
|
url: https://github.com/JoelMarcey
|
|
image_url: https://github.com/JoelMarcey.png
|
|
|
|
slorber:
|
|
name: Sébastien Lorber
|
|
title: Docusaurus maintainer
|
|
url: https://sebastienlorber.com
|
|
image_url: https://github.com/slorber.png
|
|
```
|
|
|
|
:::tip
|
|
|
|
Use the `authorsMapPath` plugin option to configure the path. JSON is also supported.
|
|
|
|
:::
|
|
|
|
In blog posts front matter, you can reference the authors declared in the global configuration file:
|
|
|
|
````mdx-code-block
|
|
<Tabs groupId="author-frontmatter">
|
|
<TabItem value="single" label="Single author">
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors: jmarcey
|
|
---
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="multiple" label="Multiple authors">
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors: [jmarcey, slorber]
|
|
---
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
````
|
|
|
|
:::info
|
|
|
|
The `authors` system is very flexible and can suit more advanced use-case:
|
|
|
|
<details>
|
|
<summary>Mix inline authors and global authors</summary>
|
|
|
|
You can use global authors most of the time, and still use inline authors:
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors:
|
|
- jmarcey
|
|
- slorber
|
|
- name: Inline Author name
|
|
title: Inline Author Title
|
|
url: https://github.com/inlineAuthor
|
|
image_url: https://github.com/inlineAuthor
|
|
---
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Local override of global authors</summary>
|
|
|
|
You can customize the global author's data on per-blog-post basis:
|
|
|
|
```md title="my-blog-post.md"
|
|
---
|
|
authors:
|
|
- key: jmarcey
|
|
title: Joel Marcey's new title
|
|
- key: slorber
|
|
name: Sébastien Lorber's new name
|
|
---
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Localize the author's configuration file</summary>
|
|
|
|
The configuration file can be localized, just create a localized copy of it at:
|
|
|
|
```bash
|
|
website/i18n/[locale]/docusaurus-plugin-content-blog/authors.yml
|
|
```
|
|
|
|
</details>
|
|
|
|
:::
|
|
|
|
An author, either declared through front matter or through the authors map, needs to have a name or an avatar, or both. If all authors of a post don't have names, Docusaurus will display their avatars compactly. See [this test post](/tests/blog/2022/01/20/image-only-authors) for the effect.
|
|
|
|
## Reading time {#reading-time}
|
|
|
|
Docusaurus generates a reading time estimation for each blog post based on word count. We provide an option to customize this.
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-start
|
|
showReadingTime: true, // When set to false, the "x min read" won't be shown
|
|
readingTime: ({content, frontMatter, defaultReadingTime}) =>
|
|
defaultReadingTime({content, options: {wordsPerMinute: 300}}),
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
The `readingTime` callback receives three parameters: the blog content text as a string, front matter as a record of string keys and their values, and the default reading time function. It returns a number (reading time in minutes) or `undefined` (disable reading time for this page).
|
|
|
|
The default reading time is able to accept additional options: `wordsPerMinute` as a number (default: 300), and `wordBound` as a function from string to boolean. If the string passed to `wordBound` should be a word bound (spaces, tabs, and line breaks by default), the function should return `true`.
|
|
|
|
:::tip
|
|
|
|
Use the callback for all your customization needs:
|
|
|
|
````mdx-code-block
|
|
<Tabs>
|
|
<TabItem value="disable-per-post" label="Per-post disabling">
|
|
|
|
**Disable reading time on one page:**
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
showReadingTime: true,
|
|
// highlight-start
|
|
readingTime: ({content, frontMatter, defaultReadingTime}) =>
|
|
frontMatter.hide_reading_time ? undefined : defaultReadingTime({content}),
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
Usage:
|
|
|
|
```md "my-blog-post.md"
|
|
---
|
|
hide_reading_time: true
|
|
---
|
|
|
|
This page will no longer display the reading time stats!
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="passing-options" label="Passing options">
|
|
|
|
**Pass options to the default reading time function:**
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-start
|
|
readingTime: ({content, defaultReadingTime}) =>
|
|
defaultReadingTime({content, options: {wordsPerMinute: 100}}),
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="using-custom-algo" label="Using custom algorithms">
|
|
|
|
**Use a custom implementation of reading time:**
|
|
|
|
```js title="docusaurus.config.js"
|
|
const myReadingTime = require('./myReadingTime');
|
|
|
|
module.exports = {
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-next-line
|
|
readingTime: ({content}) => myReadingTime(content),
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
````
|
|
|
|
:::
|
|
|
|
## Feed {#feed}
|
|
|
|
You can generate RSS / Atom / JSON feed by passing `feedOptions`. By default, RSS and Atom feeds are generated. To disable feed generation, set `feedOptions.type` to `null`.
|
|
|
|
```ts
|
|
type FeedType = 'rss' | 'atom' | 'json';
|
|
|
|
type BlogOptions = {
|
|
feedOptions?: {
|
|
type?: FeedType | 'all' | FeedType[] | null;
|
|
title?: string;
|
|
description?: string;
|
|
copyright: string;
|
|
language?: string; // possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
|
|
};
|
|
};
|
|
```
|
|
|
|
Example usage:
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
// ...
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
blog: {
|
|
// highlight-start
|
|
feedOptions: {
|
|
type: 'all',
|
|
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`,
|
|
},
|
|
// highlight-end
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
The feeds can be found at:
|
|
|
|
<Tabs>
|
|
<TabItem value="RSS">
|
|
|
|
```text
|
|
https://example.com/blog/rss.xml
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="Atom">
|
|
|
|
```text
|
|
https://example.com/blog/atom.xml
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="JSON">
|
|
|
|
```text
|
|
https://example.com/blog/feed.json
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
## Advanced topics {#advanced-topics}
|
|
|
|
### Blog-only mode {#blog-only-mode}
|
|
|
|
You can run your Docusaurus 2 site without a dedicated landing page and instead have your blog's post list page as the index page. Set the `routeBasePath` to be `'/'` to serve the blog through the root route `example.com/` instead of the subroute `example.com/blog/`.
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
// ...
|
|
presets: [
|
|
[
|
|
'@docusaurus/preset-classic',
|
|
{
|
|
// highlight-next-line
|
|
docs: false, // Optional: disable the docs plugin
|
|
blog: {
|
|
// highlight-next-line
|
|
routeBasePath: '/', // Serve the blog at the site's root
|
|
/* other blog options */
|
|
},
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
:::caution
|
|
|
|
Don't forget to delete the existing homepage at `./src/pages/index.js` or else there will be two files mapping to the same route!
|
|
|
|
:::
|
|
|
|
:::tip
|
|
|
|
There's also a "Docs-only mode" for those who only want to use the docs. Read [Docs-only mode](./guides/docs/docs-introduction.md) for detailed instructions or a more elaborate explanation of `routeBasePath`.
|
|
|
|
:::
|
|
|
|
### Multiple blogs {#multiple-blogs}
|
|
|
|
By default, the classic theme assumes only one blog per website and hence includes only one instance of the blog plugin. If you would like to have multiple blogs on a single website, it's possible too! You can add another blog by specifying another blog plugin in the `plugins` option for `docusaurus.config.js`.
|
|
|
|
Set the `routeBasePath` to the URL route that you want your second blog to be accessed on. Note that the `routeBasePath` here has to be different from the first blog or else there could be a collision of paths! Also, set `path` to the path to the directory containing your second blog's entries.
|
|
|
|
As documented for [multi-instance plugins](./using-plugins.md#multi-instance-plugins-and-plugin-ids), you need to assign a unique id to the plugins.
|
|
|
|
```js title="docusaurus.config.js"
|
|
module.exports = {
|
|
// ...
|
|
plugins: [
|
|
[
|
|
'@docusaurus/plugin-content-blog',
|
|
{
|
|
/**
|
|
* Required for any multi-instance plugin
|
|
*/
|
|
id: 'second-blog',
|
|
/**
|
|
* URL route for the blog section of your site.
|
|
* *DO NOT* include a trailing slash.
|
|
*/
|
|
routeBasePath: 'my-second-blog',
|
|
/**
|
|
* Path to data on filesystem relative to site dir.
|
|
*/
|
|
path: './my-second-blog',
|
|
},
|
|
],
|
|
],
|
|
};
|
|
```
|
|
|
|
As an example, we host a second blog [here](/tests/blog).
|