odoo-frontend

ๅฎ‰่ฃ…้‡: 37
ๆŽ’ๅ: #19141

ๅฎ‰่ฃ…

npx skills add https://github.com/ahmed-lakosha/odoo-upgrade-skill --skill odoo-frontend
Odoo Frontend Development Skill v6.0
Overview
This skill provides advanced Odoo frontend development capabilities with:
๐ŸŽจ /create-theme Command
Generate complete production-ready theme modules with all files
๐Ÿ”ง Theme Feature Activation
:
theme.utils
model with
_theme_xxx_post_copy()
for template configuration
๐Ÿ“‹ Complete Dynamic Page Reference
All 11 headers, 9 footers, shop, product, blog templates with XML IDs
๐ŸŽฏ Design Workflow
Figma โ†’ Odoo template matching โ†’ configuration โ†’ enhancement methodology
Theme Development
Complete
$o-website-values-palettes
reference, color semantics, theme mirror models
Auto-detection
Automatically detect Odoo version and map to correct Bootstrap version
publicWidget Framework
Comprehensive patterns with
editableMode
handling for website builder
Progressive Web Apps
Service Workers, offline support, push notifications
Modern JavaScript
TypeScript, ES2020+, Web Components, Owl v1/v2 patterns
Testing Frameworks
Jest, Cypress, visual regression testing
Performance Optimization
Core Web Vitals, resource hints, critical CSS
Accessibility
WCAG 2.1 AA compliance, ARIA patterns, keyboard navigation
Real-time Features
WebSockets, Server-Sent Events, live collaboration
MCP Integration
Figma design conversion and Chrome DevTools style extraction
Theme Scaffolding
Complete theme module generation with proper structure
Version-Aware
Handle differences between Odoo 14-19 (Bootstrap 4/5, Owl v1/v2, Snippet structures)
DevOps Ready
CI/CD pipelines, Vite builds, automated testing
๐ŸŽจ /create-theme Command
Quick Start
Generate a complete, production-ready Odoo theme module. Usage

Interactive mode (recommended)

/create-theme

Quick mode with arguments

/create-theme < theme_name

< project_path

Full arguments

/create-theme < theme_name

< project_path

--version

17 --colors = "#207AB7,#FB9F54,#F6F4F0,#FFFFFF,#191A19" --font = "IBM Plex Sans" What Gets Created theme_/ โ”œโ”€โ”€ init.py โ”œโ”€โ”€ manifest.py โ”œโ”€โ”€ security/ โ”‚ โ””โ”€โ”€ ir.model.access.csv โ”œโ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ assets.xml โ”‚ โ”œโ”€โ”€ menu.xml โ”‚ โ””โ”€โ”€ pages/ # Individual page files (BEST PRACTICE!) โ”‚ โ”œโ”€โ”€ home_page.xml # Homepage (inherits website.homepage) โ”‚ โ”œโ”€โ”€ aboutus_page.xml # About Us page โ”‚ โ”œโ”€โ”€ contactus_page.xml # Contact (inherits website.contactus) โ”‚ โ””โ”€โ”€ services_page.xml # Services page โ”œโ”€โ”€ views/ โ”‚ โ”œโ”€โ”€ layout/ โ”‚ โ”‚ โ”œโ”€โ”€ header.xml # Header customization (OPTIONAL) โ”‚ โ”‚ โ”œโ”€โ”€ footer.xml # Footer customization (OPTIONAL) โ”‚ โ”‚ โ””โ”€โ”€ templates.xml # Base layout templates โ”‚ โ””โ”€โ”€ snippets/ โ”‚ โ””โ”€โ”€ custom_snippets.xml # Custom snippet definitions โ””โ”€โ”€ static/src/ โ”œโ”€โ”€ scss/ โ”‚ โ”œโ”€โ”€ primary_variables.scss # Theme variables + fonts โ”‚ โ”œโ”€โ”€ bootstrap_overridden.scss # Bootstrap overrides (OPTIONAL) โ”‚ โ””โ”€โ”€ theme.scss # Additional custom styles โ”œโ”€โ”€ js/ โ”‚ โ”œโ”€โ”€ theme.js # publicWidget implementations โ”‚ โ””โ”€โ”€ snippets_options.js # Snippet options (if needed) โ””โ”€โ”€ img/ ๐Ÿ’ก Simplified Approach (Recommended) In MOST cases, you can configure via $o-website-values-palettes without custom XML: 'header-template' : 'default' | 'hamburger' | 'vertical' | 'sidebar' 'footer-template' : 'default' | 'centered' | 'minimalist' | 'links' | 'descriptive' When to use custom header.xml/footer.xml: Design requires completely custom layout not available in templates Need additional HTML elements beyond what templates provide Color System (o-color-1 to o-color-5) Variable Semantic Meaning Default o-color-1 Primary brand color

