Creating an HTMLy theme is not as difficult as you might think. To make this process faster, I asked Copilot to create an HTML template using Bootstrap 5. Copilot creates two files, index.html (containing a list of posts) and post.html (single post).

For a preview of these two files, check my github pages. Please download these files first before we start the theme creation process, download here.

This time let's create a theme with the name: starter and we will port the HTML template that we downloaded earlier to the HTMLy compatible theme.

Theme Structure

Here is the structure of the theme we will create:

themes
└── starter
    ├── 404.html.php
    ├── 404-search.html.php
    ├── layout.html.php
    ├── main.html.php
    ├── no-posts.html.php
    ├── post.html.php
    ├── profile.html.php
    └── static.html.php

The PHP files above are the required files for our HTMLy theme, so later we have to create them one by one.

First create a starter folder inside the themes folder.

Theme Layout

In HTMLy, the theme layout is layout.html.php file. In other CMS it could be for example: index.php

  1. Create layout.html.php in the starter folder.

  2. Open index.html with a text editor, select all, copy and paste all the contents into layout.html.php and save it.

  3. Now try go to admin/config page, select starter for the theme and save. The theme should have changed to the theme we created earlier.

The next step is to replace the existing elements with elements from HTMLy.

HTML lang Attribute

<html lang="en">

Replace it with:

<html lang="<?php echo blog_language();?>">

HTML metatags

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index Page</title>

Replace it with:

<?php echo head_contents();?>
<?php echo $metatags;?>

Toolbar

Let's add a toolbar to make navigation easier. Right after <body> tag add the following:

<?php if (login()):?>
    <?php echo toolbar();?>
<?php endif;?>

Branding

<a class="navbar-brand" href="index.html">HTMLy</a>

Replace it with:

<a class="navbar-brand" href="<?php echo site_url();?>"><?php echo blog_title();?></a>

Menu

<div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav ms-auto">
        <li class="nav-item"><a class="nav-link" href="#">About</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Blog</a></li>
        <li class="nav-item"><a class="nav-link" href="#"><i class="fas fa-search"></i></a></li>
    </ul>
</div>

Replace it with:

<div class="collapse navbar-collapse" id="navbarNav">
    <?php echo menu('navbar-nav ms-auto');?>
</div>

Footer

<p>© 2025 HTMLy Blog | All rights reserved</p>

Replace it with:

<p><?php echo copyright();?></p>

Try reloading the web page, the changes you made should now be visible. Let's continue the next step, which is creating blog posts list.

Posts List

To display a list of posts dynamically with pagination, for example on the homepage, category, tag and others, HTMLy uses main.html.php. So create this file inside starter folder.

Open layout.html.php again, and analyze which ones to move to main.html.php.

Cut and paste the following to main.html.php and save it.

<h1 class="blog-title mt-4 pt-2 text-center">Lorem Ipsum Blog</h1>
<div class="mb-4 text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>

<div class="blog-entry pt-4 pb-4">
    <p>APR 16, 2025</p>
    <h2><a href="post.html">Lorem Ipsum Article 1</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl....</div>
</div>

<div class="blog-entry pt-4 pb-4">
    <p>APR 7, 2025</p>
    <h2><a href="post.html">Lorem Ipsum Article 2</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl...</div>
</div>
<div class="pagination-container mt-5 text-center">
    <nav>
        <ul class="pagination justify-content-center">
            <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
            <li class="page-item active"><a class="page-link" href="#">1</a></li>
            <li class="page-item"><a class="page-link" href="#">2</a></li>
            <li class="page-item"><a class="page-link" href="#">Next</a></li>
        </ul>
    </nav>
</div>

And go back to layout.html.php again, in the place where we cut it earlier, put:

<?php echo content();?>

Then it will become:

<div class="col-lg-10 mx-auto">
    <?php echo content();?>
</div>

Note: The content() function in layout.html.php is very important so don't miss it. This function is used to display the content of all existing templates.

For example, if we are on the posts collection page (category, tag, etc.), it will display content from main.html.php, in single post it will display post.html.php and so on.

Now it's time to change main.html.php with variables from HTMLy. Open main.html.php and do the following steps:

Posts List Info

<h1 class="blog-title mt-4 pt-2 text-center">Lorem Ipsum Blog</h1>
<div class="mb-4 text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>

Replace with the following:

<h1 class="blog-title mt-4 pt-2 text-center"><?php echo $taxonomy->title;?></h1>
<div class="mb-4 text-center"><?php echo $taxonomy->body;?></div>

Blog Posts List

<div class="blog-entry pt-4 pb-4">
    <p>APR 16, 2025</p>
    <h2><a href="post.html">Lorem Ipsum Article 1</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl....</div>
</div>

