Lume SSG Handbook – How to Create a Static Blog with Lume
Lume is a new static site generator based on Deno. Deno is a JavaScript-based run-time environment that supports TypeScript.
Lume is not built around any specific language. It supports Markdown, Nunjucks, TypeScript, and JavaScript by default. Lume also supports plugins. Some plugins come preinstalled by default. This is why Lume itself is template-language agnostic.
Before learning more about Lume, let's discuss Deno and consider some important Deno features.
What is Deno?
Deno is an alternative to Node.js built by Ryan Dahl (who also developed Node). Deno is based on the Rust programming language, and the second main component in Deno is the JavaScript V8 engine for WebAssembly.
Deno has many cool features – it's fast, secure by default, is compatible with web assembly and has TypeScript support, has in-built development tools, and more. Deno also supports Node.js APIs so you can use all npm packaged with Deno.
In Deno, you do not need to create a configuration file to run a simple program. You simply deploy your website instantly with a second on-edge network. But my final favorite feature is the new node_modules
folder in the workspace. Deno caches all the packages locally and uses them, which is very fast compared to Node.
You can check out the demo blog website here, and all the code is available on GitHub here.
Now let's dive into the tutorial.
Table of Contents
- Lume + Markdown
- Why is Lume special?
- How does Lume compare to other static site generators?
- How to start a new project with Lume
- Lume folder structure
- Additional folders
- How to create global data
- How to create a dynamic page
- How to create a Home and Pagination page
- How to build an articles page
- How to generate a category page
- How to generate a tag page
- How to enable search functionality
- How to install page find
- Lume SEO
- Lume Sitemap
- Lume plugins
- How to enable comments
- How to use Netlify CMS with Lume
- How to deploly your blog with Deno Deploy
- Github pages
- Conclusion
Lume + Markdown
Lume is a new static site generator based on Deno created and maintained by Óscar Otero. Lume uses markdown-it as the default markdown. You can use the remark plugin to change the default markdown.
Markdown is a language that helps to write documents, readme files, and blogs on the internet. John Gruber created markdown in 2004.
Markdown-it is similar to GitHub-flavored Markdown (GFM) markdown. GFM and markdown-it both follow the exact markdown specifications.
If you've worked with GitHub and written README files, that means you are likely familiar with GFM markdown. If you don't like the default (markdown-it) markdown, you can change the markdown with the remark plugin.
There are tons of static site generators. So why is Lume special? What does it provide compared to other static site generators? Let's find out.
Why is Lume special?
As you know, Lume is built on Deno, and Deno is a Node.js alternative—that is why Lume provides lots of features out of the box.
Lume works similarly to a GitHub readme file. If you're familiar with writing one of those (and using markdown), you do not need to learn anything else to write articles and documentation with Lume.
Here are some benefits of Lume:
- Lume supports multiple template engines like Markdown, Nunjucks, Eta, JSX, Liquid, or Pug.
- It supports multiple authors
- It has code syntax highlighting
- There's great SEO support
- Lume supports multiple languages
- It has Windi CSS support
- There's pagination and component support
- It supports minifying JavaScript, HTML, CSS, and SASS
- It has relations support
- There is the built-in search functionality
- It supports Netlify CMS
- It supports images and SVGs
- There's Remark.js plugin support
- You can deploy with Netlify, Vercel, GitLab Pages, and the GitHub page.
How Does Lume Compare to Other Static Site Generators?
Lume is a new static site generator compared to others, but it comes with many configuration options, and you can do anything with it. You don't even need to use any third-party plugins.
With Lume processors and preprocessors, you can easily manipulate the HTML code with the JavaScript DOM API. Other static site generators support a few template engines, but Lume supports many template engines like JavaScript, JSX, Nunjucks, Eta, JSX, Liquid, and Pug.
Note that Lume can seem tough to get started with for beginners. But if you're following my article, just make sure to open the code which will make things much clearer for you.
How to Start a New Project with Lume
You can set up a new project with the Lume CLI with this command:
deno run -Ar https://deno.land/x/lume/init.ts
Lume installation demo
Follow these steps:
- First, create an empty
mkdir lume-deno
folder project. - Then run the lume
init.ts
command. - Select an available plugin from the list.
And you should be up and running.
Lume Folder Structure
After the installation finished, we saw three files:
_config file
is used to configure Lume.deno.json
is a defined script or task for Deno.import_map.json
is to help you import a Deno package for the internet.
lume default folder structure
How to run the Lume server
To run a local development server, you'll use the deno task lume --serve
command. To build a website, run the deno task build
command.
If you face a 404 - not found error, you can create a index.njk
file within the root folder.
In the index.njk
file, paste the following code.
---
title: "hello"
---
hello world
And you'll see the following output:
Lume hello-world
Additional folders:
posts
folder is not a compulsory folder. It contains all your posts' markdown files.pages
folder is not a compulsory folder. It has all your pages' markdown files.author
folder is not a compulsory folder. It has all your author markdown files._components
folder is a compulsory folder. It has all your components._includes
folder is a compulsory folder. It contains your layout and templates for your site.images
folder is not a compulsory folder. It contains all your images.
The posts, pages, authors, and images folders are optional. You can rename these folders according to your wishes. The _components
and _includes
folders are mandatory and you don't rename them.
The difference between components, layout, and template are as follows:
- The components are reusable code
- The layout and template are not reusable like components.
How to Create Global Data
In Lume, you can create a data variable, which has access to the entire website by all template engines.
// Set a variable
site.data("post_per_page", 10);
// Set a function
site.data("randomNumber", function () {
return Math.random();
});
How to create posts, pages, and author markdown files
You create posts, pages, and author folders in the root folder. Then, inside every folder, you write markdown files.
You can access all posts, pages, and authors by file name on the browser:
localhost:3000/posts/your-title.html
localhost:3000/pages/your-pages.html
localhost:3000/author/your-author.html
Suppose you need a demo post, pages, and author markdown for a project or template. Then, you can use demo-markdown posts for your project. It is free and open source, and you can create your own template.
How to create a dynamic page
In Lume, .tmpl.js
and .tmpl.ts
extensions use JS and TS as template engines. You can use them with regular pages or dynamic pages to create categories, tags, pagination, and so on for your website.
How to create a home and pagination page
The home page is based on pagination, and pagination is based on posts. Lume dynamically generates the pagination.
In Lume, I chose nunjucks and JavaScript to create my demo website. Nunjucks is the default template engine. You can easily change the default Nunjucks engine with another template engine with copy-paste code.
home page
Lume provides a JavaScript template function that helps create dynamic web pages. If you create a home page for the site, you need to create an index.tmpl.js
file in your root or src folder. Lume also supports an src folder to organize your project. In my demo project, I'm not using the src
folder.
The *.tmpl.js
is an extension of a JavaScript template that helps create dynamic pages for websites. It comes pre-installed in Lume with the modules plugin.
For example, the following code creates pagination for your website. But the layout comes from the _includes
folder.
// index.tmpl.js
// title for SEO
export const title = "Minimalist blog"
// description for SEO
export const description = "Minimalist blog theme is liteweight and work with lume."
export default function* ({ search, paginate }) {
// Get all posts of type article.
const posts = search.pages("type=article", "date=desc");
// Configation for pagination
const options = {
// Page 1 is the homepage, set "/" as url
url: (n) => n === 1 ? "/" : `/page/${n}/`,
// par page posts
size: 7,
};
// Yield the pages, but the index needs a different layout
for (const page of paginate(posts, options)) {
// if home page, use diffrent layout "/"
if (page.pagination.page === 1) {
page.menu = {visible: true, order: 1, title:"Home" }
page.title = "Home page"
// comes from _includes folder
page.layout = "layouts/home.njk";
} else {
// Render diffrent layout if it is not home page page "/page/2","/page/3",etc
page.title = "Pagination page"
page.layout = "layouts/home.njk";
}
yield page;
}
}
Lume has a search plugin that helps you search pages. In my demo blog, I search all pages base on the type.
In my all posts folder, all posts are defined in type=article
, the author is described in type=author
, and pages are defined in type=page
. The search plugin is pre-installed with Lume.
On index.tmpl.js
file, you can get all pages that have the type "article" (type=article
) using the following code: const posts = search.pages("type=article", "date=desc");
. The search.pages("type=article", "date=desc")
function only returns those that have type=article
.
The layouts/base.njk
layout file contains an HTML base and includes a header and footer for the website.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<meta name="description" content="{{ description or site.description }}">
</head>
<body>
{% include "layouts/header.njk" %}
<main class="{{ bodyClass }}">
{{ content | safe }}
</main>
{% include "layouts/footer.njk" %}
</body>
</html>
Inside the {{ content | safe }}
, Lume renders other HTML, like cards, articles, home templates, Tag and category pages, and so on.
// rest code ...
for (const page of paginate(posts, options)) {
}
// rest code ...
I used the for loop on the index.tmp.js
file that helps get all the posts and send them to the layouts/home.njk
file and the layouts/home.njk
file. You get all posts from the result, and then pass them to the card.njk
template.
---
layout: layouts/base.njk
---
{% for post in results %}
{% include "templates/card.njk" %}
{% else %}
<h2> Posts is empty </h2>
{% endfor %}
{% include "templates/pagnation.njk" %}
The templates/card.njk
file runs for all blogs and generates HTML for each blog. Your card looks like this:
card.njk
In card.js
template, you can access it using {{}}
curly brackets. Get the title using {{post.data.title}}
and {{post.data.description}}
.
In my demo blog, I'm getting only the first category to show inside the card. So I use a defined filter _config.ts
and use it with |
symbols. Inside card.njk
we get a zero index or first value in from categories with the following code: {{ post.data.category | category }}
.
To get the author on card.njk
I define the relationship between the article and the author type, which you can learn about from the docs.
<div class="container px-6 py-10 mx-auto">
<div class="mt-8 lg:-mx-6 lg:flex lg:items-center">
<img class="object-cover border-none w-full lg:mx-6 lg:w-1/2 rounded-xl h-72 lg:h-96" src="{{ post.data.image }}" alt="{{ post.data.title }}">
<div class="mt-6 lg:w-1/2 lg:mt-0 lg:mx-6 ">
<a class="text-sm text-blue-500 uppercase" href="/category/{{ post.data.category | category }}" >
{{ post.data.category | category }}
</a>
<a href="{{ post.data.url }}" class="block mt-4 text-2xl font-semibold text-gray-800 hover:text-gray-500 dark:text-white md:text-3xl">{{ post.data.title }}</a>
<p class="mt-3 text-sm text-gray-500 dark:text-gray-300 md:text-sm">
{{ post.data.description }}
</p>
<a href="{{ post.data.url }}" class="inline-block p-2 bg-blue-700 mt-4 text-white hover:bg-blue-500">Read more</a>
<div class="flex items-center mt-6">
{% if post.data.author.length <= 2 %}
{% for author in post.data.author %}
<img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.author_name}}">
<div class="mx-4">
<a href="{{author.url}}" class="text-sm text-gray-700 dark:text-gray-200">
{{ author.author_name}}</a>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{author.job}}
</p>
</div>
{% endfor %}
{% else %}
<img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ post.data.author.image}}" alt="{{ post.data.author.name}}">
<div class="mx-4">
<a href="{{ post.data.author.url}}" class="text-sm text-gray-700 dark:text-gray-200">
{{ post.data.author.author_name}}</a>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{post.data.author.job}}
</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
The {{ title }}
and {{description}}
both show the markdown file title and description. To show the category, I used a filter to show a single category on the article page and define the filter on _config.ts
file. I also show single and multiple authors with For loop. Every card has its own post.data.url
property, after the user clicks on the read more button user ago respected the article read page. To show the image, I used {{ post.data.image }}
property. I also show single and multiple authors with For loop on card.njk
file.
How to Build an Articles Page
I know the page containing the article content is one of the most important for a blog. It's where readers should spend most of their time rather than the website's home page.
---
category:
- Blog
date: 2022-03-20T13:09:24Z
description: Dolor excepteur ad ad fugiat Lorem consectetur velit excepteur duis qui.
image: /images/dice.jpg
tags:
- npm
- npm cli
- npm install command
title: Random blog Title for markdown.
draft: false
author_id: 1
type: article
layout: templates/article.njk
---
Laboris consequat elit ad excepteur. Ipsum duis amet dolore voluptate dolore consequat ullamco incididunt ullamco. Dolore laborum cupidatat dolor ipsum reprehenderit excepteur cupidatat dolore.
## First
Cupidatat non amet irure esse quis aute qui enim. Est qui ullamco proident consequat aute reprehenderit eiusmod nisi. Laboris ullamco fugiat sint occaecat.
## Second
Irure fugiat officia non esse esse irure eu sint commodo quis amet. Dolor culpa non amet elit adipisicing exercitation ex anim velit ipsum.
## conclusion
Culpa irure eiusmod labore ut proident sit enim laborum nulla voluptate eu. Id tempor velit cillum pariatur est laboris ipsum ad. Sint nostrud nostrud laboris Lorem consequat tempor voluptate dolore velit. Commodo elit nulla commodo pariatur. Deserunt ipsum fugiat id ipsum pariatur cupidatat magna ex. Fugiat aliquip nisi laboris aliquip velit velit id quis eu reprehenderit excepteur fugiat.
I created an article in the posts folder under type=article
. The author_id
defines the relation between the author and the article.
I used templates/article.njk
as the layout for my articles page. You can design yours as per your requirements. You can design the article title, description, author card, and tags as well.
---
layout: layouts/base.njk
---
<article class="container mx-auto p-2">
<div class="flex flex-col">
<h1 class="text-2xl text-black mt-3">{{ title }}</h1>
<p class="text-xl mt-1 text-gray-600">{{ description }}</p>
{% if author %}
<div class="flex flex-row mt-4">
{% if author.length <= 2 %}
{% for author in author %}
<img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.author_name}}">
<div class="mx-4">
<a href="{{author.url}}" class="text-sm text-gray-700 dark:text-gray-200">
{{ author.author_name}}</a>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{author.job}}
</p>
</div>
{% endfor %}
{% else %}
<img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.name}}">
<div class="mx-4">
<a href="{{ author.url}}" class="text-sm text-gray-700 dark:text-gray-200">
{{ author.author_name}}</a>
<p class="text-sm text-gray-500 dark:text-gray-400">
{{ author.job}}
</p>
</div>
{% endif %}
</div>
{% endif %}
<nav class="flex flex-row my-5">
{% for tag in tags %}
<a href="/tag/{{ tag.trim().toLowerCase().split(' ').join("-") }}/" class=" bg-blue-500 text-black p-2 mx-1">{{ tag }}</a>
{% endfor %}
</nav>
<time class="mt-2" datetime="{{ date | date('DATETIME') }}">
{{ date | date('HUMAN_DATE') }}
</time>
</div>
<div class="mt-4">
{{ content | safe }}
</div>
</article>
{%- set previousPost = search.previousPage(url, "type=article") %}
{% if previousPost %}
<ul class="flex flex-row w-full mt-10 justify-between p-4">
{%- if previousPost %}
<li class="w-6/12 text-left">
← Previous: <a href="{{ previousPost.data.url }}" rel="prev">{{ previousPost.data.title }}</a>
</li>
{% endif %}
{%- set nextPost = search.nextPage(url, "type=article") %}
{%- if nextPost %}
<li class="w-6/12 text-right">
<strong>Next: <a href="{{ nextPost.data.url }}" rel="next">{{ nextPost.data.title }}</a> →</strong>
</li>
{% endif %}
</ul>
{% endif %}
<div class="container p-2 mx-auto mt-6">
{# ==== #}
{# Addding the utteranc Commenting script #}
{# ==== #}
<h1 class="text-center text-2xl my-3"> Comment </h1>
<script src="https://utteranc.es/client.js"
repo="officialrajdeepsingh/Minimalist-blog"
issue-term="pathname"
theme="github-light"
crossorigin="anonymous"
async>
</script>
</div>
The layouts/base.njk
file is the base file for our blog (which I've already explained). The {{ title }}
and {{description}}
both show the markdown file title and description.
To show tags on the article page, I used a for loop. I also showed single and multiple authors with the for loop.
To convert the date into a human-readable format, I used Lume date plugin and wrapped it with a date filter that looks like this: {{ date | date('HUMAN_DATE') }}
. To show all markdown paragraphs, I used {{ content | safe }}
.
For pagination, I used the Lume pagination plugin, and with the search.previousPage(url, "type=article")
function, I showed the next and previous posts on the article page. For comments, I used utteranc.es.
How to Generate a Category Page
In Lume, you create a dynamic category based on article type. Lume also provides inbuilt functionality called a JavaScript template engine that helps you create a dynamic page. It is similar to creating pagination functionality.
In Lume, there's a special file called .tmpl.js
that helps you create a dynamic category.
export const layout = "layouts/category.njk";
export default function* (props) {
const { search }= props
for (const category of search.values("category") ) {
yield {
url: `/category/${category}/`,
title: `Categoryed ${category}`,
type:"category",
category,
};
}
}
In lume search.values()
have a function that helps you find a category using markdown meta tags and sends data into the layout/category.njk
file. It will generate all categories with the following URLs like /category/android/
, /category/android-phone/
, /category/human/
and so on.
How to Generate a Tag Page
Generating a dynamic tags page is similar to a category. Lume provides a special search.tags()
function to generate tags:
export const layout = "layouts/tag.njk";
export default function* ({ search }) {
for (const tag of search.tags()) {
yield {
url: `/tag/${tag}/`,
title: `Tagged ${tag}`,
type: "tag",
tag,
};
}
}
The following code generates all tags with the following URLs like /tag/android/
, /tag/android-phone/
, /tag/human/
and so on.
How to Enable Search Functionality
Lume has many in-built plugins which provide an excellent development experience. You can solve lots of problems with Lume plugins, and they allow you to add and remove features easily.
Lume provides inbuilt search functionality for the site. You enable it with the lume page find plugin.
Add a search bar in lume
How to Install Page Find
The Lume page finds plugin provides you with a search bar. Simply copy the following code and paste it into the _config.ts
file and restart your server.
import pagefind from "lume/plugins/pagefind.ts";
How to configure the page find plugin
You configure the plugin in the _config.ts
fil. You can also change the default config.
// rest of code ...
import lume from "lume/mod.ts";
import pagefind from "lume/plugins/pagefind.ts";
const site = lume();
// config the pagefind plugin with default config
site.use(pagefind());
// or
// change the default config in pagefind plugin
site.use(pagefind({
ui: {
containerId: "search",
showImages: false,
showEmptyFilters: true,
resetStyles: true,
},
}));
export default site;
Lume SEO
Lume has a plugin to help with SEO called metas. With the plugin, you can easily add various SEO-friendly configurations.
How to install metas
You install all plugins within the config.ts
file. Copy the following code and paste it into the config.ts
file, then restart the server.
import metas from "lume/plugins/metas.ts";
How to configure metas
You can configure metas in various ways in the _config.ts
file. See the comments below:
import lume from "lume/mod.ts";
// install metas plugin for SEO
import metas from "lume/plugins/metas.ts";
const site = lume();
// config the metas plugin with default config
site.use(metas());
or
// add custom config
site.use(metas({
defaultPageData: {
title: "title", // Use the `title` value as fallback.
},
}));
export default site;
How to Use the Metas SEO Plugin in Lume
To use the SEO metas plugin, you'll need to create a _data.yml
file in the root of the project folder and paste the following code into it:
metas:
site: Minimalist blog
twitter: "@Official_R_deep"
icon: /images/icon.png
lang: en
generator: true
mergedKeys:
metas: object
The following code helps you create all the various SEO tags for your website, and you can easily extend it with the metas plugin in Lume.
Lume Sitemap
Lume has a plugin called sitemap. This plugin helps you create sitemaps for your blog. With Lume 13 you do not need to create a sitemap manually.
How to install the sitemap plugin
You install all plugins within the config.ts
file. Copy the following code and paste it into the config.ts
file, then restart the server.
import sitemap from "lume/plugins/sitemap.ts";
How to configure the sitemap plugin
You can configure the sitemap plugin in various ways in the _config.ts
file. See the comments below:
import lume from "lume/mod.ts";
import sitemap from "lume/plugins/sitemap.ts";
const site = lume();
site.use(sitemap());
// or
// add custom config
site.use(sitemap({
filename: "my-sitemap.xml", // to change the sitemap filename
query: "indexable=true", // Select only pages with the indexable attribute as true
sort: "date=desc", // To sort by data in ascendent order
}));
export default site;
How to use the sitemap plugin in Lume
You do not need any special file to use the site map plugin. Simply add the plugin after calling the plugin in config.ts
and it'll start working on your site. This creates the sitemap.xml
file and you can change the file name with a custom configuration in _config.ts
file.
How to access the sitemap on the website
You can access the sitemap with the filename, for example by default in the localhost [http://localhost:3000/sitemap.xml](http://localhost:3000/sitemap.xml)
and production [http://my-domain-name/sitemap.xml](http://localhost:3000/sitemap.xml)
.
Lume Plugins
Lume comes with inbuilt plugins, but you can easily add or remove features according to your requirements. You do not need all the stuff on your site – you can configure everything as you wish.
You can add more template engines, minify HTML, CSS, and JavaScript with plugins, enable code highlighting, date manipulation, image manipulation, SVG support, and more.
You can also easily create your own plugins with lume. Lume also provides excellent documentation where you can learn more.
How to Enable Comments
To add comments on your Lume site, I think utteranc.es is the best choice for all static site generators. utteranc.es is an open-source commenting system based on GitHub. It looks like this:
Enable comment
If you want to enable comments on the site, the first step is to install an utterances application on GitHub. Then, copy and paste the following code into the article read file or where you show comments on the site.
<script src="https://utteranc.es/client.js"
repo="officialrajdeepsingh/Minimalist-blog"
issue-term="pathname"
theme="github-light"
crossorigin="anonymous"
async>
</script>
Next, you'll need to change the utterance comment script. The first change in the repo repo="your-github-repo"
name is compulsory. The others are not. You can adjust according to your requirements – for example, changing the theme, issue term, and so on.
To read more about utterance, here's a great article written by Josh Collinsworth.
The best approach is to add utterance comments in lume and then read the GitHub discussion.
How to Use Netlify CMS with Lume
Netlify CMS is an open-source content management system. You can easily integrate Netlify with Lume using the netllify_cms plugin. It is provided by Lume, and you just need to install it and copy/paste the code.
How to Install the Netlify Plugin
Import the Netlify plugin in your _config.ts
file to use it like this:
import lume from "lume/mod.ts";
import netlifyCMS from "lume/plugins/netlify_cms.ts";
const site = lume();
site.use(netlifyCMS());
export default site;
To configure it, you'll need to create a /_data/netlify_cms.yml
file in the root level and then paste the following code after restarting your server:
backend:
name: git-gateway
branch: master
media_folder: statics
collections:
- label: Posts
name: posts
description: List of posts
folder: posts
extension: md
create: true
fields:
- label: Title
name: title
widget: string
- label: Content
name: body
widget: markdown
Netlify will ask you for permissions for the CMS proxy. Type npx netlify-cms-proxy-server
in a terminal, press enter or type y
, and your Netlify CMS will start running locally on http://localhost:3000/admin URL. Now your Lume blog is ready for deployment on Netlify.
How to Deploy Your Blog with Deno Deploy
You can deploy Lume on various platforms such as Deno Deploy, GitHub Pages, Gitlab Pages, Netlify, Vercel, Fleek, AWS Amplify, and Cloudflare Pages. Lume also provides excellent documentation on deployment.
In this article, I'm deploying my Lume blog with Deno Deploy (and we'll also see how to do it with GitHub pages). Deno Deploy is an official platform built by the Deno team to deploy Deno-based applications.
Before deploying your Lume blog on Deno Deploy, make sure you create a server.ts
file in the root level.
import Server from "lume/core/server.ts";
const server = new Server({
port: 8000,
root: `${Deno.cwd()}/_site`,
});
server.start();
console.log("Listening on http://localhost:8000");
Deployment Steps:
- Create an account on Deno Deploy.
- Push your local code to GitHub and then select the
server.ts
file. Deno Deploy automatically creates a site based on theserver.ts
the file. - Make sure to first create a custom
server.ts
file. Then move to the next step. - The easiest way to deploy your site is with GitHub Actions. Create a new
.github/workflows/deno.yml
file in your project root level and paste the following code into it:
name: Deploy
on: [push]
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
permissions:
id-token: write # Needed for auth with Deno Deploy
contents: read # Needed to clone the repository
steps:
- name: Clone repository
uses: actions/checkout@v3
# TODO: add a build step here
- name: Upload to Deno Deploy
uses: denoland/deployctl@v1
with:
project: "minimalist-blog"
entrypoint: "./serve.ts"
How to Deploy Your Blog with Github Pages
GitHub Pages are free static sites you can use to host pages. You can also deploy your Lume blog it. The process of deployment is pretty easy.
To deploy Lume on GitHub pages you need to have GitHub Actions set up.
Deployment Steps
- It's best if you have a GitHub repository so you can convert your local website to GitHub Pages.
- Create a new repo and push all your local code into it.
- Create a new
.github/workflows/deno.yml
in your project root level, then paste the following code into it and push it into the GitHub repo. The GitHub action runs based on thegithub.yml
action and it generates a GitHub page.
name: Publish on GitHub Pages
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Setup Deno environment
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: Build site
run: deno task build
- name: Deploy
uses: crazy-max/ghaction-github-pages@v3
with:
build_dir: _site
env:
GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN_PAGE }}
You need a GitHub token to deploy your Lume website to GitHub pages. This is a required part of the setup. I found a great article written by Davide that can help you learn more about GitHub Actions and how to create one.
GitHub Actions takes two or three minutes to finish hosting your website on GitHub Pages.
Check out the GitHub repository to learn how to configure the GitHub workflow for GitHub pages. You can also see a live demo website on the GitHub page.
A quick note: if you deploy your Lume site on GitHub pages and your image does not show on the website, there are two possible reasons for this:
- If all image names aren't in lowercase, you might get an error. To resolve the error, convert your image names into lowercase with this command:
your.github.com/your-reponame/images/my-image.png
- If you're using the
base_path
andrelative_urls
Lume plugins in your project andrelative_urls
is redundant, and then you'll need to remove therelative_urls
plugin in your project. Your image should now work fine.
Conclusion
Lume is an easy-to-learn and feature-rich static site generator. You can do anything you imagine with it. Lume gives you a lot of freedom with the code.
The Lume community is not as big as those of Hugo, 11ty, Jekyll, and other tools. But, the Lume maintainers actively reply to everybody who comments in the GitHub discussion. Without a strong community, this tool should be able to create a strong impact.
One challenge with Lume is that it's tough to get started for beginners and is more suited to intermediate and advanced developers. If you're jumping right into using Lume as a beginner, you might struggle with a lack of background knowledge about how static site generators work.
Because of this, it's helpful to have a little bit of knowledge about Nuckjunks, JSX, and other template engines that work based on markdown. Once you gain this experience, then you'll easily be able to use Lume to design your markdown-based blog.
I recommend using the lume MDX plugin for markdown. You can use JSX-based components inside the markdown file, and you can create beautiful code blocks, tip blocks, and so on.
I highly encourage all developers to try Lume out. If you have problems with Lume, you can reach out to its creator on the GitHub discussion and the Discord server.
If your course is about Computer science, Bioinformatics, and Biotechnology. You can join my free newsletter.
Subscribe to my newsletter
Read articles from Rajdeep Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rajdeep Singh
Rajdeep Singh
JavaScript || Reactjs || Nextjs || Rust || Biotechnology || Bioinformatic || Front-end Developer || Author || https://ko-fi.com/officialrajdeepsingh