207AB7

o-color-2 Secondary/accent

FB9F54

o-color-3 Light backgrounds

F6F4F0

o-color-4 White/body base

FFFFFF

o-color-5 Dark text/headings

191A19

Version Support
Odoo 14-15
Bootstrap 4.5.0, simple snippets
Odoo 16-17
Bootstrap 5.1.3, modern asset bundles
Odoo 18-19
Bootstrap 5.1.3, snippet groups required
Run Script Directly
python scripts/create_theme.py
<
theme_name
>
<
output_path
>
--version
=
17
--colors
=
"#207AB7,#FB9F54,#F6F4F0,#FFFFFF,#191A19"
CRITICAL RULES
NEVER edit core Odoo
in
odoo/
or
odoo/addons/
directories
No inline JS/CSS
- Create separate
.js
and
.scss
files
JS modules
Use
/ @odoo-module /
annotation
Website themes
Use
publicWidget
framework ONLY (not Owl or vanilla JS)
Bootstrap
Use v5.1.3 classes for Odoo 16+ (never Tailwind)
Module naming
Use
snake_case
convention
Translations
Wrap static labels in JS arrays/constants with _t() AT DEFINITION TIME (not via runtime wrappers). Static XML strings are auto-translated. Auto-Detection Workflow Step 1: Detect Odoo Version When starting any frontend task, first detect the Odoo version:

Use the version detector script

python scripts
/
version_detector
.
py
<
module_path
>
The version detector will:
Look for
manifest.py
or
openerp.py
Parse the version field
If not found, detect from parent directory (e.g.,
odoo17/
)
Return:
Odoo version (e.g., "17.0")
Bootstrap version (e.g., "5.1.3")
Owl version (e.g., "2.x" or None)
Module type (theme, website, custom)
Step 2: Bootstrap Version Mapping
Automatic Bootstrap Version Selection:
Odoo 14-15: Bootstrap 4.5.0
Odoo 16-19: Bootstrap 5.1.3
Step 3: Owl Version Detection
JavaScript Framework Selection:
Odoo 14-15: Owl experimental or jQuery only
Odoo 16-17: Owl v1
Odoo 18-19: Owl v2 (with breaking changes)
Step 4: Snippet Structure Detection
Snippet Registration Method:
Odoo 14-17: Simple snippet insertion without groups
Odoo 18-19: Snippet groups required (
snippet_structure
with groups)
Complete Theme Variables Reference
This section provides complete documentation for the three core SCSS variable systems used in Odoo themes.
๐Ÿ“š 1. $o-theme-font-configs - Google Fonts Configuration
$o-theme-font-configs
defines available fonts for Odoo website themes with automatic Google Fonts import.
Structure
$o-theme-font-configs
:
(
''
:
(
'family'
:
(
)
,
// Required: Font family with fallbacks
'url'
:
''
,
// Required*: Google Fonts query param ONLY
'properties'
:
(
// Optional: Per-context CSS overrides
''
:
(
''
:
,
)
,
)
,
)
,
)
;
โš ๏ธ CRITICAL
The 'url' key contains only the query parameter , NOT the full URL! // โœ… CORRECT - Only the font parameter 'url' : 'Poppins:300,300i,400,400i,600,600i,700,700i' // The system generates: https://fonts.googleapis.com/css?family=Poppins:...&display=swap // โŒ WRONG - Do not include full URL 'url' : 'https://fonts.googleapis.com/css?family=Poppins:300,400,700' Font Weight Specification // Format: FontName:weight1,weight1i,weight2,weight2i,... // - Number alone = normal style // - Number + 'i' = italic style 'url' : 'Poppins:300,300i,400,400i,600,600i,700,700i' // Light Light-i Regular Regular-i SemiBold ... Multiple Word Font Names // Replace spaces with + 'url' : 'Open+Sans:300,300i,400,400i,700,700i' 'url' : 'Source+Sans+Pro:300,300i,400,400i,700,700i' 'url' : 'DM+Serif+Display:400,400i' Font Aliases (for 'properties' key) Alias Maps To Usage 'base' 'font' Body text 'headings' 'headings-font' All headings (H1-H6) 'h2' - 'h6' 'h2-font' - 'h6-font' Individual headings 'navbar' 'navbar-font' Navigation menu 'buttons' 'buttons-font' Button text 'display-1' - 'display-4' 'display-1-font' - 'display-4-font' Display text Complete Example // โš ๏ธ STANDALONE definition - NO map-merge with core variables! $o-theme-font-configs : ( 'Poppins' : ( 'family' : ( 'Poppins' , sans-serif ) , 'url' : 'Poppins:300,300i,400,400i,500,500i,600,600i,700,700i' , 'properties' : ( 'base' : ( 'font-size-base' : ( 15 / 16 ) * 1rem , 'header-font-size' : ( 15 / 16 ) * 1rem , ) , ) , ) , 'Playfair Display' : ( 'family' : ( 'Playfair Display' , serif ) , 'url' : 'Playfair+Display:400,400i,700,700i' , ) , 'Inter' : ( 'family' : ( 'Inter' , sans-serif ) , 'url' : 'Inter:300,400,500,600,700' , ) , ) ; Arabic/RTL Font Support $o-theme-font-configs : ( 'IBM Plex Sans Arabic' : ( 'family' : ( 'IBM Plex Sans Arabic' , sans-serif ) , 'url' : 'IBM+Plex+Sans+Arabic:100,200,300,400,500,600,700' , ) , 'Cairo' : ( 'family' : ( 'Cairo' , sans-serif ) , 'url' : 'Cairo:200,300,400,500,600,700,800,900' , ) , 'Almarai' : ( 'family' : ( 'Almarai' , sans-serif ) , 'url' : 'Almarai:300,400,700,800' , ) , ) ; ๐Ÿ“š 2. $o-color-palettes - Color System $o-color-palettes defines all color palettes with 5 core colors plus component assignments. The Five Core Colors Color Semantic Meaning Typical Usage o-color-1 Primary/Accent Brand color, buttons, links, highlights o-color-2 Secondary Complementary accent, secondary buttons o-color-3 Light Background Section backgrounds, cards, light areas o-color-4 White/Lightest Main content background (usually #FFFFFF) o-color-5 Dark/Text Dark backgrounds, text color, footer Visual Representation โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ o-color-4 (White Background) โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ o-color-3 (Light Section) โ”‚ โ”‚ โ”‚ โ”‚ Text: o-color-5 (Dark) โ”‚ โ”‚ โ”‚ โ”‚ Links: o-color-1 (Primary) โ”‚ โ”‚ โ”‚ โ”‚ Buttons: o-color-1 (Primary), o-color-2 (Sec)โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ o-color-5 (Dark Section - Footer) โ”‚ โ”‚ โ”‚ โ”‚ Text: o-color-4 (White) โ”‚ โ”‚ โ”‚ โ”‚ Links: o-color-3 (Light) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Color Combinations (o_cc1 - o_cc5) Color combinations are preset color schemes that automatically set background, text, headings, links, and buttons. Class Background Typical Usage o_cc1 o-color-4 (White) Main content areas o_cc2 o-color-3 (Light) Alternate sections o_cc3 o-color-2 (Secondary) Accent sections o_cc4 o-color-1 (Primary) Call-to-action sections o_cc5 o-color-5 (Dark) Footer, dark sections Color Palette Structure $o-color-palettes : map-merge ( $o-color-palettes , ( 'my-palette' : ( // Required: The 5 core colors 'o-color-1' :

09294F

, // Primary (Navy blue) 'o-color-2' :

FFA807

, // Secondary (Orange) 'o-color-3' :

F6F4F0

, // Light background 'o-color-4' :

FFFFFF

, // White 'o-color-5' :

1B212C

, // Dark // Component color assignments (1-5 โ†’ o_cc1-o_cc5) 'menu' : 1 , // Menu uses o_cc1 'footer' : 5 , // Footer uses o_cc5 'copyright' : 5 , // Copyright uses o_cc5 // Color combination overrides 'o-cc1-text' : 'o-color-5' , 'o-cc1-headings' : 'o-color-5' , 'o-cc5-link' : 'o-color-4' , 'o-cc5-btn-primary' : 'o-color-2' , ) , ) ) ; Override Syntax for Color Combinations // Override specific colors within a combination 'o-cc{n}-{property}' : value // Available properties: 'o-cc1-text' :

333333

, // Text color 'o-cc1-headings' : 'o-color-5' , // Headings color 'o-cc1-link' : 'o-color-1' , // Link color 'o-cc1-btn-primary' : 'o-color-1' , // Primary button 'o-cc1-btn-secondary' : 'o-color-2' , // Secondary button // Example for dark background (o_cc5) 'o-cc5-text' : rgba (

fff

, .8 ) , // Semi-transparent white 'o-cc5-headings' : 'o-color-4' , // White headings 'o-cc5-link' : 'o-color-4' , // White links 'o-cc5-btn-primary' : 'o-color-2' , // Orange buttons on dark HTML Usage

< section class = " o_cc o_cc1 pt32 pb32 "

< div class = " container "

< h2

Content </ h2

</ div

</ section

< section class = " o_cc o_cc2 pt32 pb32 "

... </ section

< section class = " o_cc o_cc4 pt32 pb32 "

... </ section

