git clone https://github.com/19prince/claude-odoo-builder
T=$(mktemp -d) && git clone --depth=1 https://github.com/19prince/claude-odoo-builder "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/new-odoo-project" ~/.claude/skills/19prince-claude-odoo-builder-new-odoo-project && rm -rf "$T"
skills/new-odoo-project/SKILL.mdSkill: new-odoo-project
TRIGGER: User invokes
/new-odoo-project to scaffold a new Odoo website builder project.
Objective
Scaffold a new Odoo website builder project directory, copy all bundled tools and workflows from the skill's
templates/ directory, create a configured .env template, and orient the user for their first session.
Prerequisites
Before running this skill, ensure the following are in place:
- Python 3.8+ installed and available as
python3 - Python packages — install from the bundled requirements file:
This installspip install -r {skill_dir}/templates/requirements.txt
andrequests
, the only third-party dependencies.python-dotenv - An Odoo instance with admin or API access (URL, database name, and login email)
- Claude Code — this skill is designed for Claude Code's skill system
Step 1 — Gather technical information (ask all at once)
Ask the user for the following in a single message. Do not proceed until you have answers:
- Project parent directory — the folder where the project subdirectory should be created (e.g.
or~/projects
)~/Odoo - Client / project name — used for folder naming and memory. The project will be created at
(e.g.{parent_dir}/{slugified-client-name}/
)~/Odoo/client-acme/ - Odoo URL — e.g.
https://mysite.odoo.com - Odoo DB name — e.g.
mysite-main-12345 - Odoo login email
- Is this a production-only server, or is there a separate staging instance?
- If staging + production: collect both URLs and DB names (but NOT passwords)
- If production only: note that changes go live immediately — extra caution required
Do NOT ask for any passwords. Tell the user: "I'll leave the password fields blank in
.env — fill those in yourself before running any tools."
Do NOT ask about brand, fonts, or design yet — those come after the project is set up.
Step 2 — Create the project directory
Derive
{project_dir} by slugifying the client name (lowercase, replace spaces with hyphens) and appending it to the parent directory: {parent_dir}/{slugified-client-name}.
For example, if parent is
~/Odoo and client name is "Demo Video", then {project_dir} = ~/Odoo/demo-video.
mkdir -p {project_dir}/tools mkdir -p {project_dir}/workflows mkdir -p {project_dir}/.tmp
Step 3 — Copy tools from skill templates
Copy all
.py files from the skill's bundled templates. The skill's base directory is provided when invoked — use it to locate templates/tools/:
cp {skill_dir}/templates/tools/*.py {project_dir}/tools/
The
migrate_to_production.py template ships pre-cleaned with empty META_UPDATES, CSS_VIEW_KEYS, and PAGE_URLS lists, and a clean main() with commented examples. No post-copy cleanup is needed.
Step 4 — Copy workflows from skill templates
cp {skill_dir}/templates/workflows/*.md {project_dir}/workflows/
Workflows are generic and apply to any Odoo project without modification.
Step 4b — Create .gitignore
.gitignoreWrite
.gitignore to the project root to prevent committing secrets and temporary files:
# Credentials .env # Temporary files .tmp/ # Python __pycache__/ *.pyc *.pyo # OS files .DS_Store Thumbs.db # IDE .vscode/ .idea/
Step 5 — Create .env
.envWrite
.env to the project root. Leave all password fields blank.
For a staging + production setup:
# Staging ODOO_URL={staging_url} ODOO_DB={staging_db} ODOO_USER={login_email} ODOO_PASSWORD= # Production (fill in when ready to migrate) # PROD_ODOO_URL={prod_url} # PROD_ODOO_DB={prod_db} # PROD_ODOO_USER= # PROD_ODOO_PASSWORD=
For a production-only setup:
# Production (working directly on production — no staging) ODOO_URL={odoo_url} ODOO_DB={odoo_db} ODOO_USER={login_email} ODOO_PASSWORD=
Step 6 — Create CLAUDE.md
CLAUDE.mdWrite
CLAUDE.md to the project root using this template:
# Agent Instructions You're working inside the **WAT framework** (Workflows, Agents, Tools). ## The WAT Architecture **Layer 1: Workflows** — Markdown SOPs in `workflows/` **Layer 2: Agents** — Your role: read workflows, run tools, handle failures **Layer 3: Tools** — Python scripts in `tools/` for deterministic execution ## How to Operate 1. Look for existing tools before building new ones 2. Learn and adapt when things fail — update workflows with findings 3. Keep workflows current as the project evolves ## File Structure \`\`\` .tmp/ # Temporary files — regenerated as needed tools/ # Python scripts workflows/ # Markdown SOPs .env # Credentials — NEVER commit this \`\`\` ## Project: {client_name} - **Server:** {odoo_url} - **DB:** {odoo_db} - **Brand colors:** TBD - **Brand fonts:** TBD - **Design direction:** TBD - **Logo:** TBD > ⚠️ [Production-only note if applicable: This project works directly on production. There is no separate staging server. Always use `--dry-run` before any migration. Be extra careful — changes go live immediately.] ## Key Workflows - `workflows/design_page.md` — designing and building pages - `workflows/push_to_odoo.md` — pushing content to Odoo - `workflows/css_theming.md` — CSS injection pattern - `workflows/migrate_staging_to_prod.md` — staging → production migration ## Rules - Always read a workflow before starting a task that matches it - Never store secrets anywhere except `.env` - Validate HTML before pushing: `python3 tools/validate_html.py --input .tmp/draft.html` - Always dry-run before migrating to production
Step 7 — Verify setup
Run a connection test:
cd {project_dir} && python3 -c " import sys; sys.path.insert(0, 'tools') from odoo_client import OdooClient c = OdooClient() uid = c.authenticate() print('Connected — uid:', uid) pages = c.search_read('website.page', [('active','=',True)], ['url','name','is_published']) print(f'{len(pages)} pages found:') for p in sorted(pages, key=lambda x: x['url']): pub = 'published' if p['is_published'] else 'draft' print(f' {p[\"url\"]:<35} {pub}') "
If authentication error: remind the user to fill in
ODOO_PASSWORD in .env.
If connection error: ask the user to double-check
ODOO_URL and ODOO_DB.
Step 8 — Verify the WYSIWYG editor and snippet blocks
This step must be done by the user in a browser. Instruct them to:
- Log into the Odoo backend and open the website editor on any page (click Edit in the top bar)
- Look at the right-hand Blocks panel — confirm snippet thumbnails load with no orange ! warning icons
- Drag any block (e.g. a Text block) onto the page — confirm it drops and renders without errors
- Click an existing text element — confirm the formatting toolbar appears
- Click an existing image — confirm the image toolbar appears
If snippet blocks show orange ! icons (all or most of them):
Root cause: No theme is linked to the website (
theme_id = False). This causes Odoo's snippet rendering to fail.
Fix — install and link
:theme_clean
python3 - <<'EOF' import sys sys.path.insert(0, 'tools') from odoo_client import OdooClient c = OdooClient() c.authenticate() # Find theme_clean module modules = c.search_read("ir.module.module", [["name", "=", "theme_clean"]], ["id", "name", "state"]) print("theme_clean:", modules) # If state is 'uninstalled', install it if modules and modules[0]["state"] == "uninstalled": module_id = modules[0]["id"] c._execute_kw("ir.module.module", "button_immediate_install", [[module_id]], {}) print("Installed theme_clean") # Link theme to website sites = c.search_read("website", [], ["id", "name", "theme_id"]) print("Sites:", sites) theme_module = c.search_read("ir.module.module", [["name", "=", "theme_clean"]], ["id"]) theme_id = theme_module[0]["id"] c.write("website", [sites[0]["id"]], {"theme_id": theme_id}) print(f"Linked theme_clean (id={theme_id}) to website {sites[0]['id']}") EOF
After running, ask the user to hard-refresh the editor page (
Cmd+Shift+R) and confirm the orange icons are gone.
Important: After installing
theme_clean, re-push any existing custom_code_head CSS — the theme installation may reset the field.
If the editor toolbar appears but JS errors occur in the console, check
custom_code_head for any <script> tags — JS in custom_code_head breaks the editor widget panel. Remove all <script> blocks and use CSS-only approaches instead.
Step 9 — Gather branding information
Now that the project is set up and connected, ask the user for branding details in a single message:
- Brand colors — primary, secondary, background (or "TBD")
- Brand fonts — or "TBD"
- Design direction — e.g. dark theme, light theme, minimal, bold (or "TBD")
- Logo — do they have a logo file, or is it text-only? (or "TBD")
Once answered (even if all "TBD"), update
CLAUDE.md with the values:
- Replace
,{brand_colors}
,{brand_fonts}
placeholders with the actual answers{design_direction}
Step 10 — Save to memory
Create a memory file for this project. Determine the memory path from the project directory path by converting it to the Claude project slug format (replace
/ with -, strip leading -).
Memory file location:
~/.claude/projects/{slugified_project_dir}/memory/MEMORY.md
Include:
- Client name and project directory
- Odoo URL and DB
- Brand colors, fonts, and design direction (even if TBD)
- Logo notes if provided
- Production URL and DB if provided
- Note if production-only (no staging)
Step 11 — Output summary
Print a clean summary:
Project scaffolded: {project_dir} tools/ — Python scripts (from skill templates) workflows/ — Markdown SOPs (from skill templates) .env — fill in ODOO_PASSWORD before running tools CLAUDE.md — project instructions written Next steps: 1. Fill in ODOO_PASSWORD in .env 2. Open a new Claude Code session pointed at {project_dir} 3. Verify connection: python3 tools/list_pages.py
Notes
- Never ask for passwords — always leave password fields blank for the user to fill in
- Brand/font/design questions come in Step 9, after the project is set up and connected — never ask them upfront
- If the user says "TBD" for any brand field, write "TBD" in CLAUDE.md — it can be updated later
- The
migrate_to_production.py
list starts empty — it gets populated as meta descriptions are written during the projectMETA_UPDATES - The
directory starts empty — that's correct.tmp/ - For production-only projects, add the
warning to CLAUDE.md and remind the user throughout the session that changes are live immediately⚠️
Appendix — Complete Odoo Theming Checklist
Use this as a tracking checklist at the start of every project. Every surface below needs to be reviewed and styled (or explicitly accepted as default). Check each off as CSS is pushed to
custom_code_head.
Pages (full-page layouts)
| Surface | URL | Body class / selector | Notes |
|---|---|---|---|
| Homepage | | — | Custom page arch |
| Shop listing | | | Product grid, filters, pagination |
| Shop category | | | Same as shop listing |
| Product detail | | | PDP — name, price, add-to-cart, tabs |
| Shopping cart | | , | Line items, totals, checkout CTA |
| Checkout | | | Address form, payment, confirm button |
| Order confirmation | | | Thank-you message, order summary |
| Contact form | | | Form fields, submit button |
| Contact thank-you | | | Post-submit confirmation message |
| 404 / error | | | Odoo default error page |
| Blog listing | | | Post cards, sidebar, pagination |
| Blog post | | | Post header, content, author, related posts |
| Login | | | Separate from website layout — needs scoped CSS |
| Signup / Register | | | Same caveat as login |
| Customer portal home | | | Portal layout is separate from website layout |
| My Orders | | | Order list |
| Order detail | | | Line items, status, download PDF |
| My Account | | | Profile / address edit form |
| Wishlist | | | Only if Wishlist module is installed |
UI Elements (overlays, modals, popups, widgets)
| Element | Selector | Notes |
|---|---|---|
| Cookie consent banner | , | Appears on first visit |
| "Added to cart" toast | , | Triggered on add-to-cart |
| Product quick-view modal | | Shop listing — if quick-view is enabled |
| Search overlay / autocomplete | , | Global site search |
| Newsletter popup | | If Newsletter popup snippet is placed |
| Mobile nav drawer | | Hamburger menu on mobile |
| Live chat widget | , | If Livechat module is installed |
| Wishlist sidebar | | If Wishlist module is installed |
| My Account dropdown | | Top-right user menu when logged in |
How to use this checklist
- At the start of the project, paste this checklist into
.tmp/theming_checklist.md - Mark each row
(not done),[ ]
(styled), or[x]
(skipped / not applicable)[—] - After pushing each CSS block, update the checklist
- Do not mark a project complete until all applicable rows are checked