It will ask you the project name, author name, project path and if you want to add a basic blog. I chose the project name animeshdotblog-model and it will automatically assume the project path will be a folder with the project name the current path. Of course, you can change it.

Configuration

Change into the new project path and open the editor.

cd animeshdotblog-model
code .

Init a git repository, add a .gitignore file and add the /public to it. By default, the /public folder holds the artifacts after the build and we don't need it in version control. Add and commit all the files.

This will run the site on port 5000. You could specify a port by adding -p PORT at the end. To automatically open the browser after serving the site, add --browse at the end.

First Run

The landing page is generated from the contents.lr file at the root of content folder. Inside the content folder, you also have folders for about, blog and projects with a contents.lr file inside each of them. As explained earlier, these contents.lr files at the root of each folder are just markdown files that Lektor expects to build into the index.html for that folder.

The about/contents.lr file is built into about/index.html so that when you visit http://localhost:5000/about you would see the contents of your about page. Pretty easy and intuitive right?

We have added a new field title and updated the label attribute in [model] section to {{ this.title}}. I am not really sure why the title is empty when it is just label = Blog.

Now we can move onto writing our first post.

Authoring posts

Click the pencil icon in the corner to navigate to the admin.

Lektor admin

Lektor has a very minimalistic admin designed around the actions necessary for the current view. Lektor admin doesn't support theming at the moment, but it gets its job done. You can see the sub pages of the root About, Hello Website and Projects. Though Hello Website is the only blog post, it still shows the other sub folders of the root.

Click on the plus icon beside the Home link in the top left corner to add a blog post. Enter the title of the post and the ID (id or URL or slug) field automatically builds off of the title. Click on the Add Child Page button to open the post for editing.

Add post

This is the edit view of the post just created:

Edit post

Fill in your author and twitter handle. Unless your template displays these two fields you don't have to fill them. Select publication date and click on Save Changes. Your post is now created and you will be shown the post preview page inside admin.

Preview post

Now check your landing page again. You have a new post:

New post

Customization

The quickstart that Lektor provides is an extremely simple website. We made a few modifications to this to understand how the content is used and organized by Lektor. Let us make a few customizations.

Post Summary

Initially, I used to have only the post title in my static site.

Simplest landing page

I wanted a summary of the post below the post title, generated automatically, in this fashion.

Simple landing page

I found a plugin for this called markdown-excerpt which will extract the first paragraph from the body of the post. We have to update the part where the body of a post is rendered in the blog.html macro or wherever you have the blog post template with the filter excerpt like this:

{{ post.body|excerpt }}

When I started importing old posts from my previous blogs, I found that some posts did not have a good first paragraph. To change the first paragraphs for all these posts is tedious and some posts have to be adjusted for the change in the first paragraph.

Though it is not a big deal, this also means that {{ post.body|excerpt }} is parsing the entire posts' body N times on my landing page, given N posts on the landing page. It felt a bit excessive. I wanted another option.

I created a new field, excerpt in the blog post model blog-post.ini:

[fields.excerpt]
label = Excerpt
type = markdown
size = normal

This creates a new field that can accept markdown text.

New excerpt field in admin

Add some text there and save the post. The contents.lr for the post has an updated field now

excerpt: First Post

Then surround the {{ post.body }} part in the blog.html macro with the following HTML:

Categories

The official guide does a good job explaining how to go about setting up categories for your projects. We can easily adapt this for blog posts.

First, we need to create two new models, one for blog categories blog-categories.ini which will represent all categories available and the other for blog category blog-category.ini which will represent the individual category. Blog categories model will be the parent of blog category.

Since Lektor considers any sub folder under current folder as its child, categories would not have its associated posts as its children by default. To get around this, we use an attribute replaced_with in the [children] section which makes a query to the landing page path and returns a set of items that have this category.

Next, we update the blog post model blog-post.ini to have a new field, categories, so that it shows up in the admin when a post is in the edit view.

Here we are using site.query to fill the categories from the folder blog-categories.

Now that models are ready, let us create a folder blog-categories and set its contents.lr as such:

_model: blog-categories
_slug: /categories

The _slug will be /blog-categories by default, but you can change it to categories to have a simpler URL. Go to admin and now you can see a sub page for categories.

Blog Categories link on the left

Click on it and you can see that it is just a regular page on the site.

Categories Page Edit View

Click on the plus sign on the top left to add a sub page to Blog Categories

Add Category

Add a few more categories in this way and you can see them on the side. After adding each category we see an error like this:

Template not found

This is because we do not have templates setup for blog category and categories.

Before adding the templates, we need to add two macros, one to fetch a list of posts belonging to a category, render_post_list, and the other to render a list of all categories available, render_cat_nav. Save them into a new categories.html in the templates/macros folder.

In macros, we can use the set statement to assign a variable to an expression. In the render_cat_nav macro, we get the count of all categories available. In the render_cat_nav macro, while looping over the available posts in the current category, we are also getting a count of the available posts for that category.

Add two templates blog-categories.html and blog-category.html. After adding these two empty templates, we don't see the error anymore. We need to inherit from layout.html and update them as follows.

Open up the blog posts in admin and select categories as needed and save them.

Categories on post

Also, add the categories link in the navigation. Now you have the categories ready.

Categories Page

Click on any category to see the list of posts in that category.

Specific category

Comments

I had setup comments on my static site using the official plugin lektor-disqus. It is fairly easy to setup comments once you have your account ready with Disqus. Identify the short name from the Disqus admin and add into the config file for it as per the documentation.

I have removed the comments recently as I am experimenting with having comments using gitlab issues API.

References

This example

The quickstart example, animeshdotblog-model, we worked on in this post is available at: