mcpField
T
theme-create

theme-create

github.com/ahmed-lakoshaDesign & UI7657 installsUpdated 31w ago
Repository

About theme-create

An implementation guide for Odoo theme developers, covering module structure, SCSS load order, page templates, and theme activation. It also includes installation checks and version-specific notes.

Key features

  1. 01Define the Odoo theme module structure
  2. 02Follow SCSS variable load order
  3. 03Configure fonts and asset bundles
  4. 04Create website page templates
  5. 05Implement post-copy theme activation
  6. 06Check installation and responsive layouts

Use cases

  1. 01Build an Odoo website theme from scratch
  2. 02Troubleshoot SCSS compilation or installation errors
  3. 03Adapt a theme for different Odoo versions
  4. 04Verify theme pages and the website builder

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ahmed-lakosha/odoo-plugins --skill theme-create

After installing, type/theme-createin Claude Code to confirm it loaded.

Details

From the project README

Theme Creation Skill

Critical Rules

  1. NEVER modify core Odoo in odoo/ or odoo/addons/
  2. NEVER use map-merge() with core Odoo variables in theme SCSS — they're undefined at load time
  3. NEVER use ir.asset records for Google Fonts — use $o-theme-font-configs
  4. ALWAYS use ('prepend', ...) for primary_variables.scss in asset bundles
  5. H6 is ALWAYS 16px (1rem) — the fixed base reference
  6. All manifests must include author: 'TaqaTechno', website, support, license: 'LGPL-3'

Generated Theme Structure (v8.0)

theme_<name>/
├── __init__.py                      # Imports models
├── __manifest__.py                  # With proper asset bundles
├── models/
│   ├── __init__.py                 # Imports theme_<name>
│   └── theme_<name>.py             # theme.utils implementation (REQUIRED!)
├── security/
│   └── ir.model.access.csv
├── data/
│   ├── assets.xml                  # Minimal (fonts via SCSS, not ir.asset!)
│   ├── menu.xml
│   └── pages/                      # Individual page files (best practice)
│       ├── home_page.xml           # Inherits website.homepage
│       ├── aboutus_page.xml        # theme.website.page
│       ├── contactus_page.xml      # Inherits website.contactus
│       └── services_page.xml       # theme.website.page
├── views/
│   ├── layout/
│   │   └── templates.xml           # Base layout templates
│   └── snippets/
│       └── custom_snippets.xml
└── static/src/
    ├── scss/
    │   ├── primary_variables.scss   # Theme variables + font configs
    │   └── theme.scss               # Additional custom styles
    ├── js/
    │   └── theme.js                 # publicWidget implementations
    └── img/

Manifest Template

{
    'name': 'Theme <Name>',
    'version': '<odoo_version>.0.1.0.0',
    'category': 'Theme/Creative',
    'summary': 'Custom theme for <client>',
    'author': 'TaqaTechno',
    'website': 'https://www.taqatechno.com/',
    'support': '[email protected]',
    'license': 'LGPL-3',
    'depends': ['website'],
    'data': [
        'security/ir.model.access.csv',
        'views/layout/templates.xml',
        'views/snippets/custom_snippets.xml',
        'data/menu.xml',
        'data/pages/home_page.xml',
        'data/pages/aboutus_page.xml',
        'data/pages/contactus_page.xml',
    ],
    'assets': {
        'web._assets_primary_variables': [
            ('prepend', 'theme_<name>/static/src/scss/primary_variables.scss'),
        ],
        'web.assets_frontend': [
            'theme_<name>/static/src/scss/theme.scss',
            'theme_<name>/static/src/js/theme.js',
        ],
    },
    'installable': True,
    'auto_install': False,
    'application': False,
}

SCSS Load Order (Critical)

1. YOUR theme's primary_variables.scss (via 'prepend')  ← FIRST
2. Odoo core primary_variables.scss                      ← SECOND
3. Other SCSS files