<
section
class
=
"
o_cc o_cc5 pt32 pb32
"
>
...
</
section
>
๐Ÿ“š 3. $o-website-values-palettes - Complete Configuration (115+ Keys)
$o-website-values-palettes
is the
master configuration variable
controlling Bootstrap components, typography, buttons, inputs, header/footer templates, and much more.
Quick Reference by Category
Category
Keys Count
Description
Typography & Fonts
13
Font family configuration
Font Sizes
13
Base and heading sizes
Line Heights
11
Text spacing
Margins
22
Heading and paragraph margins
Buttons
17
Button styling
Inputs
12
Form field styling
Header
13
Header/navigation config
Footer
3
Footer config
Links
1
Link underline behavior
Layout
3
Page layout
Colors & Gradients
5
Color palette and gradients
Google Fonts
2
Additional font loading
Total
115+
3.1 Typography & Fonts
Key
Type
Default
Description
'font'
string
First in config
Base font for entire site
'headings-font'
string
Inherits
font
Font for H1-H6 headings
'navbar-font'
string
Inherits
font
Font for navigation menu
'buttons-font'
string
Inherits
font
Font for button text
'h2-font'
-
'h6-font'
string
Inherits headings
Individual heading fonts
'display-1-font'
-
'display-4-font'
string
Inherits headings
Display text fonts
3.2 Font Sizes
Key
Type
Default
Description
'font-size-base'
size
1rem
Base font size (16px)
'small-font-size'
size
0.875rem
Small text (14px)
'h1-font-size'
-
'h6-font-size'
size
Calculated
Heading sizes
'display-1-font-size'
-
'display-6-font-size'
size
5rem-2.5rem
Display sizes
3.3 Line Heights & Margins
Key
Type
Default
Description
'body-line-height'
number
1.5
Body text line height
'headings-line-height'
number
1.2
All headings line height
'h2-line-height'
-
'h6-line-height'
number
Inherits
Individual heading line heights
'paragraph-margin-top'
size
0
Paragraph top margin
'paragraph-margin-bottom'
size
16px
Paragraph bottom margin
'headings-margin-top'
size
0
Headings top margin
'headings-margin-bottom'
size
0.5rem
Headings bottom margin
'h2-margin-top'
-
'h6-margin-top'
size
Inherits
Individual margins
'h2-margin-bottom'
-
'h6-margin-bottom'
size
Inherits
Individual margins
3.4 Buttons (17 Keys)
Key
Type
Default
Description
'btn-padding-y'
size
Bootstrap
Vertical padding
'btn-padding-x'
size
Bootstrap
Horizontal padding
'btn-font-size'
size
Bootstrap
Font size
'btn-padding-y-sm'
/
'btn-padding-x-sm'
size
Bootstrap
Small button padding
'btn-padding-y-lg'
/
'btn-padding-x-lg'
size
Bootstrap
Large button padding
'btn-font-size-sm'
/
'btn-font-size-lg'
size
Bootstrap
Size variants
'btn-border-width'
size
Bootstrap
Border thickness
'btn-border-radius'
size
Bootstrap
Corner radius
'btn-border-radius-sm'
/
'btn-border-radius-lg'
size
Bootstrap
Size variant radius
'btn-primary-outline'
boolean
false
Primary as outline
'btn-secondary-outline'
boolean
false
Secondary as outline
'btn-primary-flat'
boolean
false
Flat primary style
'btn-secondary-flat'
boolean
false
Flat secondary style
'btn-ripple'
boolean
false
Material Design ripple
3.5 Inputs & Forms (12 Keys)
Key
Type
Default
Description
'input-padding-y'
/
'input-padding-x'
size
Bootstrap
Input padding
'input-font-size'
size
Bootstrap
Input font size
'input-padding-y-sm'
/
'input-padding-x-sm'
size
Bootstrap
Small input padding
'input-padding-y-lg'
/
'input-padding-x-lg'
size
Bootstrap
Large input padding
'input-border-width'
size
Bootstrap
Border thickness
'input-border-radius'
size
Bootstrap
Corner radius
'input-border-radius-sm'
/
'input-border-radius-lg'
size
Bootstrap
Size variant radius
3.6 Header & Navigation (13 Keys)
Key
Type
Values
Default
Description
'header-template'
string
See below
'default'
Header layout
'header-links-style'
string
See below
'default'
Nav link styling
'header-font-size'
size
CSS length
Bootstrap
Header text size
'logo-height'
size
CSS length
Navbar height
Logo height
'fixed-logo-height'
size
CSS length
Smaller
Logo when fixed
'hamburger-position'
string
'left'
/
'center'
/
'right'
'left'
Desktop position
'hamburger-position-mobile'
string
'left'
/
'center'
/
'right'
'left'
Mobile position
'menu-border-width'
size
CSS length
null
Menu border
'menu-border-radius'
size
CSS length
null
Menu corners
'menu-box-shadow'
CSS
shadow/none
null
Menu shadow
'sidebar-width'
size
CSS length
18.75rem
Sidebar width
Header Template Options:
'default'
- Standard horizontal navbar
'hamburger'
- Hamburger menu (collapsed)
'vertical'
- Vertical sidebar navigation
'sidebar'
- Full sidebar layout
Header Links Style Options:
'default'
- Standard links
'fill'
- Filled background on hover
'outline'
- Outline border on hover
'pills'
- Rounded pill-shaped links
'block'
- Block-style links
'border-bottom'
- Underline border on hover
3.7 Footer (3 Keys)
Key
Type
Values
Default
Description
'footer-template'
string
Template name
'default'
Footer layout
'footer-effect'
string
See below
null
Animation effect
'footer-scrolltop'
boolean
true
/
false
false
Scroll-to-top button
Footer Template Options:
'default'
- Standard footer
'centered'
- Center-aligned
'minimalist'
- Clean, minimal
'links'
- Link-heavy
'descriptive'
- Detailed description
Footer Effects:
null
- No effect (static)
'slideout_slide_hover'
- Slide out on hover
'slideout_shadow'
- Shadow on scroll
3.8 Links (1 Key)
Key
Type
Values
Default
Description
'link-underline'
string
'never'
/
'hover'
/
'always'
'hover'
Underline behavior
3.9 Layout (3 Keys)
Key
Type
Values
Default
Description
'layout'
string
'full'
/
'boxed'
'full'
Page layout
'body-image'
URL
Image path
null
Background image
'body-image-type'
string
'image'
/
'pattern'
'image'
Background type
3.10 Colors & Gradients (5 Keys)
Key
Type
Default
Description
'color-palettes-name'
string
null
Active color palette name
'menu-gradient'
CSS gradient
null
Menu background gradient
'menu-secondary-gradient'
CSS gradient
null
Secondary menu gradient
'footer-gradient'
CSS gradient
null
Footer background gradient
'copyright-gradient'
CSS gradient
null
Copyright gradient
3.11 Google Fonts (2 Keys)
Key
Type
Default
Description
'google-fonts'
list
null
Additional Google fonts to load
'google-local-fonts'
map
null
Locally hosted fonts
Complete Example - Modern Corporate Theme
$o-website-values-palettes
:
(
(
// === REQUIRED ===
'color-palettes-name'
:
'my-corporate-palette'
,
// === TYPOGRAPHY ===
'font'
:
'Inter'
,
'headings-font'
:
'Inter'
,
'navbar-font'
:
'Inter'
,
'buttons-font'
:
'Inter'
,
'font-size-base'
:
1rem
,
'headings-line-height'
:
1.3
,
'body-line-height'
:
1.6
,
// === HEADER (NO custom header.xml needed!) ===
'header-template'
:
'default'
,
// or 'hamburger', 'vertical', 'sidebar'
'header-links-style'
:
'default'
,
// or 'pills', 'fill', 'border-bottom'
'logo-height'
:
48px
,
'fixed-logo-height'
:
36px
,
// === BUTTONS ===
'btn-padding-y'
:
0.75rem
,
'btn-padding-x'
:
1.5rem
,
'btn-padding-y-lg'
:
1rem
,
'btn-padding-x-lg'
:
2rem
,
'btn-border-radius'
:
8px
,
'btn-border-radius-lg'
:
12px
,
'btn-ripple'
:
true
,
// === INPUTS ===
'input-padding-y'
:
0.75rem
,
'input-padding-x'
:
1rem
,
'input-border-radius'
:
8px
,
// === FOOTER (NO custom footer.xml needed!) ===
'footer-template'
:
'default'
,
// or 'centered', 'minimalist', 'links'
'footer-scrolltop'
:
true
,
// === LINKS ===
'link-underline'
:
'hover'
,
// or 'never', 'always'
// === LAYOUT ===
'layout'
:
'full'
,
// or 'boxed'
)
,
)
;
โš ๏ธ CRITICAL: SCSS Load Order in Odoo Themes
Theme SCSS files load BEFORE core Odoo variables are defined!
When you use
prepend
in your manifest's asset bundles, your SCSS executes BEFORE Odoo's core
primary_variables.scss
:
LOAD ORDER:
1. YOUR theme's primary_variables.scss (via prepend) โ† FIRST
2. Odoo core primary_variables.scss โ† SECOND
3. Other SCSS files
โ›” CRITICAL LIMITATIONS:
CANNOT use map-merge()
with core variables (they don't exist yet!)
$o-color-palettes
,
$o-theme-color-palettes
,
$o-theme-font-configs
are all UNDEFINED when your theme loads
โŒ WRONG (Will cause "Undefined variable" error):
$o-color-palettes
:
map-merge
(
$o-color-palettes
,
(
...
)
)
;
// ERROR!
$o-theme-font-configs
:
map-merge
(
$o-theme-font-configs
,
(
...
)
)
;
// ERROR!
โœ… CORRECT (Define as standalone):
// Standalone font config (no map-merge!)
$o-theme-font-configs
:
(
'Poppins'
:
(
'family'
:
(
'Poppins'
,
sans-serif
)
,
'url'
:
'Poppins:300,300i,400,400i,500,500i,600,600i,700,700i'
,
)
,
)
;
// Reference existing palette by name
$o-website-values-palettes
:
(
(
'color-palettes-name'
:
'default-1'
,
// Use existing palette name!
'font'
:
'Poppins'
,
// ...other values
)
,
)
;
โŒ WRONG
Do NOT use ir.asset records for Google Fonts in themes - this causes malformed URLs! Theme Page Creation Standard Individual Page Files Pattern (Recommended) Create individual page files instead of a single pages.xml : theme_name/ โ”œโ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ home.xml # Homepage template + page โ”‚ โ”œโ”€โ”€ about.xml # About page template + page โ”‚ โ”œโ”€โ”€ contact.xml # Contact page (inherits website.contactus) โ”‚ โ”œโ”€โ”€ services.xml # Services page template + page โ”‚ โ””โ”€โ”€ menu.xml # Menu configuration โ””โ”€โ”€ views/ โ””โ”€โ”€ templates.xml # Shared templates and layout 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 "

</ div

</ xpath

</ template

Contact Page (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
>
<
field
name
=
"
name
"
>
About
</
field
>
</
record
>
Theme Mirror Model Architecture
How Themes Install to Pages
Theme Module XML
โ†“
theme.ir.ui.view (Template View)
โ†“
theme.website.page (Template Page)
โ†“ (Theme Installation)
โ†“
ir.ui.view (Actual View with website_id)
โ†“
website.page (Actual Page with website_id)
Key Points
Theme modules contain
theme.*
models (templates)
On installation, these convert to actual models with
website_id
Each website gets independent copies, enabling theme reuse
website_id
assignment happens at view creation level
Theme Scaffolding Commands
Command: Scaffold Complete Theme Module
Trigger
User asks to "create theme", "scaffold theme", "generate theme module" Workflow : Detect Context

Determine current Odoo version

cd < project_path

python -c "import sys; sys.path.insert(0, 'helpers'); from version_detector import detect_version; print(detect_version('.'))" Create Module Structure theme_/ โ”œโ”€โ”€ init.py โ”œโ”€โ”€ manifest.py โ”œโ”€โ”€ security/ โ”‚ โ””โ”€โ”€ ir.model.access.csv โ”œโ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ assets.xml โ”‚ โ”œโ”€โ”€ menu.xml โ”‚ โ””โ”€โ”€ pages/ โ”‚ โ”œโ”€โ”€ home_page.xml โ”‚ โ””โ”€โ”€ aboutus_page.xml โ”œโ”€โ”€ views/ โ”‚ โ”œโ”€โ”€ layout/ โ”‚ โ”‚ โ”œโ”€โ”€ header.xml # Header customization (OPTIONAL) โ”‚ โ”‚ โ”œโ”€โ”€ footer.xml # Footer customization (OPTIONAL) โ”‚ โ”‚ โ””โ”€โ”€ templates.xml # Base layout templates โ”‚ โ””โ”€โ”€ snippets/ โ”‚ โ””โ”€โ”€ custom_snippets.xml # Custom snippet definitions โ”œโ”€โ”€ static/ โ”‚ โ””โ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ scss/ โ”‚ โ”‚ โ”œโ”€โ”€ primary_variables.scss โ”‚ โ”‚ โ”œโ”€โ”€ bootstrap_overridden.scss โ”‚ โ”‚ โ””โ”€โ”€ theme.scss โ”‚ โ”œโ”€โ”€ js/ โ”‚ โ”‚ โ”œโ”€โ”€ theme.js โ”‚ โ”‚ โ””โ”€โ”€ snippets_options.js โ”‚ โ””โ”€โ”€ img/ โ””โ”€โ”€ README.md Generate manifest.py { 'name' : 'Theme ' , 'version' : '.1.0.0' , 'category' : 'Website/Theme' , 'author' : 'TaqaTechno' , 'website' : 'https://www.taqatechno.com/' , 'support' : 'support@example.com' , 'license' : 'LGPL-3' , 'depends' : [ 'website' ] , 'data' : [ 'security/ir.model.access.csv' , 'views/layout/templates.xml' , 'views/layout/header.xml' , 'views/layout/footer.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/static/src/scss/primary_variables.scss' ) , ] , 'web.assets_frontend_helpers' : [ 'theme/static/src/scss/bootstrap_overridden.scss' , ] , 'web.assets_frontend' : [ 'theme_/static/src/scss/theme.scss' , 'theme_/static/src/js/theme.js' , ] , 'website.assets_wysiwyg' : [ 'theme_/static/src/js/snippets_options.js' , ] , } , 'installable' : True , 'auto_install' : False , 'application' : False , } Generate primary_variables.scss (COMPLETE v5.0) // =================================================================== // Theme: // Generated by TAQAT Techno /create-theme command v5.0 // =================================================================== // // โš ๏ธ IMPORTANT: This file is PREPENDED before Odoo core variables! // DO NOT use map-merge() with core variables - they don't exist yet! // =================================================================== // === Font Configuration (STANDALONE - no map-merge!) === $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) === // NO bootstrap_overridden.scss needed - configure everything here! $o-website-values-palettes : ( ( // Reference existing palette (avoids map-merge issues) 'color-palettes-name' : 'default-1' , // === Typography === 'font' : 'Inter' , 'headings-font' : 'Inter' , 'navbar-font' : 'Inter' , 'buttons-font' : 'Inter' , // === Header (NO custom header.xml needed!) === // Options: 'default' | 'hamburger' | 'vertical' | 'sidebar' '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 , // === Inputs === 'input-padding-y' : 0.45rem , 'input-border-radius' : 0.25rem , // === Footer (NO custom footer.xml needed!) === // Options: 'default' | 'centered' | 'minimalist' | 'links' | 'descriptive' 'footer-template' : 'default' , 'footer-scrolltop' : true , // === Links & Layout === 'link-underline' : 'hover' , 'layout' : 'full' , ) ) ; Generate Initial Template

< odoo

<
template
id
=
"
layout
"
inherit_id
=
"
website.layout
"
>
<
xpath
expr
=
"
//head
"
position
=
"
inside
"
>
<
meta
name
=
"
theme-name
"
content
=
"
"
/>
</
xpath
>
</
template
>
</
odoo
>
Command: Create Snippet (Version-Aware)
Trigger
User asks to "create snippet", "add custom snippet" Workflow : Detect Odoo Version (determines registration method) For Odoo 17 and Earlier:

< template id = " s_ " name = " "

< section class = " s_ " data-name = " "

< div class = " container "

</ div

</ section

</ template

< template id = " s__insert " inherit_id = " website.snippets "

< xpath expr = " //div[@id='snippet_effect']//t[@t-snippet][last()] " position = " after "

< t t-snippet = " theme_.s_ " string = " " t-thumbnail = " /theme_/static/img/snippets/.svg " /> </ xpath

</ template

For Odoo 18/19:

< template id = " s_ " name = " "

< section class = " s_ " data-name = " "

< div class = " container "

</ div

</ section

</ template

< template id = " snippet_group_custom " inherit_id = " website.snippets "

< xpath expr = " //div[@id='snippet_groups'] " position = " inside "

< t snippet-group = " custom " t-snippet = " website.s_snippet_group " string = " Custom Snippets " /> </ xpath

</ template

< template id = " s__insert " inherit_id = " website.snippets "

< xpath expr = " //div[@id='snippet_structure']/*[1] " position = " before "

< t t-snippet = " theme_.s_ " string = " " group = " custom " t-thumbnail = " /theme_/static/img/snippets/.svg " /> </ xpath

</ template

Generate Snippet Options (if needed) < template id = " s__options " inherit_id = " website.snippet_options "

< xpath expr = " . " position = " inside "

< div data-selector = " .s_ "

< we-select string = " Layout "

< we-button data-select-class = " "

Default </ we-button

< we-button data-select-class = " s__alt "

Alternate </ we-button

</ we-select

< we-row string = " Items "

< we-button data-add-item = " true " data-no-preview = " true " class = " o_we_bg_brand_primary "

Add Item </ we-button

</ we-row

<
we-colorpicker
string
=
"
Background Color
"
data-css-property
=
"
background-color
"
/>
</
div
>
</
xpath
>
</
template
>
Generate JavaScript for Options
(if dynamic behavior needed)
/**
@odoo-module
**/
import
options
from
"@web_editor/js/editor/snippets.options"
;
options
.
registry
.
<
SnippetName
>
=
options
.
Class
.
extend
(
{
/**
* Add item to snippet
*/
addItem
:
function
(
previewMode
,
widgetValue
,
params
)
{
let
$lastItem
=
this
.
$target
.
find
(
'.snippet-item'
)
.
last
(
)
;
if
(
$lastItem
.
length
)
{
$lastItem
.
clone
(
)
.
appendTo
(
this
.
$target
.
find
(
'.snippet-container'
)
)
;
}
}
,
}
)
;
Include in manifest assets
:
'assets'
:
{
'website.assets_wysiwyg'
:
[
'theme_/static/src/js/snippets_options.js'
,
]
,
}
Figma Integration Workflow
Command: Convert Figma Design to Odoo Theme
Trigger
User provides Figma URL or asks to "convert Figma to Odoo", "import Figma design"
Prerequisites
Figma MCP must be available
Workflow
:
Use Figma MCP with Version-Specific Prompt
Convert this Figma design to HTML for Odoo website theme with these requirements:
- Use Bootstrap v classes (not Tailwind)
- Apply proper Odoo theme structure with sections and containers
- Include responsive classes (col-sm-, col-md-, col-lg-*)
- Use semantic HTML5 elements (header, nav, main, section, article)
- Add data attributes for Odoo website builder compatibility
- Map colors to CSS custom properties for theme variables
- Include accessibility attributes (aria-labels, alt text)
Extract Color Palette
Extract the color palette from this Figma design and map to CSS custom properties using the o-color-1 through o-color-5 naming convention for Odoo themes.
Convert HTML to QWeb Template
Wrap in