# Customization Guide
*Making TufteCMS reflect your unique voice and vision*
TufteCMS provides a foundation for contemplative digital publishing while remaining flexible enough to adapt to your specific needs and aesthetic preferences.
> This guide assumes familiarity with [getting started](/docs/getting-started) and [content structure](/docs/content-structure). For specialized sidenote styling, see the [sidenotes guide](/docs/sidenotes).
## Template System
TufteCMS uses Flask's Jinja2 templating with a clean, semantic structure.
### Template Directory
```
tuftecms/templates/
├── base.html # Master layout template
├── post.html # Individual content pages
├── archive.html # Chronological content listings
├── directory.html # File browser interface
├── sidenotes.html # Sidenotes index
├── outlines.html # Headings index
├── quotes.html # Blockquotes index
├── connections.html # Cross-references index
├── terms.html # Terms index
├── graph.html # Interactive content graph
└── search.html # Full-text search interface
```
### Base Template Structure
The `base.html` template provides the foundational layout:
```html
{% block title %}{{ title }}{% endblock %}
{% block content %}{% endblock %}
```
### Content Template Variables
When customizing templates, you have access to these variables:
#### All Templates
- `title`: Page title
- `current_year`: Current year for copyright
- `index_counts`: Statistics for all content indexes
#### Content Pages (`post.html`)
- `content`: Rendered HTML content
- `metadata`: Frontmatter data
- `reading_time`: Estimated reading time in minutes
- `word_count`: Content word count
- `tags`: List of content tags
- `unique_icon`: Custom icon for the content
- `related_posts`: Algorithm-suggested related content
- `adjacent_posts`: Previous and next in chronological order
#### Index Pages
- `articles`: Content items for the index
- `total_count`: Total items in the index
- Specific data based on index type (sidenotes, quotes, etc.)
## Styling System
TufteCMS includes Tufte-inspired CSS that you can customize or replace entirely.
### CSS Architecture
```
tuftecms/static/css/
├── tufte.css # Core Tufte-style typography
├── layout.css # Site layout and structure
├── components.css # UI components (navigation, forms)
├── syntax.css # Code syntax highlighting
└── custom.css # Your customizations
```
### Key Design Classes
```css
/* Content layout */
.post-content /* Main content container */
.sidenote /* Marginal annotations */
.margin-toggle /* Sidenote toggle mechanism */
/* Typography */
.subtitle /* Subtitle styling */
.legend-dot /* Colored dots for categorization */
.project-link /* Internal link styling */
/* Navigation */
.pathway-box /* Homepage pathway sections */
.footer-indexes /* Footer navigation links */
/* Content organization */
.color-philosophy /* Philosophy content theme */
.color-software /* Software content theme */
.color-ai /* AI content theme */
.color-essay /* Essay content theme */
```
### Color Theming
TufteCMS uses a semantic color system for content categorization:
```css
:root {
--color-philosophy: #95a5a6;
--color-software: #e74c3c;
--color-ai: #9b59b6;
--color-essay: #3498db;
--color-music: #f39c12;
--color-poetry: #27ae60;
}
.project-link.color-philosophy { color: var(--color-philosophy); }
.project-link.color-software { color: var(--color-software); }
/* etc. */
```
## Custom CSS
Add your customizations to `tuftecms/static/css/custom.css`:
```css
/* Override typography */
body {
font-family: your-preferred-font, serif;
font-size: 1.1em;
line-height: 1.7;
}
/* Customize sidenote appearance */
.sidenote {
background-color: #f9f9f9;
border-left: 3px solid #ddd;
padding-left: 0.5em;
}
/* Add custom content themes */
.project-link.color-custom {
color: #your-brand-color;
}
/* Modify layout constraints */
.post-content {
max-width: 50rem; /* Adjust reading column width */
}
```
## Navigation Customization
### Header Navigation
Modify the site navigation in `base.html`:
```html
```
### Footer Indexes
Customize the footer content guides in your index template:
```html
```
### Custom Index Pages
Create new index types by adding routes and templates:
```python
# In blueprints/main.py
@main_bp.route("/custom-index")
def custom_index():
# Your custom logic here
return render_template("custom-index.html", data=your_data)
```
## Content Processing Customization
### Markdown Extensions
Extend markdown processing in `core/markdown.py`:
```python
import markdown
from markdown.extensions import codehilite, toc, tables
# Add custom extensions
md = markdown.Markdown(
extensions=[
'codehilite',
'toc',
'tables',
'your_custom_extension'
],
extension_configs={
'codehilite': {'css_class': 'highlight'},
'toc': {'anchorlink': True}
}
)
```
### Custom Content Filters
Add Jinja2 template filters in `app.py`:
```python
@app.template_filter('your_filter')
def your_custom_filter(text):
"""Custom text processing."""
return process_text(text)
```
### Content Metadata
Extend frontmatter processing to support custom fields:
```python
# In your content processing
def extract_metadata(frontmatter_data):
metadata = {
'title': frontmatter_data.get('title', ''),
'date': frontmatter_data.get('date'),
'your_custom_field': frontmatter_data.get('custom_field'),
# Process custom metadata here
}
return metadata
```
## Brand Integration
### Logo and Identity
Replace the site title with your logo in `base.html`:
```html
Your Digital Garden
```
### Custom Fonts
Add web fonts in your base template:
```html
```
```css
/* Apply in your CSS */
body {
font-family: 'Your Font', Georgia, serif;
}
.sidenote {
font-family: 'Your Sans Font', 'Helvetica Neue', sans-serif;
}
```
### Color Scheme
Define your brand colors:
```css
:root {
--primary-color: #your-primary;
--secondary-color: #your-secondary;
--accent-color: #your-accent;
--text-color: #your-text;
--background-color: #your-background;
--border-color: #your-border;
}
/* Apply throughout your styles */
.project-link { color: var(--accent-color); }
.sidenote { border-color: var(--border-color); }
```
## Content Organization
### Custom Content Types
Create new content categories by adding directories and customizing templates:
```
data/
├── essays/ # Existing
├── projects/ # Existing
├── reviews/ # New: Book/film reviews
├── tutorials/ # New: Technical guides
└── experiments/ # New: Work-in-progress ideas
```
Add routing logic in `blueprints/content.py` for custom handling:
```python
# Special handling for new content types
if path.startswith("reviews/"):
# Custom processing for reviews
return render_review_template(content_data)
elif path.startswith("experiments/"):
# Different template for experimental content
return render_experiment_template(content_data)
```
### Custom Metadata Fields
Extend frontmatter for specific content types:
```yaml
---
title: "Book Review: Consciousness Explained"
type: "review"
reviewed_item: "Consciousness Explained by Daniel Dennett"
rating: 4
review_date: 2025-01-15
tags: [consciousness, philosophy, books]
---
```
Process in templates:
```html
{% if metadata.type == 'review' %}
{{ metadata.reviewed_item }}
Rating: {{ metadata.rating }}/5
{% endif %}
```
## Advanced Customization
### Custom Caching
Extend the caching system for your content types:
```python
# In core/cache.py
@lru_cache(maxsize=1)
def get_custom_cache():
"""Cache your custom content analysis."""
# Your caching logic
return processed_data
```
### Search Integration
Customize search behavior in your templates and JavaScript:
```javascript
// Custom search filtering
function filterResults(results, contentType) {
if (contentType === 'essays') {
return results.filter(r => r.path.includes('/essays/'));
}
return results;
}
```
### Analytics and Insights
Add custom analytics while respecting privacy:
```html
```
## Performance Optimization
### Static Asset Optimization
```python
# In app.py - add asset versioning
@app.template_filter('asset_version')
def asset_version(filename):
"""Add version hash to asset URLs."""
# Your versioning logic
return f"{filename}?v={get_file_hash(filename)}"
```
### Caching Headers
Customize caching behavior in `blueprints/content.py`:
```python
# Custom cache headers for different content types
if file_path.suffix == '.md':
# Shorter cache for dynamic content
response.headers['Cache-Control'] = 'public, max-age=3600'
elif file_path.suffix in ['.jpg', '.png', '.svg']:
# Longer cache for images
response.headers['Cache-Control'] = 'public, max-age=604800'
```
## Next Steps
With your customized TufteCMS site:
- **Structure your content** - Apply customizations to well-organized content using the [content structure guide](/docs/content-structure)
- **Master sidenotes** - Style the [sidenotes system](/docs/sidenotes) to match your visual identity
- **Deploy to production** - Launch your customized site with the [deployment guide](/docs/deployment)
- **Continue exploring** - Return to the [documentation index](/docs) for advanced topics
---
*Remember: Customization should serve your content, not overshadow it. The best modifications enhance readability and discovery while maintaining the contemplative focus that makes your digital garden a place worth visiting.*