Theme Structure
Complete file organization for OQO themes.
Directory Layout
app/themes/my_theme/
├── assets/
│ ├── css/
│ │ ├── tailwind.css # Tailwind source (compiled locally)
│ │ ├── _variables.css.liquid # CSS variables from settings
│ │ ├── _base.css # Base element styles
│ │ ├── _layout.css # Container/section utilities
│ │ ├── _typography.css # Text styling
│ │ ├── _components.css # Cards, buttons, etc.
│ │ ├── _utilities.css # Animations, helpers
│ │ └── theme.css # Entry point (@imports all)
│ ├── framework.css # Pre-compiled CSS framework
│ └── theme.css # Final bundled output (generated)
├── config/
│ └── settings_schema.json # Theme-level settings
├── layouts/
│ └── theme.liquid # Main layout template
├── sections/
│ ├── hero/
│ │ ├── hero_01.liquid
│ │ └── hero_02.liquid
│ ├── content/
│ │ ├── recent_posts.liquid
│ │ └── featured_post.liquid
│ └── cta/
│ └── cta_01.liquid
└── snippets/
├── post_card.liquid
└── social_icons.liquid
Key Files
layouts/theme.liquid
The main layout wrapping all pages:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.title }} | {{ site.name }}</title>
{% theme_asset 'theme.css' %}
</head>
<body>
<header>
{% render 'navigation' %}
</header>
<main>
{{ content_for_layout }}
</main>
<footer>
{% render 'footer' %}
</footer>
{% theme_asset 'theme.js' %}
</body>
</html>
config/settings_schema.json
Theme-wide configurable settings organized in groups:
[
{
"name": "Colors",
"settings": [
{
"type": "color",
"id": "primary_color",
"label": "Primary Color",
"default": "#3B82F6"
},
{
"type": "color",
"id": "secondary_color",
"label": "Secondary Color",
"default": "#10B981"
}
]
},
{
"name": "Layout",
"settings": [
{
"type": "range",
"id": "content_width",
"label": "Max Content Width",
"min": 960,
"max": 1920,
"step": 40,
"default": 1280,
"unit": "px"
}
]
}
]
assets/css/_variables.css.liquid
Maps theme settings to CSS variables (processed with Liquid):
:root {
--theme-primary-color: {{ theme.settings.primary_color }};
--theme-secondary-color: {{ theme.settings.secondary_color }};
--theme-content-width: {{ theme.settings.content_width }}px;
}
CSS Framework Integration
Themes are framework-agnostic. You compile your CSS framework locally and include the output.
Tailwind CSS (Recommended)
Create assets/css/tailwind.css:
@import "tailwindcss";
@source "../../sections/**/*.liquid";
@source "../../layouts/**/*.liquid";
@source "../../snippets/**/*.liquid";
Compile locally:
tailwindcss -i assets/css/tailwind.css -o assets/framework.css --watch
This produces a tree-shaken framework.css with only the utilities you use.
Bootstrap or Other Frameworks
Download or compile your framework and place it in assets/framework.css.
No Framework
Simply omit framework.css - the bundler will skip it.
Section Organization
Group sections by category:
sections/
├── hero/ # Hero banners, sliders
├── content/ # Posts, articles, text blocks
├── cta/ # Call-to-action blocks
├── features/ # Feature grids, lists
├── testimonials/ # Reviews, quotes
└── footer/ # Footer variations
Each section file includes:
- Liquid template markup
{% schema %}block defining settings- Optional
{% style %}block for scoped CSS
CSS Compilation
When theme settings are saved, the platform:
- Loads framework.css (if present)
- Renders _variables.css.liquid with current settings
- Resolves @imports by inlining partial files (plain CSS concatenation via ThemeFileSystem)
- Bundles everything into single
theme.css
Output is loaded via {% theme_asset 'theme.css' %}.