CONSEQUENCE:
  - CANNOT use map-merge() with core variables (they don't exist yet!)
  - MUST define standalone variables
  - Use 'color-palettes-name': 'default-1' to reference existing palettes

WRONG:  $o-color-palettes: map-merge($o-color-palettes, (...));
RIGHT:  $o-website-values-palettes: ( ( 'color-palettes-name': 'default-1' ) );

primary_variables.scss Template

// ===================================================================
// Theme: <Name> — Generated by TaqaTechno
// PREPENDED before Odoo core — DO NOT use map-merge()!
// ===================================================================

// === Font Configuration (STANDALONE) ===
$o-theme-font-configs: (
    'Inter': (
        'family': ('Inter', sans-serif),
        'url': 'Inter:300,300i,400,400i,500,500i,600,600i,700,700i',
    ),
);

// === Website Values Palette (MASTER CONFIGURATION) ===
$o-website-values-palettes: (
    (
        'color-palettes-name': 'default-1',

        // Typography
        'font': 'Inter',
        'headings-font': 'Inter',
        'navbar-font': 'Inter',
        'buttons-font': 'Inter',

        // Header (NO custom header.xml needed!)
        'header-template': 'default',
        'header-links-style': 'default',
        'logo-height': 3rem,
        'fixed-logo-height': 2rem,

        // Buttons
        'btn-padding-y': 0.45rem,
        'btn-padding-x': 1.35rem,
        'btn-border-radius': 0.25rem,

        // Footer (NO custom footer.xml needed!)
        'footer-template': 'default',
        'footer-scrolltop': true,

        // Links & Layout
        'link-underline': 'hover',
        'layout': 'full',
    )
);

// === Typography Multipliers ===
$o-theme-h1-font-size-multiplier: (64 / 16); // 64px
$o-theme-h2-font-size-multiplier: (48 / 16); // 48px
$o-theme-h3-font-size-multiplier: (32 / 16); // 32px
$o-theme-h4-font-size-multiplier: (24 / 16); // 24px
$o-theme-h5-font-size-multiplier: (20 / 16); // 20px
$o-theme-h6-font-size-multiplier: (16 / 16); // 16px (FIXED)

Page Creation Patterns

Homepage (inherits website.homepage)
<template id="view_home" inherit_id="website.homepage" name="Home">
    <xpath expr="//div[@id='wrap']" position="replace">
        <div id="wrap" class="oe_structure">
            <!-- Homepage content -->
        </div>
    </xpath>
</template>
Contact (inherits website.contactus)
<template id="view_contact" inherit_id="website.contactus" name="Contact">
    <xpath expr="//h1" position="replace">
        <h1>Get in Touch</h1>
    </xpath>
</template>
Custom Pages (theme.website.page)
<template id="view_about" name="About">
    <t t-call="website.layout">
        <div id="wrap" class="oe_structure">
            <section class="s_title pt96 pb48">
                <div class="container"><h1>About Us</h1></div>
            </section>
        </div>
    </t>
</template>

<record id="page_about" model="theme.website.page">
    <field name="view_id" ref="view_about"/>
    <field name="is_published" eval="True"/>
    <field name="url">/about</field>
</record>

Theme Mirror Model Architecture

theme.ir.ui.view (Template) → ir.ui.view (Actual, with website_id)
theme.website.page (Template) → website.page (Actual, with website_id)

Each website gets independent copies, enabling theme reuse across multiple sites.

theme.utils Activation (REQUIRED)

Every theme MUST include models/theme_<name>.py:

from odoo import models

class Theme<Name>(models.AbstractModel):
    _inherit = 'theme.utils'

    def _theme_<name>_post_copy(self, mod):
        """Called automatically when theme is installed on a website."""
        # Enable header template
        self.enable_view('website.template_header_default')
        # Enable footer template
        self.enable_view('website.template_footer_contact')
        # Show logo, not brand name
        self.enable_view('website.option_header_brand_logo')
        self.disable_view('website.option_header_brand_name')

Method name MUST be _theme_{technical_name}_post_copy where technical_name matches the folder name.

Available methods: enable_view(xml_id), disable_view(xml_id), enable_asset(xml_id), disable_asset(xml_id)

Installation & Testing

# 1. Update module list
python -m odoo -c conf/<PROJECT>.conf -d <DB> --update-list

# 2. Install theme
python -m odoo -c conf/<PROJECT>.conf -d <DB> -i theme_<name> --stop-after-init

# 3. If errors, auto-fix and retry (up to 3 attempts)
Common Auto-Fix Patterns
ErrorFix
Undefined variable "$o-color-palettes"Remove map-merge, use standalone
Undefined variable "$o-theme-font-configs"Define standalone (no map-merge)
SyntaxError in SCSSParse error location, fix syntax
Module not foundAdd dependency to manifest
Malformed Google Fonts @importRemove ir.asset, use $o-theme-font-configs
Testing Checklist
  • Theme installs without errors
  • CSS compilation succeeds
  • No SCSS/JS errors in browser console
  • Header and footer styling apply correctly
  • Responsive layout works on mobile/tablet/desktop
  • Website builder (edit mode) functions without errors

Version-Specific Notes

OdooBootstrapSnippet RegistrationKey Differences
14-154.xSimple XPathml-*/mr-* classes
16-175.1.3Simple XPathms-*/me-* classes
18-195.1.3Groups requiredsnippet-group attribute needed

For the complete 115+ SCSS variable reference, see the theme-scss skill. For Figma-to-Odoo workflow and page template matching, see the theme-design skill.

Comments

Markdown supported