Theme Structure
Understanding the folder structure of a FeedGen CMS theme.
Directory Layout
my-theme/
├── theme.json # Theme manifest (required)
├── index.js # Theme entry point (required)
│
├── views/ # Templates (required)
│ ├── layouts/
│ │ └── main.html # Main layout wrapper
│ │
│ ├── pages/ # Page templates
│ │ ├── home.html # Homepage
│ │ ├── post-detail.html # Single post
│ │ ├── posts.html # Posts archive
│ │ ├── category-detail.html # Single category
│ │ ├── categories.html # Categories list
│ │ ├── author-detail.html # Author profile
│ │ ├── authors.html # Authors list
│ │ ├── tag.html # Tag archive
│ │ ├── tags.html # Tags list
│ │ ├── search.html # Search results
│ │ ├── contact.html # Contact page
│ │ ├── about.html # About page
│ │ └── error.html # Error page (404, etc.)
│ │
│ └── partials/ # Reusable components
│ ├── head.html
│ ├── header.html
│ ├── footer.html
│ ├── post-card.html
│ ├── pagination.html
│ └── sidebar.html
│
└── assets/ # Static files
├── css/
│ └── main.css
├── js/
│ └── main.js
├── images/
└── icons/Required Files
theme.json
The manifest file that defines your theme:
theme.json
{
"name": "My Theme",
"version": "1.0.0",
"description": "Theme description",
"author": "Your Name",
"license": "MIT",
"screenshots": ["screenshot.png"],
"tags": ["blog", "minimal", "responsive"],
"supports": {
"customLogo": true,
"customColors": true,
"widgets": ["sidebar", "footer-1", "footer-2"],
"menus": ["primary", "footer", "mobile"]
},
"assets": {
"css": ["css/main.css"],
"js": ["js/main.js"],
"icons": "assets/icons/symbols.svg"
},
"variables": {
"colors": {
"--primary-color": "#3b82f6",
"--secondary-color": "#10b981",
"--text-color": "#1f2937",
"--background-color": "#ffffff"
}
}
}index.js
The entry point that can provide custom helpers:
index.js
module.exports = function(sdk) {
return {
// Custom template helpers
helpers: {
// Example: Custom date formatter
customDate: (date) => {
return new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
},
// Example: Reading time calculator
readingTime: (content) => {
const words = content.split(/\s+/).length;
const minutes = Math.ceil(words / 200);
return `${minutes} min read`;
}
}
};
};views/layouts/main.html
The main layout that wraps all pages:
views/layouts/main.html
<!DOCTYPE html>
<html lang="{{ settings.language || 'en' }}">
<head>
{{{ include('partials/head') }}}
</head>
<body class="{{ bodyClass || '' }}">
{{{ hooks.do('theme_body_start') }}}
{{{ include('partials/header') }}}
<main id="main">
{{{ content }}}
</main>
{{{ include('partials/footer') }}}
{{{ hooks.do('theme_body_end') }}}
</body>
</html>Page Templates
Each page template receives specific variables:
| Template | Variables |
|---|---|
home.html | latestPosts, featuredPosts, categories, sections |
post-detail.html | post, relatedPosts, author, category |
posts.html | posts, pagination, total |
category-detail.html | category, posts, pagination |
author-detail.html | author, posts, pagination |
search.html | query, results, pagination |
error.html | statusCode, message |
Partials
Reusable components included with include():
{# Include a partial #}
{{{ include('partials/post-card', { post: post }) }}}
{# Include with multiple variables #}
{{{ include('partials/pagination', {
current: pagination.page,
total: pagination.pages,
baseUrl: '/posts'
}) }}}Assets
Static files are served from /themes/your-theme/assets/:
{# CSS #}
<link rel="stylesheet" href="/themes/my-theme/assets/css/main.css">
{# JavaScript #}
<script src="/themes/my-theme/assets/js/main.js"></script>
{# Images #}
<img src="/themes/my-theme/assets/images/logo.png">
{# SVG Icons #}
<svg class="icon">
<use href="/themes/my-theme/assets/icons/symbols.svg#arrow-right"></use>
</svg>Next Steps
- Template Syntax - Learn the templating language
- Template Variables - All available data
- Examples - Complete theme examples