<div class="blog-entry pt-4 pb-4">
    <p>APR 7, 2025</p>
    <h2><a href="post.html">Lorem Ipsum Article 2</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl...</div>
</div>

Replace it with:

<?php foreach ($posts as $p):?>
<div class="blog-entry pt-4 pb-4">
    <p><?php echo format_date($p->date);?></p>
    <h2><a href="<?php echo $p->url;?>"><?php echo $p->title;?></a></h2>
    <div><?php echo $p->description;?> [...]</div>
</div>
<?php endforeach;?>

Pagination

<div class="pagination-container mt-5 text-center">
    <nav>
        <ul class="pagination justify-content-center">
            <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
            <li class="page-item active"><a class="page-link" href="#">1</a></li>
            <li class="page-item"><a class="page-link" href="#">2</a></li>
            <li class="page-item"><a class="page-link" href="#">Next</a></li>
        </ul>
    </nav>
</div>

Replace it with:

<?php if (!empty($pagination)):?>
<div class="pagination-container mt-5 text-center">
    <nav class="d-inline-flex align-items-center"><?php echo $pagination['html'];?></nav>
</div>
<?php endif;?>

For the collection of posts is done. If you reload the page, the front page should display a list of posts.

Next is to create a template for a single post.

Single Post

For single posts, HTMLy uses post.html.php. Create this file inside the starter folder.

Now go back to the post.html file that we downloaded earlier along with index.html.

Edit post.html, try to analyze it, you will find the content of the post consisting of title, meta, main content, related posts and post navigation.

Copy and paste the following into post.html.php:

<h1 class="post-title">Lorem ipsum dolor sit amet</h1>
<p class="post-meta mt-3">Published on Feb 20, 2025 by <a href="#">@danpros</a></p>
<div class="post-content mt-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl, ut blandit metus mauris id ipsum. Integer convallis consequat nibh sed finibus.
</div>

<div class="taxonomy mt-3 h6">
    <span class="category me-2 text-small"><strong>Filled in:</strong> My Category</span>
    <span class="tags"><strong>Tagged:</strong> My Tag</span>
</div>

<div class="related-posts mt-4">
    <h3>Related Posts</h3>
    <ul>
        <li><a href="#">Lorem ipsum</a></li>
        <li><a href="#">Dolor sit amet</a></li>
        <li><a href="#">Fusce tincidunt neque purus</a></li>
    </ul>
</div>

<div class="mt-5 d-block clearfix">
    <a href="#" class="btn btn-outline-secondary float-start">← Previous Post</a>
    <a href="#" class="btn btn-outline-secondary float-end">Next Post →</a>
</div>

Let's change them one by one to the variables provided by HTMLy.

Title

<h1 class="post-title">Lorem ipsum dolor sit amet</h1>

Replace it with:

<h1 class="post-title"><?php echo $p->title;?></h1>

Post Meta

<p class="post-meta mt-3">Published on Feb 20, 2025 by <a href="#">@danpros</a></p>

Replace it with:

<p class="post-meta mt-3">Published on <?php echo format_date($p->date);?> by <a href="<?php echo $p->authorUrl;?>"><?php echo $p->authorName;?></a></p>

Post Body

<div class="post-content mt-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tincidunt neque purus, in viverra nisl ultricies ut. Quisque interdum, purus non fringilla pharetra, tellus libero vehicula nisl, ut blandit metus mauris id ipsum. Integer convallis consequat nibh sed finibus.</div>

Replace it with:

<div class="post-content mt-4"><?php echo $p->body;?></div>

Category and Tag

<div class="taxonomy mt-3 h6">
    <span class="category me-2 text-small"><strong>Filled in:</strong> My Category</span>
    <span class="tags"><strong>Tagged:</strong> My Tag</span>
</div>

Replace it with:

<div class="taxonomy mt-4 h6">
    <span class="category me-2 text-small"><strong>Filled in:</strong> <?php echo $p->category;?></span>
    <span class="tags"><strong>Tagged:</strong> <?php echo $p->tag;?></span>
</div>

Related Posts

<div class="related-posts mt-4">
    <h3>Related Posts</h3>
    <ul>
        <li><a href="#">Lorem ipsum</a></li>
        <li><a href="#">Dolor sit amet</a></li>
        <li><a href="#">Fusce tincidunt neque purus</a></li>
    </ul>
</div>

Replace it with:

<div class="related-posts mt-4">
    <h3>Related Posts</h3>
    <?php echo get_related($p->related);?>
</div>

Post Navigation

<div class="mt-5 d-block clearfix">
    <a href="#" class="btn btn-outline-secondary float-start">← Previous Post</a>
    <a href="#" class="btn btn-outline-secondary float-end">Next Post →</a>
