Create a new theme from scratch
In this recipe, we will create a new theme from scratch. We will (re)create the theme called "Minimalist" that is included in the Bloggrify core repository.
Getting Started
First, you need to create a new Nuxt application. You can do this by running the following command:
npx nuxi@latest init neo-minimalist
Then, you need to install the dependencies:
npm install @bloggrify/core
npm install -D sass-embedded
Then you have to explicitly say to Nuxt that you are using Bloggrify as an extended module. You can do this by adding the following line in your nuxt.config.js
file:
extends: [
'@bloggrify/core',
],
Create a basic configuration file
Create a new file called app.config.ts
in the root of your project. This file will contain the configuration of your theme.
This file will override the default configuration of Bloggrify. If you don't specify a configuration, the default configuration will be used.
Here is an example of a basic configuration file:
export default defineAppConfig({
url: 'https://neo-minimalist.bloggrify.com/',
theme: 'neo-minimalist',
name: 'Neo-minimalist Demo',
description:
'A minimalist theme for Bloggrify',
})
That's probably not enough for a complete theme, but it's a good start. You can add more configuration options later. Don't forget to read the official documentation to know more about the configuration options.
Create the layout for the home page
Create a new folder called layouts/themes/neo-minimalist
in the root of your project. This folder will contain the layouts of your theme.
Create a new file called home.vue
in the layouts/themes/neo-minimalist
folder. This file will be the layout for the home page.
Here is an example of a basic layout file:
<template>
<div>
<header>
<h1>
{{ title }}
</h1>
</header>
<main>
<div>
<div >
{{ description }}
</div>
<div >
<NuxtLink to="/archives">
Read all posts
</NuxtLink>
</div>
</div>
</main>
</div>
</template>
<script setup lang="ts">
defineProps<{
doc: unknown;
}>()
const config = useAppConfig()
const title = config.name
const description = config.description
</script>
Let's explain the code above:
- The
<template>
section contains the HTML structure of the layout. In this example, we have a navigation bar and a main content area. - The
<script setup>
section contains the logic of the layout. In this example, we get the configuration from theapp.config.ts
file and display the title of the blog.
Create the index page
Create a new folder called content
in the root of your project. This folder will contain the articles of your blog and the index page.
Create a new file called index.md
in the pages
folder. This file will be the index page of your blog.
---
id: "1"
title: "Home page"
description: "Basic home page"
date: "2024-12-31"
categories:
- home
tags:
- lorem
- ipsum
layout: home
listed: false
---
Run the development server
You can now start the development server by running the following command:
npm run dev
Go to http://localhost:3000
in your browser, and you should see the home page of your blog.
This is cool, but, you don't have the list of all the articles. Let's add a new layout for the archives page.
Create the layout for the archives page
Create a new file called archive.vue
in the layouts/themes/neo-minimalist
folder. This file will be the default layout for the archive page.
Here is an example of a basic layout file:
<template>
<div>
<header>
<h1>
{{ title }}
</h1>
</header>
<main>
<div>
<div >
All Posts
</div>
<div >
<section class="mt-10">
<MinimalistListing title="All Posts"/>
</section>
</div>
</div>
</main>
</div>
</template>
<script setup lang="ts">
const config = useAppConfig()
const title = config.name
</script>
This layout will display the list of all the articles. To do so, we use the MinimalistListing
component. This component is provided by the @bloggrify/core
package. But we will see how to create a custom component later.
Now, you can go to http://localhost:3000/archives
in your browser, and you should see the list of all the articles.
The list is probably empty, because you don't have any articles yet. Let's add some content.
Create the default layout for the pages
Create a new file called default.vue
in the layouts/themes/neo-minimalist
folder. This file will be the default layout for all pages.
Here is an example of a basic layout file:
<template>
<div>
<header>
<h1>
{{ title }}
</h1>
</header>
<main>
<div v-if="doc">
<div >
<h2>
{{ doc.title }}
</h2>
</div>
<ContentRenderer
id="nuxtContent"
:value="doc"
/>
</div>
</main>
</div>
</template>
<script setup lang="ts">
defineProps<{
doc: unknown;
}>()
const config = useAppConfig()
const title = config.name
</script>
The ContentRenderer
component is a custom component from Nuxt Content that renders the content of the page.
Add some content
You can read the official documentation to know more about how to write articles.
But for now, you can create a new file called hello-world.md
in the content
folder with the following content:
---
title: Hello World
description: A simple article to say hello to the world
---
# Hello World
This is a simple article to say hello to the world.
Now, you can go to http://localhost:3000/hello-world
in your browser, and you should see the article.
And voilà, you have created a new theme from scratch! You can now start customizing it to fit your needs. (it's probably ugly, but it's a start :) )
Create the layout for the tag page
Create a new file called tag.vue
in the layouts/themes/neo-minimalist
folder. This file will be the layout for the tag page.
Here is an example of a basic layout file:
<template>
<div>
<header>
<h1>
{{ title }}
</h1>
</header>
<main>
<div>
<div >
All Posts
</div>
<div >
<section class="mt-10">
<MinimalistListing title="All Posts" :tag="tag"/>
</section>
</div>
</div>
</main>
</div>
</template>
<script setup lang="ts">
defineProps<{
tag: string;
}>()
const config = useAppConfig()
const title = config.name
</script>
This layout will display the list of all the articles with the specified tag. To do so, we use the MinimalistListing
component.
Now, you can go to http://localhost:3000/tags/lorem
in your browser, and you should see the list of all the articles with the tag "lorem".
Create the layout for the category page
The layout for the category page is similar to the layout for the tag page. You can create a new file called category.vue
in the layouts/themes/neo-minimalist
. The only difference is that you have to replace the tag
prop by the category
prop.
Create a custom component to display the list of articles
Let's create a custom component to display the list of articles. Create a new file called MyOwnListing.vue
in the components/content
folder of your project.
<template>
<div>
<ul>
<li v-for="doc in docs" :key="doc.id">
<NuxtLink :to="`/${doc._path}`">
{{ doc.title }}
</NuxtLink>
</li>
</ul>
<MinimalistPaginationBar :total="totalNumberOfPages" />
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
category?: string;
tag?: string;
}>()
const {itemsPerPage, currentPage} = usePagination()
const id = 'listing-' + props.category + '-' + props.tag
let where = {}
if (props.category) {
where['categories'] = { $in: [props.category] }
}
if (props.tag) {
where['tags'] = { $in: [props.tag] }
}
where = { ...where, ...{ draft: { $ne: true }, listed: { $ne: false } } }
const numberOfPostsPerPage = itemsPerPage.value
const { data: docs } = useAsyncData(id, () => {
return queryContent('')
.where(where)
.sort({ date: -1 })
.skip((currentPage.value - 1) * numberOfPostsPerPage)
.limit(numberOfPostsPerPage)
.find()
})
const totalNumberOfPages = await queryContent('').where(where).count()
</script>
Now, you can use the MyOwnListing
component in the archive.vue
, tag.vue
, and category.vue
layouts.
You can replace the MinimalistListing
component by the MyOwnListing
component in the archive.vue
, tag.vue
, and category.vue
layouts.
usePagination
composable. This hook is provided by the @bloggrify/core
package.- Getting Started
- Create a basic configuration file
- Create the layout for the home page
- Create the index page
- Run the development server
- Create the layout for the archives page
- Create the default layout for the pages
- Add some content
- Create the layout for the tag page
- Create the layout for the category page
- Create a custom component to display the list of articles