- Remove legacy themes (black-orange, minimal) with old .tpl structure - Create new minimal theme with proper qsgen3 structure: - Complete layouts/ directory with all required templates - Modern CSS with responsive design and clean styling - Proper theme documentation in README.md - Update THEMES-HOWTO.md to accurately reflect theme behavior: - Clarify complete layout override (no fallback to defaults) - Document included minimal theme example - Correct layout processing documentation - Update site.conf to use new minimal theme CSS path - Ensure themes are complete packages when specified
866 lines
22 KiB
Markdown
866 lines
22 KiB
Markdown
# qsgen3 Themes How-To Guide
|
|
|
|
This guide explains how to create and customize themes for qsgen3, based on how the code actually interprets and processes themes.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Theme Basics](#theme-basics)
|
|
2. [Theme Directory Structure](#theme-directory-structure)
|
|
3. [Creating Your First Theme](#creating-your-first-theme)
|
|
4. [Layout Templates](#layout-templates)
|
|
5. [Static Assets (CSS, JS, Images)](#static-assets-css-js-images)
|
|
6. [Theme Configuration](#theme-configuration)
|
|
7. [Advanced Theme Features](#advanced-theme-features)
|
|
8. [Theme Best Practices](#theme-best-practices)
|
|
9. [Troubleshooting](#troubleshooting)
|
|
|
|
## Theme Basics
|
|
|
|
### What is a Theme?
|
|
|
|
A qsgen3 theme is a collection of layout templates and static assets (CSS, JavaScript, images) that define the visual appearance and structure of your generated website. Themes allow you to:
|
|
|
|
- Customize the HTML structure of your pages
|
|
- Apply custom CSS styling
|
|
- Include JavaScript functionality
|
|
- Override default layouts with theme-specific designs
|
|
|
|
### How qsgen3 Processes Themes
|
|
|
|
When you specify a theme in your `site.conf`, qsgen3 follows this processing order:
|
|
|
|
1. **Theme Detection**: Looks for the theme directory at `themes/{theme_name}/`
|
|
2. **Layout Override**: If the theme has a `layouts/` directory, it **completely replaces** the default layouts
|
|
3. **Static File Copying**: Copies static files from both root `static/` and theme `static/` directories
|
|
4. **CSS Linking**: Automatically links the theme's main CSS file in generated HTML
|
|
|
|
**Important**: When a theme provides layouts, qsgen3 uses **only** the theme's layouts. There is no fallback to default layouts for individual templates. If you want to use a theme, ensure it provides all necessary layout files (`index.html`, `post.html`, `page.html`, `rss.xml`).
|
|
|
|
### Included Example Theme
|
|
|
|
qsgen3 includes a `minimal` theme that demonstrates the proper theme structure:
|
|
|
|
```
|
|
themes/minimal/
|
|
├── layouts/ # Complete set of templates
|
|
│ ├── index.html # Homepage layout
|
|
│ ├── post.html # Blog post layout
|
|
│ ├── page.html # Static page layout
|
|
│ └── rss.xml # RSS feed template
|
|
├── static/ # Theme assets
|
|
│ └── css/
|
|
│ └── style.css # Clean, minimal styling
|
|
└── README.md # Theme documentation
|
|
```
|
|
|
|
To use the minimal theme:
|
|
1. Set `site_theme="minimal"` in your `site.conf`
|
|
2. Set `site_theme_css_file="css/style.css"`
|
|
3. Run `./bin/qsgen3`
|
|
|
|
## Theme Directory Structure
|
|
|
|
### Standard Theme Structure
|
|
|
|
```
|
|
themes/
|
|
└── your-theme-name/
|
|
├── layouts/ # Optional: Custom layout templates
|
|
│ ├── index.html # Homepage layout (overrides default)
|
|
│ ├── post.html # Blog post layout (overrides default)
|
|
│ ├── page.html # Static page layout (overrides default)
|
|
│ └── rss.xml # RSS feed template (overrides default)
|
|
└── static/ # Theme's static assets
|
|
├── css/
|
|
│ └── style.css # Main theme CSS
|
|
├── js/
|
|
│ └── theme.js # Theme JavaScript
|
|
└── images/
|
|
└── logo.png # Theme images
|
|
```
|
|
|
|
**Important**: By default, qsgen3 uses the `layouts/` directory in your project root (as specified by `paths_layouts_dir` in `site.conf`). When a theme provides its own `layouts/` directory, it completely overrides the default layouts directory.
|
|
|
|
### Alternative Structure (Legacy Support)
|
|
|
|
For themes that don't use the `static/` subdirectory:
|
|
|
|
```
|
|
themes/
|
|
└── your-theme-name/
|
|
├── layouts/ # Optional: Custom layout templates
|
|
├── css/ # CSS files directly in theme root
|
|
│ └── style.css
|
|
├── js/ # JavaScript files
|
|
└── images/ # Image files
|
|
```
|
|
|
|
### How Layout Override Works
|
|
|
|
1. **Default**: qsgen3 uses templates from your project's `layouts/` directory (configurable via `paths_layouts_dir`)
|
|
2. **Theme Override**: If `themes/your-theme/layouts/` exists, qsgen3 uses **only** those templates
|
|
3. **No Fallback**: If a theme provides layouts, there is no fallback to default layouts. The theme must provide all required templates.
|
|
|
|
**Note**: The project root `layouts/` directory serves as default templates for projects not using themes, or as a fallback when no theme is specified.
|
|
|
|
## Creating Your First Theme
|
|
|
|
### Step 1: Create the Theme Directory
|
|
|
|
```bash
|
|
mkdir -p themes/my-theme/static/css
|
|
mkdir -p themes/my-theme/static/js
|
|
mkdir -p themes/my-theme/layouts
|
|
```
|
|
|
|
### Step 2: Create a Basic CSS File
|
|
|
|
Create `themes/my-theme/static/css/style.css`:
|
|
|
|
```css
|
|
/* Basic theme styles */
|
|
body {
|
|
font-family: 'Arial', sans-serif;
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
padding: 0;
|
|
background-color: #f4f4f4;
|
|
}
|
|
|
|
header {
|
|
background: #333;
|
|
color: white;
|
|
padding: 1rem;
|
|
text-align: center;
|
|
}
|
|
|
|
header h1 a {
|
|
color: white;
|
|
text-decoration: none;
|
|
}
|
|
|
|
main {
|
|
max-width: 800px;
|
|
margin: 2rem auto;
|
|
padding: 0 1rem;
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
article {
|
|
padding: 2rem;
|
|
}
|
|
|
|
footer {
|
|
text-align: center;
|
|
padding: 1rem;
|
|
background: #333;
|
|
color: white;
|
|
margin-top: 2rem;
|
|
}
|
|
```
|
|
|
|
### Step 3: Configure Your Site
|
|
|
|
Update your `site.conf`:
|
|
|
|
```bash
|
|
# Theme configuration
|
|
site_theme="my-theme"
|
|
site_theme_css_file="css/style.css"
|
|
```
|
|
|
|
### Step 4: Test Your Theme
|
|
|
|
```bash
|
|
./bin/qsgen3
|
|
```
|
|
|
|
Your site should now use your custom theme!
|
|
|
|
## Layout Templates
|
|
|
|
### Understanding Pandoc Templates
|
|
|
|
qsgen3 uses Pandoc templates with special variable syntax:
|
|
|
|
- `$variable$` - Simple variable substitution
|
|
- `$if(variable)$...$endif$` - Conditional blocks
|
|
- `$for(list)$...$endfor$` - Loop over lists
|
|
- `$body$` - The main content (converted from Markdown)
|
|
|
|
### Available Variables
|
|
|
|
#### Site-wide Variables (from site.conf)
|
|
- `$site_name$` - Your site's name
|
|
- `$site_tagline$` - Your site's tagline
|
|
- `$site_url$` - Your site's URL
|
|
- `$current_year$` - Current year (auto-generated)
|
|
|
|
#### Content Variables (from Markdown frontmatter)
|
|
- `$title$` - Page/post title
|
|
- `$author$` - Content author
|
|
- `$date$` - Publication date
|
|
- `$description$` - Page description
|
|
- `$body$` - The converted Markdown content
|
|
|
|
#### Special Variables
|
|
- `$css$` - CSS file paths (handled automatically)
|
|
- `$math$` - Math rendering support (if enabled)
|
|
|
|
### Creating Custom Layouts
|
|
|
|
#### Basic Post Layout (`layouts/post.html`)
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>$site_name$ - $title$</title>
|
|
<meta name="author" content="$author$">
|
|
<meta name="description" content="$description$">
|
|
$if(date)$<meta name="date" content="$date$">$endif$
|
|
$for(css)$
|
|
<link rel="stylesheet" href="$css$">
|
|
$endfor$
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1><a href="/">$site_name$</a></h1>
|
|
<p>$site_tagline$</p>
|
|
</header>
|
|
<main>
|
|
<article>
|
|
<header>
|
|
<h1>$title$</h1>
|
|
$if(author)$<p class="author">By: $author$</p>$endif$
|
|
$if(date)$<p class="date">Published: $date$</p>$endif$
|
|
</header>
|
|
$body$
|
|
</article>
|
|
</main>
|
|
<footer>
|
|
<p>© $current_year$ $site_name$. Generated by qsgen3.</p>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### Index Page Layout (`layouts/index.html`)
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>$site_name$ - $site_tagline$</title>
|
|
<meta name="description" content="$site_tagline$">
|
|
$for(css)$
|
|
<link rel="stylesheet" href="$css$">
|
|
$endfor$
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>$site_name$</h1>
|
|
<p>$site_tagline$</p>
|
|
</header>
|
|
<main>
|
|
$body$
|
|
</main>
|
|
<footer>
|
|
<p>© $current_year$ $site_name$. Generated by qsgen3.</p>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
## Static Assets (CSS, JS, Images)
|
|
|
|
### How Static Files Are Processed
|
|
|
|
qsgen3 copies static files in this order:
|
|
|
|
1. **Root Static Files**: Copies from `static/` to `output/static/`
|
|
2. **Theme Static Files**: Copies from `themes/{theme}/static/` to `output/static/` (overwrites root files)
|
|
|
|
This means theme files take precedence over root static files.
|
|
|
|
### CSS File Linking
|
|
|
|
The main theme CSS file is automatically linked in all generated HTML pages using the `--css` flag passed to Pandoc. The CSS path is determined by:
|
|
|
|
1. `site_theme_css_file` setting in `site.conf` (recommended)
|
|
2. `site_theme_css_path` setting (legacy, deprecated)
|
|
|
|
Example configuration:
|
|
```bash
|
|
site_theme="my-theme"
|
|
site_theme_css_file="css/style.css" # Relative to theme's static/ directory
|
|
```
|
|
|
|
This results in:
|
|
- CSS file copied to: `output/static/css/style.css`
|
|
- HTML links to: `/static/css/style.css`
|
|
|
|
### Adding Additional Assets
|
|
|
|
#### JavaScript Files
|
|
|
|
Create `themes/my-theme/static/js/theme.js`:
|
|
|
|
```javascript
|
|
// Theme-specific JavaScript
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('My theme loaded!');
|
|
|
|
// Add smooth scrolling
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
|
behavior: 'smooth'
|
|
});
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
Include in your layout:
|
|
|
|
```html
|
|
<script src="/static/js/theme.js"></script>
|
|
```
|
|
|
|
#### Images and Other Assets
|
|
|
|
Place images in `themes/my-theme/static/images/` and reference them in your CSS or templates:
|
|
|
|
```css
|
|
.logo {
|
|
background-image: url('/static/images/logo.png');
|
|
}
|
|
```
|
|
|
|
```html
|
|
<img src="/static/images/hero.jpg" alt="Hero image">
|
|
```
|
|
|
|
## Theme Configuration
|
|
|
|
### Required Configuration
|
|
|
|
In your `site.conf`:
|
|
|
|
```bash
|
|
# Minimum theme configuration
|
|
site_theme="theme-name" # Name of theme directory
|
|
site_theme_css_file="css/main.css" # Path to main CSS file
|
|
```
|
|
|
|
### Optional Configuration
|
|
|
|
```bash
|
|
# Optional: Override default paths
|
|
paths_layouts_dir="layouts" # Will be overridden if theme has layouts/
|
|
paths_static_dir="static" # Root static directory
|
|
paths_output_dir="output" # Output directory
|
|
```
|
|
|
|
### Theme-Specific Variables
|
|
|
|
You can add custom variables to your `site.conf` and use them in templates:
|
|
|
|
```bash
|
|
# Custom theme variables
|
|
theme_color_primary="#3498db"
|
|
theme_color_secondary="#2c3e50"
|
|
theme_font_family="'Roboto', sans-serif"
|
|
```
|
|
|
|
Use in templates:
|
|
```html
|
|
<style>
|
|
:root {
|
|
--primary-color: $theme_color_primary$;
|
|
--secondary-color: $theme_color_secondary$;
|
|
--font-family: $theme_font_family$;
|
|
}
|
|
</style>
|
|
```
|
|
|
|
## Advanced Theme Features
|
|
|
|
### Responsive Design
|
|
|
|
Create responsive themes using CSS media queries:
|
|
|
|
```css
|
|
/* Mobile-first approach */
|
|
.container {
|
|
max-width: 100%;
|
|
padding: 1rem;
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
.container {
|
|
max-width: 750px;
|
|
margin: 0 auto;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.container {
|
|
max-width: 970px;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Dark Mode Support
|
|
|
|
```css
|
|
/* Default (light) theme */
|
|
:root {
|
|
--bg-color: #ffffff;
|
|
--text-color: #333333;
|
|
--accent-color: #3498db;
|
|
}
|
|
|
|
/* Dark mode */
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--bg-color: #1a1a1a;
|
|
--text-color: #e0e0e0;
|
|
--accent-color: #5dade2;
|
|
}
|
|
}
|
|
|
|
body {
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
}
|
|
```
|
|
|
|
### Typography and Web Fonts
|
|
|
|
```css
|
|
/* Import Google Fonts */
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap');
|
|
|
|
body {
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
font-weight: 400;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
}
|
|
```
|
|
|
|
### Custom RSS Template
|
|
|
|
Create `layouts/rss.xml` for custom RSS styling:
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
<channel>
|
|
<title>$site_name$</title>
|
|
<description>$site_tagline$</description>
|
|
<link>$site_url$</link>
|
|
<atom:link href="$site_url$/rss.xml" rel="self" type="application/rss+xml"/>
|
|
<language>en-us</language>
|
|
<lastBuildDate>$build_date$</lastBuildDate>
|
|
|
|
$for(posts)$
|
|
<item>
|
|
<title>$it.post_title$</title>
|
|
<description>$it.post_description$</description>
|
|
<link>$it.post_url$</link>
|
|
<guid>$it.post_url$</guid>
|
|
<pubDate>$it.post_date_rfc$</pubDate>
|
|
</item>
|
|
$endfor$
|
|
</channel>
|
|
</rss>
|
|
```
|
|
|
|
## Theme Best Practices
|
|
|
|
### 1. Design Principles
|
|
|
|
- **Mobile-First**: Design for mobile devices first, then enhance for larger screens
|
|
- **Accessibility**: Use semantic HTML, proper contrast ratios, and keyboard navigation
|
|
- **Performance**: Optimize images, minimize CSS/JS, use efficient selectors
|
|
- **Consistency**: Maintain consistent spacing, typography, and color schemes
|
|
|
|
### 2. File Organization
|
|
|
|
```
|
|
themes/my-theme/
|
|
├── static/
|
|
│ ├── css/
|
|
│ │ ├── main.css # Main theme styles
|
|
│ │ ├── components.css # Component-specific styles
|
|
│ │ └── utilities.css # Utility classes
|
|
│ ├── js/
|
|
│ │ ├── theme.js # Main theme JavaScript
|
|
│ │ └── components/ # Component-specific JS
|
|
│ └── images/
|
|
│ ├── icons/ # Icon files
|
|
│ └── backgrounds/ # Background images
|
|
└── layouts/
|
|
├── index.html # Homepage layout
|
|
├── post.html # Blog post layout
|
|
├── page.html # Static page layout
|
|
└── rss.xml # RSS feed template
|
|
```
|
|
|
|
### 3. CSS Architecture
|
|
|
|
Use a modular approach:
|
|
|
|
```css
|
|
/* main.css */
|
|
@import url('base.css'); /* Reset and base styles */
|
|
@import url('layout.css'); /* Layout components */
|
|
@import url('components.css'); /* UI components */
|
|
@import url('utilities.css'); /* Utility classes */
|
|
```
|
|
|
|
### 4. Performance Optimization
|
|
|
|
- **Minimize HTTP Requests**: Combine CSS/JS files when possible
|
|
- **Optimize Images**: Use appropriate formats (WebP, SVG) and sizes
|
|
- **Use CSS Custom Properties**: For maintainable theming
|
|
- **Lazy Load**: Implement lazy loading for images and non-critical resources
|
|
|
|
### 5. Browser Compatibility
|
|
|
|
Test your theme across different browsers and devices:
|
|
|
|
```css
|
|
/* Provide fallbacks for modern CSS features */
|
|
.card {
|
|
background: #ffffff; /* Fallback */
|
|
background: var(--card-bg, #ffffff); /* Custom property */
|
|
}
|
|
|
|
.grid {
|
|
display: block; /* Fallback */
|
|
display: grid; /* Modern */
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
#### 1. CSS Not Loading
|
|
|
|
**Problem**: Your theme's CSS isn't being applied.
|
|
|
|
**Solutions**:
|
|
- Check that `site_theme_css_file` path is correct relative to theme's `static/` directory
|
|
- Verify the CSS file exists at `themes/{theme}/static/{css_path}`
|
|
- Check qsgen3 logs for CSS-related warnings
|
|
- Ensure the theme directory name matches `site_theme` setting
|
|
|
|
#### 2. Layouts Not Being Used
|
|
|
|
**Problem**: Your custom layouts aren't being applied.
|
|
|
|
**Solutions**:
|
|
- Verify layouts exist in `themes/{theme}/layouts/`
|
|
- Check that layout filenames match expected names (`index.html`, `post.html`, `page.html`)
|
|
- Review qsgen3 logs for layout-related messages
|
|
|
|
#### 3. Static Files Not Copying
|
|
|
|
**Problem**: Images, JS, or other static files aren't appearing in output.
|
|
|
|
**Solutions**:
|
|
- Check that files are in `themes/{theme}/static/` directory
|
|
- Verify file permissions are readable
|
|
- Look for rsync/cp errors in qsgen3 logs
|
|
- Ensure no .gitignore rules are excluding files
|
|
|
|
#### 4. Template Variables Not Working
|
|
|
|
**Problem**: Variables like `$site_name$` aren't being substituted.
|
|
|
|
**Solutions**:
|
|
- Check that variables are defined in `site.conf`
|
|
- Verify variable names match exactly (case-sensitive)
|
|
- Ensure Pandoc template syntax is correct
|
|
- Test with a minimal template to isolate issues
|
|
|
|
### Debugging Tips
|
|
|
|
#### 1. Enable Debug Logging
|
|
|
|
Run qsgen3 with verbose output to see detailed processing information:
|
|
|
|
```bash
|
|
# Enable debug logging (if supported by your qsgen3 version)
|
|
QSG_LOG_LEVEL=DEBUG ./bin/qsgen3
|
|
```
|
|
|
|
#### 2. Test with Minimal Theme
|
|
|
|
Create a minimal theme to isolate issues:
|
|
|
|
```html
|
|
<!-- minimal-test.html -->
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>$title$</title>
|
|
<style>body { font-family: Arial; margin: 2rem; }</style>
|
|
</head>
|
|
<body>
|
|
<h1>$title$</h1>
|
|
$body$
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### 3. Validate Generated HTML
|
|
|
|
Check that your generated HTML is valid:
|
|
|
|
```bash
|
|
# Use HTML validator tools
|
|
htmlhint output/*.html
|
|
# or
|
|
w3c-validator output/index.html
|
|
```
|
|
|
|
#### 4. Check File Permissions
|
|
|
|
Ensure qsgen3 can read your theme files:
|
|
|
|
```bash
|
|
find themes/my-theme -type f -not -perm -644
|
|
find themes/my-theme -type d -not -perm -755
|
|
```
|
|
|
|
### Getting Help
|
|
|
|
If you encounter issues not covered here:
|
|
|
|
1. Check the qsgen3 documentation and examples
|
|
2. Review existing themes in the `themes/` directory
|
|
3. Examine the qsgen3 source code for theme processing logic
|
|
4. Create a minimal reproduction case
|
|
5. Report issues with detailed logs and configuration
|
|
|
|
---
|
|
|
|
## Example: Complete Theme Creation
|
|
|
|
Here's a complete example of creating a modern, responsive theme called "modern-blog":
|
|
|
|
### 1. Create Directory Structure
|
|
|
|
```bash
|
|
mkdir -p themes/modern-blog/{layouts,static/{css,js,images}}
|
|
```
|
|
|
|
### 2. Create Main CSS (`themes/modern-blog/static/css/style.css`)
|
|
|
|
```css
|
|
/* Modern Blog Theme */
|
|
:root {
|
|
--primary-color: #2563eb;
|
|
--secondary-color: #64748b;
|
|
--background-color: #ffffff;
|
|
--text-color: #1e293b;
|
|
--border-color: #e2e8f0;
|
|
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
line-height: 1.6;
|
|
color: var(--text-color);
|
|
background-color: var(--background-color);
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 0 1rem;
|
|
}
|
|
|
|
header {
|
|
background: var(--background-color);
|
|
border-bottom: 1px solid var(--border-color);
|
|
padding: 2rem 0;
|
|
}
|
|
|
|
header h1 {
|
|
margin: 0;
|
|
font-size: 2rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
header h1 a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
}
|
|
|
|
header p {
|
|
margin: 0.5rem 0 0 0;
|
|
color: var(--secondary-color);
|
|
}
|
|
|
|
main {
|
|
padding: 3rem 0;
|
|
}
|
|
|
|
article {
|
|
background: var(--background-color);
|
|
border-radius: 8px;
|
|
box-shadow: var(--shadow);
|
|
padding: 2rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
article header h1 {
|
|
margin: 0 0 1rem 0;
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
.meta {
|
|
color: var(--secondary-color);
|
|
font-size: 0.9rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.meta .author,
|
|
.meta .date {
|
|
display: inline-block;
|
|
margin-right: 1rem;
|
|
}
|
|
|
|
footer {
|
|
background: var(--text-color);
|
|
color: var(--background-color);
|
|
text-align: center;
|
|
padding: 2rem 0;
|
|
margin-top: 3rem;
|
|
}
|
|
|
|
footer a {
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
/* Responsive design */
|
|
@media (max-width: 768px) {
|
|
.container {
|
|
padding: 0 0.5rem;
|
|
}
|
|
|
|
header {
|
|
padding: 1rem 0;
|
|
}
|
|
|
|
main {
|
|
padding: 1.5rem 0;
|
|
}
|
|
|
|
article {
|
|
padding: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Create Post Layout (`themes/modern-blog/layouts/post.html`)
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>$site_name$ - $title$</title>
|
|
<meta name="author" content="$author$">
|
|
<meta name="description" content="$description$">
|
|
$if(date)$<meta name="date" content="$date$">$endif$
|
|
$for(css)$
|
|
<link rel="stylesheet" href="$css$">
|
|
$endfor$
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="container">
|
|
<h1><a href="/">$site_name$</a></h1>
|
|
<p>$site_tagline$</p>
|
|
</div>
|
|
</header>
|
|
<main>
|
|
<div class="container">
|
|
<article>
|
|
<header>
|
|
<h1>$title$</h1>
|
|
<div class="meta">
|
|
$if(author)$<span class="author">By: $author$</span>$endif$
|
|
$if(date)$<span class="date">Published: $date$</span>$endif$
|
|
</div>
|
|
</header>
|
|
$body$
|
|
</article>
|
|
</div>
|
|
</main>
|
|
<footer>
|
|
<div class="container">
|
|
<p>© $current_year$ $site_name$. Generated by qsgen3.</p>
|
|
<p><a href="$site_url$">$site_url$</a></p>
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### 4. Configure Site (`site.conf`)
|
|
|
|
```bash
|
|
site_theme="modern-blog"
|
|
site_theme_css_file="css/style.css"
|
|
```
|
|
|
|
### 5. Generate Site
|
|
|
|
```bash
|
|
./bin/qsgen3
|
|
```
|
|
|
|
Your modern, responsive blog theme is now ready!
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
This guide covers everything you need to know about creating themes for qsgen3. Key points to remember:
|
|
|
|
1. **Complete Override**: When a theme provides layouts, it completely replaces default layouts
|
|
2. **No Partial Fallback**: Themes must provide all necessary templates (`index.html`, `post.html`, `page.html`, `rss.xml`)
|
|
3. **Static File Merging**: Theme static files are copied after root static files, allowing themes to override default assets
|
|
4. **CSS Automation**: The main theme CSS file is automatically linked in generated HTML
|
|
|
|
Understanding this processing flow is key to creating effective themes that work reliably across different configurations.
|