</div>

Replace it with:

<div class="mt-5 d-block clearfix">
    <?php if (!empty($next)): ?>
    <a href="<?php echo $next['url'];?>" class="btn btn-outline-secondary float-start">← Next Post</a>
    <?php endif;?>
    <?php if (!empty($prev)): ?>
    <a href="<?php echo $prev['url'];?>" class="btn btn-outline-secondary float-end">Previous Post →</a>
    <?php endif;?>
</div>

Try visiting any blog post to test it. Next is to create a template for the static page.

Static Page

For static pages, HTMLy uses static.html.php. Create this file in the starter folder.

The contents of static.html.php are almost the same with post.html.php (single post template), the only difference is that static pages do not have a publication date, category, tag, and related posts widget.

So open the post.html.php file, copy the entire contents and paste it into static.html.php and delete the following elements:

Remove Post Meta

<p class="post-meta mt-3">Published on <?php echo format_date($p->date);?> by <a href="<?php echo $p->authorUrl;?>"><?php echo $p->authorName;?></a></p>

Remove Category and Tag

<div class="taxonomy mt-4 h6">
    <span class="category me-2 text-small"><strong>Filled in:</strong> <?php echo $p->category;?></span>
    <span class="tags"><strong>Tagged:</strong> <?php echo $p->tag;?></span>
</div>

Remove Related Posts

<div class="related-posts mt-4">
    <h3>Related Posts</h3>
    <?php echo get_related($p->related);?>
</div>

Here is the final result after the unnecessary ones are removed in the static.html.php template:

Final Result

<h1 class="post-title"><?php echo $p->title;?></h1>
<div class="post-content mt-4"><?php echo $p->body;?></div>

<div class="mt-5 d-block clearfix">
    <?php if (!empty($next)): ?>
    <a href="<?php echo $next['url'];?>" class="btn btn-outline-secondary float-start">← Next Post</a>
    <?php endif;?>
    <?php if (!empty($prev)): ?>
    <a href="<?php echo $prev['url'];?>" class="btn btn-outline-secondary float-end">Previous Post →</a>
    <?php endif;?>
</div>

Next is the profile page, the file is profile.html.php.

Profile Page

This profile.html.php template is used when we visit the profile page. Please create this file in the starter folder.

The content of profile.html.php is almost similar to main.html.php. Open and copy paste the contents of main.html.php to profile.html.php.

Here's what needs to be changed:

<h1 class="blog-title mt-4 pt-2 text-center"><?php echo $taxonomy->title;?></h1>
<div class="mb-4 text-center"><?php echo $taxonomy->body;?></div>

Replace it with:

<h1 class="blog-title mt-4 pt-2 text-center"><?php echo $author->title;?></h1>
<div class="mb-4 text-center"><?php echo $author->body;?></div>

If you visit the profile page then there is now information about the author and a list of posts.

Additional Templates

The next three templates are 404.html.php, 404-search.html.php, and no-posts.html.php, quite explicit in name so it is easy to guess what page they are for.

You can add any message on these pages.

404 Not Found

This page uses the 404.html.php template, please create this template, and its content very flexible, here I just put a title using the h1:

<h1>Error 404!</h1>

Search Not Found

This page uses the 404-search.html.php template. Please create one and the content:

<h1>Search Not Found!</h1>

No Posts

Displays a message if a published post is not available. The file is no-posts.html.php

<h1>No Published Posts Found!</h1>

Self Hosted Resources

Perhaps you don't want to use a CDN for CSS/JS or inline CSS/JS, and want to put it in your theme folder. In HTMLy there is a theme_path() variable, so you can use this to direct it to your theme folder.

For example, if you want to move inline CSS to a CSS file, first create a css folder in the starter folder and put your CSS file here, eg. style.css.

themes
└── starter
    ├── css
    │   └── style.css
    ├── 404.html.php
    ├── 404-search.html.php
    ├── layout.html.php
    ├── main.html.php
    ├── no-posts.html.php
    ├── post.html.php
    ├── profile.html.php
    └── static.html.php

Open layout.html.php and add the following line in <head>

<link href="<?php echo theme_path();?>css/style.css" rel="stylesheet">

Edit Link

You can add edit links in posts or on static pages. Add this to post.html.php or static.html.php. I put it before the title:

<?php if (authorized($p)):?>
   <span><a href="<?php echo $p->url;?>/edit?destination=post">Edit</a></span>
<?php endif;?>

You can also add it in main.html.php and profile.html.php. Add it inside a foreach loop, for example after the description.

Congratulations, you have created your first HTMLy theme. For the final result of the theme above, you can download it here. I added the following lines in each file:

<?php if (!defined('HTMLY')) die('HTMLy'); ?>