This post offers a guide on how to effectively use Markdown syntax and MDX to create well-structured and visually appealing blog posts using the blog.v2
template.
#Writing Content with Markdown
Markdown is a lightweight markup language commonly used for formatting plain text in a simple, readable way. In the context of MDX
, which stands for Markdown + JSX, Markdown allows you to write content with familiar syntax (like #
for headers, *
for lists, and []()
for links) while also enabling the embedding of React components directly within the Markdown file.
This combination makes MDX especially useful in projects like blogs or documentation sites, as it allows developers to mix static content (written in Markdown) with interactive elements (created using JSX components) in a seamless way.
Let's get started!
#Article Title and Header
The article title is a crucial element of your blog post, serving as the first impression for readers. In the blog.v2
template, the title is automatically generated from the title
property in the metadata
object you defined earlier.
The header, which includes the title, date, author, and view count, is rendered using the src/app/blog/[slug]/header.tsx
component. Here's a breakdown of its elements:
- Title: From the
metadata.title
property. - Date: From the
metadata.date
property. - Author: By default, it uses the
AUTHOR
constant fromsrc/config.ts
; override withmetadata.author
andmetadata.authorUrl
. - View Count: This feature only increments in the production environment. For local development modifications, you can adjust the
src/components/Views/index.tsx
component.
Here's an example of how the header appears at the top of this blog post:
This header provides a clean, informative introduction to your post, enhancing readability and user experience.
#Headings
Headings are important for SEO and readability. They help organize the content of your blog post and make it easier to read.
To create a heading, use the #
symbol followed by the heading text. For example:
# My Heading
If you want to add an anchor to the heading for when user hovers over it, you can use the following syntax:
## My Heading [#my-heading]
This will create a heading with an anchor that you can use to link to the heading. When a user clicks on the anchor, they will be redirected to the heading.
#Subheadings
Subheadings are smaller headings that help break up the content of your blog post and make it easier to read.
#Here's a sub-header with an anchor
You also have sub-sub headings:
#Here's a sub-sub-header with an anchor
#Table of Contents
The table of contents menu is toggled via a floating button on the blog post. To ensure your heading is added to the table of contents, use an anchor on your heading:
# My Heading [#this-heading-will-appear-in-table-of contents]
All headings with anchors will automatically be added to the table of contents.
Note
The floating button for the Table of Contents will only render if your post has at least three headings with anchors.
#Paragraphs
Paragraphs are a block of text that are displayed in a paragraph.
An example of two paragraphs is:
#Italic
To create italic text, use the *
symbol followed by the text. For example:
*Italic text*
Here is an example of italic text:
Italic text
#Bold
To create bold text, use the **
symbol followed by the text. For example:
**Bold text**
Here is an example of bold text:
Bold text
#Strikethrough
To create strikethrough text, use the ~~
symbol followed by the text. For example:
~~Strikethrough text~~
Here is an example of strikethrough text:
Strikethrough text
#Checkbox
To create a checkbox, use the [ ]
symbol followed by the text. For example:
- [ ] Checkbox
Here is an example of a checkbox:
- Walk my beautiful doggo
If you want to create a checkbox that is checked, you can use the [x]
symbol followed by the text. For example:
- [x] Checkbox
Here is an example of a list of checkboxes, checked and unchecked:
- Walk my beautiful doggo
- Do the gardening
- Code for 5 hours straight
#Newlines
A newline is a text break that moves the content to the next line without creating a new paragraph or adding additional vertical spacing.
To create a newline in Markdown, add the "\
" (backslash) character at the end of the line where you want the break to occur. This technique allows you to control line breaks without introducing the extra spacing that comes with paragraphs.
so much depends \ upon a red wheel \ barrow glazed with rain \ water beside the white \ chickens
Here is an example of text using newlines:
so much depends
upon
a red wheel
barrow
glazed with rain
water
beside the white
chickens
Use newlines when you want to maintain a visual flow in your content without creating the visual separation of a new paragraph. For example, in poetry, addresses, or to preserve line breaks in quoted content.
#Lists
Lists are a block of text that are displayed in a list.
#Unordered Lists
You can create unordered lists using asterisks (*):
* Item 1
* Item 2
* Item 3
- Item 1
- Item 2
- Item 3
#Ordered Lists
You can create ordered lists using numbers:
1. Item 1
2. Item 2
3. Item 3
- Item 1
- Item 2
- Item 3
#Tables
To create a table using Markdown syntax:
| Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Value 1 | Value 2 | Value 3 | | Value 4 | Value 5 | Value 6 |
This will render the table as:
Column 1 | Column 2 | Column 3 |
---|---|---|
Value 1 | Value 2 | Value 3 |
Value 4 | Value 5 | Value 6 |
#Blockquotes
Blockquotes are a block of text that are displayed in a blockquote.
An example of a blockquote is:
> This is a blockquote
Here is a blockquote with a citation:
The only way to do great work is to love what you do. If you haven't found it yet, keep looking. Don't settle. — Steve Jobs
#Break
A break is a block of text that are displayed in a break.
An example of a break is:
***
Here is a break:
This is useful for adding a break in your text to separate sections.
#Images
Images are a block of text that are displayed in a blockquote.
An example of an image is:
![My Image](/images/my-image.png)
Here is an example of an image:
Images are stored in the public/images
directory.
#Externally Referenced Images
If you wish to use an image from an external URL. For example:
![My Image](https://example.com/image.jpg)
You must add it to remotePatterns
in next.config.mjs
file. Otherwise it will not be displayed and you will see an error in the console
See NextJS documentation on next/image and remotePatterns for more information.
#Image Captions
Captions can be added to images using the <Caption>
component below the image.
![My Image](/images/guide-to-writing-your-first-blogv2-post-using-markdown/patrickprunty.png)
<Caption>Patrick Prunty: Creator of this blog template</Caption>
Here is an example of an image with a caption:
The Creator of this blog template, Patrick Prunty on the Camino de Santiago
These images use next/image
under the hood to optimize the images for the web.
#Custom Styled Image
If you wish to add specific styling, resize the image, or make the image a loading priority, you can directly import the Image
component from next/image
and use it directly in your blog post.
<div className="flex items-center justify-center mt-10 mb-10">
<Image
src="/images/_placeholders/avatar.svg"
alt="Example Avatar"
className="rounded-full object-cover w-40 h-40"
width={140}
height={140}
unoptimized
/>
</div>
Here is an example of an image with custom styling; positioned centrally, fully rounded borders, responsive sizing and priority loading:
Custom Styled ImageIf you wish to change default optimization options for images rendered via:
![My Image](/images/_placeholders/avatar.svg)
You can refer to the mdx-components.tsx
file and change the default optimization configuration.
#Photo Grid
To create a photo grid, you can use the <PhotoGrid>
component.
import PhotoGrid from '@/components/PhotoGrid';
...
// Export is needed here even though it is referenced in the same file because of MDX
export const photoGridImages = [
"/images/_placeholders/avatar.svg",
"/images/_placeholders/avatar.svg",
"/images/_placeholders/avatar.svg"
];
const metadata = {
...
}
<PhotoGrid images={photoGridImages} />
Here is an example of a photo grid:
Note
The PhotoGrid
component displays three columns on large screens and two on small screens. To maintain even rows, it
omits the last photo if it creates an uneven row. For example, with 4 photos: large screens show one row of three,
omitting the fourth, while small screens display two rows of two, showing all photos.
#Links
Links are a block of text that are displayed in a blockquote.
An example of a link is:
[My Link](https://example.com)
Here is a link to my website.
#Link with an Image
You can also wrap links around other content to make it clickable:
[![Clickable image](/images/_placeholders/avatar.svg)](https://patrickprunty.com)
<Caption>Click me to navigate to my website!</Caption>
Here is a clickable image:
Click me to navigate to my website!
#Admonitions
Admonitions are a block of text that are displayed in a blockquote.
An example of an admonition is:
<Admonition type="info" title="Info">
This is a note
</Admonition>
Info
This is a note
Other types of admonitions include type "warning", "tip", "danger" and "note":
Warning
This is a warning
Danger
This is a danger
Tip
This is a tip
Note
This is a note
#Code Blocks
Code is a block of text that are displayed in a code block.
Code blocks are escaped with three backticks followed by the language of the code and a newline, code body and then another three backticks.
Here is an example of a code block for C++:
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
#Footnotes
Footnotes are a block of text that are displayed in a footnote.
An example of a footnote is:
Here is a footnote.<Ref id="1" />
<FootNotes>
<FootNote id="1">Here is a reference to a footnote with a link to <a href="https://patrickprunty.com">my website</a>.</FootNote>
</FootNotes>
This is a footnote.[1]. You will see this in the footer of the blog post or by clicking on the footnote number.
Here is another footnote on a blockquote with citation:
"Two roads diverged in a wood, and I— I took the one less traveled by, And that has made all the difference." — Robert Frost [2]
#Social Embeds
#YouTube Videos
You can embed YouTube videos into your blog posts using the following syntax:
<YouTube videoId="fJ9rUzIMcZQ" />
The YouTube videoId
is the ID of the YouTube video. You can find the video ID by clicking on the YouTube video and then copying the ID from the URL after v=
in the URL: https://www.youtube.com/watch?v=fJ9rUzIMcZQ
.
#TikTok Videos
To embed TikTok videos, use the videoUrl parameter. This is the complete URL of the TikTok video you want to embed.
<TikTok videoUrl="https://www.tiktok.com/@ashleypicock12345678/video/7430963230823959854"/>
#Strava Activity
You can embed your Strava activities to showcase your recent workouts or race results. Just specify the activityId, which you can find in the URL of your activity on Strava.
<Strava activityId="10125503113" />
Embedding LinkedIn posts enables you to share professional updates, articles, and discussions directly within your blog, providing readers with a richer context and up-to-date insights. Use the postUrl parameter to specify the link to your LinkedIn post.
How to Get the postUrl
# for LinkedIn Embeds
- Open the LinkedIn post you want to embed.
- Click the "Share" button on the post and select "Embed."
- Copy the URL in the embed code that appears, and paste it into the postUrl field in your blog’s Markdown or component code.
<LinkedIn postUrl="https://www.linkedin.com/embed/feed/update/urn:li:share:7259535098184663041" />
To share tweets, you can embed them by providing the full tweetUrl. This allows you to include real-time Twitter content such as status updates or comments.
<Twitter tweetUrl="https://twitter.com/elonmusk/status/1853612871877329188?ref_src=twsrc%5Etfw" />
Thanks for reading!
Remember, you can always add more custom components to your blog posts by editing the mdx-components.tsx
file. If you would like to add a new default MDX component, please open an issue on the GitHub repository and I will be happy to review your request.
If you have any questions or feedback, please feel free to reach out to me using any of my social links on my personal website: patrickprunty.com, or via email at patrickprunty.business@gmail.com.
1. ^ Here is a reference to a footnote with a link to my website. You can return to where you left off in the blog post by clicking on the '^' character at the beginning of this footnote.
2. ^ Robert Frost's poem The Road Not Taken.