jekcms Theme File Structure: Why We Chose This Architecture

Which files a jekcms theme contains, which template each page loads, and why we use plain PHP instead of a template engine.

jekcms Theme File Structure: Why We Chose This Architecture, jekcms blog cover

Which files a jekcms theme contains, which template each page loads, and why we use plain PHP instead of a template engine.

A jekcms theme is a single folder, and every file in it has a specific job. This post walks through that folder, explains which template the site loads for each page, and why we chose plain PHP templates.

Inside the Folder

All the bundled themes use the same layout. Here is the News theme as an example:

themes/news/
+-- theme.json        # theme name, version, colours and fonts
+-- functions.php     # theme-specific helper functions
+-- screenshot.png    # the preview shown in the panel
+-- demo-content.php  # sample content
+-- templates/        # page templates
|   +-- header.php, footer.php
|   +-- index.php, single.php, page.php, archive.php
|   +-- search.php, 404.php, contact.php, legal.php
+-- partials/         # reusable pieces
|   +-- post-card.php, pagination.php, sidebar.php, comments.php
+-- sections/         # blocks arranged in the layout editor
+-- assets/css, assets/js

theme.json is the theme's identity card. The theme customiser in the panel reads its colour and font options from this file, so changing a default colour does not require touching the CSS.

Which Page Loads Which Template

jekcms has no long template hierarchy like WordPress. Each page type goes to one file: posts open with single.php, pages with page.php, category and tag archives with archive.php and search results with search.php. There is 404.php for missing addresses and legal.php for legal pages. When you wonder why a page looks the way it does, you always know which file to open.

Partials and Sections

Files in partials/ are used by more than one template. To change the post card you edit only post-card.php, and the cards on the homepage, in archives and in search all change together. You call a partial from a template with get_template_part('post-card'); the function looks in partials/ first and then in templates/.

The sections/ folder holds the homepage and sidebar blocks: the hero, latest posts, category sections, the newsletter box and so on. The drag-and-drop layout editor in the panel arranges these files, so turning a section off or moving it needs no code.

functions.php

Theme-specific helper functions live in functions.php. In the News theme these are the functions that fetch breaking news, the most-read posts or the latest posts in a category. They use the core get_posts() and get_categories() functions, which return plain PHP arrays rather than objects. Arrays cache easily and read as $post['title'] in a template.

For people coming from WordPress, add_action, do_action and apply_filters are defined with the same names, but they are not a full plugin hook system. Their main purpose is to keep small snippets written the WordPress way from throwing errors. SEO tags, schema and analytics code are printed into the template by output_head_scripts().

Why Not a Template Engine

Template engines such as Twig and Blade compile templates to PHP first and write them to a cache folder. On shared hosting, the permissions of that folder and stale cache files cause frequent trouble. Plain PHP templates have no such step: the change shows on the site as soon as you edit the file, and anyone who knows PHP can read the template.

CSS and JavaScript Files

A theme's styles and scripts live in assets/css/ and assets/js/. jekcms adds each file's last-modified time to its address as a ?v= parameter. Browsers can keep the file cached for a long time, and when you update it visitors get the new version straight away.

When Building a Theme

  • Start a new theme by copying one of the bundled themes; the folder layout and theme.json fields come ready.
  • Put repeated HTML in partials/, not in the templates.
  • Keep homepage blocks in sections/ so they can be arranged in the layout editor.
  • Turn on DEBUG_MODE while developing to see undefined-variable warnings early.

Written by

Celil Uyanıkoğlu

Computer engineer with 25+ years in IT. He builds jekcms and runs his own network of content sites on it - every guide published here is tried on those live installs first.

See all posts →

Choose a Licence

Annual licence with a discounted first year; updates and support included. Setup in 30 minutes.

View Pricing
  • Setup and live in 30 minutes
  • 14 professional themes
  • AVIF/WebP image optimization
  • Automatic SEO - Sitemap, Schema.org
  • ZeroTrack cookieless analytics

Be the first to know

New features, release notes and CMS guides. We send a couple of emails a month.