Setting up a blog with Shipixen at a later time
- Updated on
In some cases, you might turn off the blog in the Shipixen app when you generate your template. However, we can't always predict the future. In those cases when you want to add a blog later, we got you covered!
Overview of the process
The process will require 3 steps to complete:
- Add blog overview page & pagination
- Add the blog tags pages
- Add a default author for blog posts
- Finally: add your first blog post
There are few optional steps we'll cover in point 5.:
- Add blog list to the homepage (or any other page)
- Add a link to the blog in the navigation
- Add a link to the blog in the footer
1. Add blog overview page & pagination
Start by creating a new directory under app
called all-articles
. This will be the overview page for all your blog posts.
Inside this the all-articles
directory, create two files
import ListLayout from '@/layouts/ListLayoutWithTags';
import { allCoreContent, sortPosts } from '@shipixen/pliny/utils/contentlayer';
import { allBlogs } from 'shipixen-contentlayer/generated';
import { genPageMetadata } from 'app/seo';
const POSTS_PER_PAGE = 5;
export const metadata = genPageMetadata({ title: 'Blog' });
export default function BlogPage() {
const posts = allCoreContent(sortPosts(allBlogs));
const pageNumber = 1;
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber,
);
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
};
return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Articles"
/>
);
}
/* This makes pagination work */
import ListLayout from '@/layouts/ListLayoutWithTags';
import { allCoreContent, sortPosts } from '@shipixen/pliny/utils/contentlayer';
import { allBlogs } from 'shipixen-contentlayer/generated';
const POSTS_PER_PAGE = 5;
export const generateStaticParams = async () => {
const totalPages = Math.ceil(allBlogs.length / POSTS_PER_PAGE);
const paths = Array.from({ length: totalPages }, (_, i) => ({
page: (i + 1).toString(),
}));
return paths;
};
export default function Page({ params }: { params: { page: string } }) {
const posts = allCoreContent(sortPosts(allBlogs));
const pageNumber = parseInt(params.page as string);
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber,
);
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
};
return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
);
}
If you don't want to use all-articles as your path, you can change it to anything you want. However, the configuration needs to match the value of
allArticlesPath
indata/config/site.settings.ts
. Read more in the configuration docs.
2. Add the blog tags pages
Next, we will add the tags pages. This will allow you to filter your blog posts by tags. Tags are also paginated.
Start by creating a new directory under app
called tags
. This will be the overview page for all your blog posts.
Inside this the tags
directory, create two files
import Link from '@/components/shared/Link';
import Tag from '@/components/shared/Tag';
import { slug } from 'github-slugger';
import tagData from 'app/tag-data.json';
import { genPageMetadata } from 'app/seo';
export const metadata = genPageMetadata({
title: 'Tags',
description: 'All tags on the site.',
});
export default async function Page() {
const tagCounts = tagData as Record<string, number>;
const tagKeys = Object.keys(tagCounts);
const sortedTags = tagKeys.sort((a, b) => tagCounts[b] - tagCounts[a]);
return (
<>
<div className="flex flex-col items-start justify-start divide-y divide-gray-200 dark:divide-gray-700 md:mt-24 md:flex-row md:items-center md:justify-center md:space-x-6 md:divide-y-0">
<div className="space-x-2 pb-8 pt-6 md:space-y-5">
<h1 className="text-3xl font-extrabold leading-9 tracking-tight text-gray-900 dark:text-gray-100 sm:text-4xl sm:leading-10 md:border-r-2 md:px-6 md:text-6xl md:leading-14">
Tags
</h1>
</div>
<div className="flex max-w-lg flex-wrap">
{tagKeys.length === 0 && 'No tags found.'}
{sortedTags.map((t) => {
return (
<div key={t} className="mb-2 mr-5 mt-2">
<Tag text={t} />
<Link
href={`/tags/${slug(t)}`}
className="-ml-2 text-sm font-semibold uppercase text-gray-600 dark:text-gray-300"
aria-label={`View posts tagged ${t}`}
>
{` (${tagCounts[t]})`}
</Link>
</div>
);
})}
</div>
</div>
</>
);
}
import { slug } from 'github-slugger';
import { allCoreContent } from '@shipixen/pliny/utils/contentlayer';
import { siteConfig } from '@/data/config/site.settings';
import ListLayout from '@/layouts/ListLayoutWithTags';
import { allBlogs } from 'shipixen-contentlayer/generated';
import tagData from 'app/tag-data.json';
import { genPageMetadata } from 'app/seo';
import { Metadata } from 'next';
export async function generateMetadata({
params,
}: {
params: { tag: string };
}): Promise<Metadata> {
const tag = decodeURI(params.tag);
return genPageMetadata({
title: tag,
description: `${siteConfig.title} ${tag} tagged content`,
alternates: {
canonical: './',
types: {
'application/rss+xml': `${siteConfig.siteUrl}/tags/${tag}/feed.xml`,
},
},
});
}
export const generateStaticParams = async () => {
const tagCounts = tagData as Record<string, number>;
const tagKeys = Object.keys(tagCounts);
const paths = tagKeys.map((tag) => ({
tag: tag,
}));
return paths;
};
export default function TagPage({ params }: { params: { tag: string } }) {
const tag = decodeURI(params.tag);
// Capitalize first letter and convert space to dash
const title = tag[0].toUpperCase() + tag.split(' ').join('-').slice(1);
const filteredPosts = allCoreContent(
allBlogs.filter(
(post) => post.tags && post.tags.map((t) => slug(t)).includes(tag),
),
);
return <ListLayout posts={filteredPosts} title={`${title} posts`} />;
}
3. Add a default author for blog posts
In order to write blog posts, you need to have an author. It's possible to add multiple authors, but for now, we will just add one that will be used by default when creating new posts.
Create a new file under data/authors
called default.md
with the following content:
---
name: Jane Doe
avatar: /static/images/avatar.png
occupation: Writer
---
Jane works tirelessly to make sure all customers are happy. We are always looking for ways to improve our service and welcome any feedback.
4. Finally: add your first blog post
Now that we have all the pages and configuration in place, we can add our first blog post.
Adding an article to the blog is as simple as creating a Markdown (mdx file) in the data
directory. The file name is used as the slug for the article.
Create a new file under data
called my-first-post.mdx
with the following content:
---
title: Writing in Markdown
date: 2023-01-01
tags:
- guide
- markdown
- syntax-highlight
summary: Example of a blog post
---
# Introduction
Writing in markdown is easy. You can use any editor you want. We recommend [Visual Studio Code](https://code.visualstudio.com/).
## Basic formatting
You can use **bold**, _italic_ and `code` formatting.
Congratulations! 🎉 You have now added your first blog post.
If you have your website running locally, you should restart the development server and you will see your new blog post (use npm run dev
to start the development server after you shut it down).
You can read more on writing markdown in the documentation.
5. Optional steps
While these steps are optional, they are recommended to make your blog more accessible.
5.1 Add blog list to the homepage (or any other page)
If you'd like to show a list of blog posts on the homepage or any other page, you can do so by adding the following code to the page:
+ import LatestArticles from '@/components/blog/LatestArticles';
export default function Page() {
...
return (
...
+ <section className="container-wide mt-12">
+ <LatestArticles />
+ </section>
...
);
}
5.2 Add a link to the blog in the navigation
It's likely a good idea to add a link to the blog in the navigation. You can do so by adding the following code to the header navigation links:
+ import { siteConfig } from '@/data/config/site.settings';
export const headerNavLinks = [
...
+ { href: siteConfig.allArticlesPath, title: 'Blog' }
];
5.3 Add a link to the blog in the footer
Similarly, you can add a link to the blog in the footer by adding the following code to the footer navigation links:
+ import { siteConfig } from '@/data/config/site.settings';
export const footerLinks = [
{
columnName: 'Product',
links: [
...
+ { href: siteConfig.allArticlesPath, title: 'Blog' }
],
},
...
];