Create a Theme
This tutorial walks you through creating a basic Basker theme from scratch. By the end, you’ll have a working theme with a layout, page template, content block, and theme settings.
What You’ll Learn
Section titled “What You’ll Learn”- Create a theme file structure
- Build a base layout with required Liquid objects
- Create a page template
- Add a reusable content block
- Configure global theme settings
- Package and deploy your theme
Prerequisites
Section titled “Prerequisites”- Basic knowledge of HTML and CSS
- Familiarity with templating concepts
- Access to a Basker CMS instance
Theme File Structure
Section titled “Theme File Structure”A minimal Basker theme requires these directories and files:
Directorytheme/
Directorylayouts/
- default.liquid (required)
Directorytemplates/
- page.liquid
Directoryblocks/
- content.liquid
- settings_schema.json
Step 1: Create the Base Layout
Section titled “Step 1: Create the Base Layout”The layout is the foundation of your theme. Create layouts/default.liquid with the required Liquid objects:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ page.title | default: 'My Site' }}</title> {{ content_for_header }} </head> <body> <header> <nav> <a href="/">Home</a> </nav> </header>
<main> {{ content_for_layout }} </main>
<footer> <p>© {{ 'now' | date: '%Y' }} My Site</p> </footer> </body></html>Step 2: Create a Page Template
Section titled “Step 2: Create a Page Template”Templates render specific content types. Create templates/page.liquid to render pages:
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}<article class="page"> <header class="page-header"> <h1>{{ page.title }}</h1>
{% if page.description %} <p class="lead">{{ page.description }}</p> {% endif %} </header>
<div class="page-content"> {% stageblocks page %} </div></article>{% endcapture %}
{% schema %}{ "name": "page", "settings": [], "blocks": ["content"]}{% endschema %}Key elements:
{% layout %}specifies which layout to use{% capture content_for_layout %}wraps the template content{{ page.title }}accesses page properties{% stageblocks page %}renders content blocks{% schema %}defines template settings and allowed blocks
Step 3: Add a Content Block
Section titled “Step 3: Add a Content Block”Blocks are reusable components editors can add to pages. Create blocks/content.liquid:
<section id="{{ block.id }}" class="content-block"> {% if block.title %} <h2>{{ block.title }}</h2> {% endif %}
{% if block.content %} <div class="prose"> {{ block.content_html }} </div> {% endif %}</section>
{% schema %}{ "name": "content", "singular": "Content", "plural": "Content Blocks", "label": "Content Block", "settings": [ { "type": "text", "name": "title", "label": "Title" }, { "type": "richtext", "name": "content", "label": "Content" } ]}{% endschema %}Key elements:
{{ block.id }}provides a unique identifier for the block instance{{ block.title }}accesses the text field value{{ block.content_html }}renders richtext as HTML (note the_htmlsuffix)- The schema defines the block name and its configurable fields
Step 4: Configure Theme Settings
Section titled “Step 4: Configure Theme Settings”Global settings let administrators customize the theme. Create settings_schema.json:
[ { "name": "colors", "label": "Colors", "settings": [ { "type": "color", "name": "primary", "label": "Primary Color", "default": "#0066cc" }, { "type": "color", "name": "background", "label": "Background Color", "default": "#ffffff" } ] }, { "name": "typography", "label": "Typography", "settings": [ { "type": "select", "name": "font_family", "label": "Font Family", "options": [ { "label": "System", "value": "system-ui" }, { "label": "Serif", "value": "Georgia, serif" }, { "label": "Sans-serif", "value": "Arial, sans-serif" } ], "default": "system-ui" } ] }]Access these settings in your layout:
<style> :root { --color-primary: {{ settings.colors.primary }}; --color-background: {{ settings.colors.background }}; --font-family: {{ settings.typography.font_family }}; }</style>Step 5: Package and Deploy
Section titled “Step 5: Package and Deploy”To deploy your theme:
-
Create a ZIP file containing your theme directory structure:
theme.zip└── theme/├── layouts/├── templates/├── blocks/└── settings_schema.json -
Upload the ZIP file through the Basker admin panel under Themes
-
Activate your theme to make it live
Complete Example
Section titled “Complete Example”Here’s the final file structure with all files:
Directorytheme/
Directorylayouts/
- default.liquid
Directorytemplates/
- page.liquid
Directoryblocks/
- content.liquid
- settings_schema.json
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ page.title | default: 'My Site' }}</title> {{ content_for_header }} <style> :root { --color-primary: {{ settings.colors.primary }}; --color-background: {{ settings.colors.background }}; --font-family: {{ settings.typography.font_family }}; } body { font-family: var(--font-family); background-color: var(--color-background); margin: 0; padding: 0; } header, footer { padding: 1rem 2rem; background: #f5f5f5; } main { padding: 2rem; max-width: 800px; margin: 0 auto; } .prose { line-height: 1.6; } </style> </head> <body> <header> <nav><a href="/">Home</a></nav> </header> <main> {{ content_for_layout }} </main> <footer> <p>© {{ 'now' | date: '%Y' }} My Site</p> </footer> </body></html>{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}<article class="page"> <header class="page-header"> <h1>{{ page.title }}</h1> {% if page.description %} <p class="lead">{{ page.description }}</p> {% endif %} </header> <div class="page-content"> {% stageblocks page %} </div></article>{% endcapture %}
{% schema %}{ "name": "page", "settings": [], "blocks": ["content"]}{% endschema %}<section id="{{ block.id }}" class="content-block"> {% if block.title %} <h2>{{ block.title }}</h2> {% endif %} {% if block.content %} <div class="prose"> {{ block.content_html }} </div> {% endif %}</section>
{% schema %}{ "name": "content", "singular": "Content", "plural": "Content Blocks", "label": "Content Block", "settings": [ { "type": "text", "name": "title", "label": "Title" }, { "type": "richtext", "name": "content", "label": "Content" } ]}{% endschema %}[ { "name": "colors", "label": "Colors", "settings": [ { "type": "color", "name": "primary", "label": "Primary Color", "default": "#0066cc" }, { "type": "color", "name": "background", "label": "Background Color", "default": "#ffffff" } ] }, { "name": "typography", "label": "Typography", "settings": [ { "type": "select", "name": "font_family", "label": "Font Family", "options": [ { "label": "System", "value": "system-ui" }, { "label": "Serif", "value": "Georgia, serif" }, { "label": "Sans-serif", "value": "Arial, sans-serif" } ], "default": "system-ui" } ] }]Next Steps
Section titled “Next Steps”Now that you have a basic theme, explore the architecture documentation to learn more:
- Layouts - Learn about layout structure and parameters
- Templates - Discover all available templates and their objects
- Blocks - Create more complex content blocks
- Input Settings - Explore all available field types
- Liquid Reference - Master the Liquid templating language