Commit Graph
27 Commits
Author SHA1 Message Date
webmaster bd0881f882 cache-bust local assets; narrow the language facet to scores >= 3
Part 1 — asset versioning: every local <script src> and <link rel=stylesheet> on the
tracked pages now carries ?v=<sha256-of-the-file> (10 hex), computed at BUILD time from
the file's bytes by work/build-asset-versions.py — never hand-typed, and idempotent
(re-running with no file change rewrites nothing). This is what makes an edited
focus-rule.js / photo-upload.js a new URL instead of a stale cache hit.

Part 2 — language facet: a language now counts for the Language filter only when its
0-5 self-assessment is >= LANG_FACET_MIN (3 = 'works in it'). The constant sits beside
the 15-point rule in the page script and its mirror in build-directory.py. Nothing
stored changes; the card's languages chart still prints every language above 0, the
search box is unchanged, and the facet stays an exact membership test against the
card's value. A '1' language no longer offers the person under that language.
2026-11-03 21:26:58 +00:00
webmaster 82b74c359a refactor(blog): rebuild Odoo 20 Is Live post on the newest post chrome
Same URL, slug, date and body (body bytes unchanged, sha256 4fea9c0c).
Chrome copied from blog/posts/how-to-install-odoo-modules-using-git.html:
main.blog-post / span.badge / div.post-body / a.back-link, Marcellus headings,
cream palette. Replaces the older .container/.post-content chrome.
2026-11-03 10:16:35 +00:00
webmaster 5d65fa7027 feat(blog): publish Odoo 20 Is Live on Our Servers — Here Is What Changed
New post blog/posts/odoo-20-is-live-on-our-servers-here-is-what-changed.html
(chrome copied from blog/posts/track-the-oca-modules-you-actually-use.html,
body verbatim from the inbox source), plus the blog/index.json entry (first),
one sitemap.xml <url> and one llms.txt blog line.
2026-11-03 10:11:11 +00:00
webmaster 0e832d8fd1 perf(site-wide): render-blocking /style.css on 17 pages; <main> landmark; BF footer form action
Same defect the bootcamp carried (2aa9b19), fixed site-wide in one mechanical pass.

P0 (17 pages): /style.css was deferred via media="print" onload=... -> unstyled
first paint -> a BODY layout shift. Now a normal render-blocking
<link rel="stylesheet">; the now-redundant no-JS <noscript> for style.css is
dropped. Web fonts + Font Awesome keep their legitimate deferral.
Pages: index.html, odoo-black-friday/, odoo-hosting-offers/, de/index.html,
es/index.html, odoo-hosting-2027.html (+de/+es), odoo-community-upgrade.html
(+de/+es), odoo-staging-environment/, odoo-community-ai/,
odoo-n8n-masterclass/, australia.html, workshops/, what-can-i-use-odoo-for/.

P1 (1 page): /odoo-black-friday/ footer form action mailto: -> CRM webhook
(Lighthouse is-on-https). Changed only because the page already loads a handler
for #footerContactForm (static/black-friday.js). The other 13 mailto-form pages
load no handler and are left alone on purpose (no drive-by handler copy-in).
Added the no-JS <noscript> fallback so a JS-off visitor keeps a path.

P2 (35 pages): add a single <main> landmark wrapping the primary content; top
bar and footer stay outside. Additive only, no redesign.

Guards held: bootcamp EN/DE/ES and every JS/static file untouched; Buy forms
product_id 4/17 intact; one [data-bc-seats]; ads-consent gate intact.
verify-html.py PROBLEMS 0; competitor QC 74 pre-existing, 0 added.
2026-11-02 18:18:46 +00:00
oliver bcd0ef890a feat(blog): publish From a Spreadsheet to a Running ERP in Ten Thursday Sessions
New post blog/posts/from-a-spreadsheet-to-a-running-erp.html (area news, 2026-11-02),
body pasted verbatim from the inbox source (sha256 59568fc8…). Chrome copied from the
newest post (oca-paraguay-internationalization-hackathon.html), inline style trimmed to
the rules the page uses. Card image screencast.png wired in three additive places
(post-image after the meta line, og:image, blog/index.json image key) plus BlogPosting
JSON-LD. blog/index.json 17 -> 18, sitemap.xml 42 -> 43 <loc>, llms.txt 17 -> 18 lines,
all text splices (16 insertions, 0 deletions).
2026-11-02 14:39:29 +00:00
webmaster 137bd1a2ae feat(staging): inbound links so /odoo-staging-environment/ is not an orphan
The copy's 'Into this page' table, applied as single additive sentences:
- support.html: the 'error 500 after a git check in' FAQ answer links
  'test it safely first'.
- blog/posts/speed-run-backup.html: end of the post links
  'what a staging environment is, and why you probably do not need one'.
- odoo-hosting-2027.html: one contextual note by the backup/module rows
  links 'do you need a staging environment?'.
- index.html: one FAQ card 'Do you need an Odoo staging environment?'.
No footer change. No new impeccable finding category.
2026-11-01 09:32:52 +00:00
oliver e37acde30c feat(seo): wire internal links between the 17 blog posts and the pages that sell
The blog was an island: zero post→page links to hosting/upgrade/support/courses,
and only one page→post link in the whole site. Posts ranked for nothing while the
old blog host ranked for our long-tail queries.

Posts → pages (26 new in-body contextual links across 17 posts):
each post now carries one or two links to the page that answers its reader's next
question — odoo-hosting-2027, odoo-community-upgrade, support, the workshops hub,
the n8n masterclass, and the plan pricing on index.html#pricing.

Pages → posts (7 pages, one contextual link each):
index.html (OCA section), odoo-hosting-2027, odoo-community-upgrade, support,
workshops/, odoo-n8n-masterclass/, odoo-erp-automation-bootcamp/ now link into the
post that fits their own subject. The clearest miss is fixed — the
community-vs-enterprise-cost post and the odoo-community-upgrade page now link
to each other.

Anchors wrap existing sentences where the text already said the thing; four short
linking sentences were added (index OCA section, support first-steps FAQ, masterclass
lessons, bootcamp included section). No new components, no related-posts widget,
in-body anchors only. English pages only; DE/ES untouched (translator follow-up).
2026-10-29 15:15:00 +00:00
oliver bfa7f595cc feat(blog): publish OCA Paraguay Internationalization Hackathon post
New post blog/posts/oca-paraguay-internationalization-hackathon.html (News,
2026-10-29), body verbatim from the supplied source (sha256 cca84c45...),
chrome copied from how-to-install-odoo-modules-using-git.html with the inline
style trimmed to the figureless variant. Adds the newest-first entry to
blog/index.json (16 -> 17), one 0.6 <url> to sitemap.xml (39 -> 40) and the
top line of the llms.txt blog list (16 -> 17).
2026-10-29 09:03:21 +00:00
oliver 0cd0fa1af1 feat(analytics): Plausible snippet on every page, FAQ marked on the bootcamp
The snippet was on 10 of 40 pages, so the Trial / FAQ / Buy / Custom Quote /
search posts / Project Plan goals were inert everywhere else. It now sits
verbatim, in the same <head> position as index.html, on all 39 visitor-facing
pages. email/trial-confirmation.html is deliberately left out (email template).

FAQ: the five <details class="bc-faq"> <summary> elements on the bootcamp page
and its DE/ES twins now carry plausible-event-name=FAQ, and the 15
.faq-question buttons on de/es/support.html get the marking they were believed
to already have. No goal renamed: one FAQ goal across all languages.

No markup, copy or behaviour change, and no third-party request beyond the
snippet itself. verify-html.py PROBLEMS 0; check-links.py OK; event checker
59 PASS / 0 FAIL; impeccable detector +0/-0 findings on the changed files.
2026-10-28 21:50:53 +00:00
oliver ea97e65416 feat(blog): publish "How to Install Odoo Modules Using Git"
New post at blog/posts/how-to-install-odoo-modules-using-git.html
(2026-10-28, area "deep dive"), body pasted verbatim from the boss's
supplied block (7 h2, two figures in place). Chrome copied from the
newest post (odoo-community-is-going-online-on-odoo4projects.html:
main.blog-post / span.badge / div.post-meta / img.post-image /
div.post-body / a.back-link), style block trimmed to the rules this
page uses plus the ol/figure/figcaption rules its body needs.

Additive wiring: og:image + twitter:card, post-image after post-meta
(alt = h1), BlogPosting JSON-LD with dateModified.

blog/index.json gets the entry first (newest-first, key order
id,date,area,headline,teaser,link,image) by text splice - 15 -> 16
posts; sitemap.xml one new 0.6 blog url - 35 -> 36 <loc>; llms.txt one
new line at the top of the post list.
2026-10-28 10:21:32 +00:00
oliver 3c602d97be fix(seo): legal.html canonical, host-case normalisation, BlogPosting x15, blog body domain typo
Four follow-up defects found beyond the 2026-10-27 SEO audit (no copy changes):

1. legal.html canonical was https://ODOO4projects.com/legal — uppercase host AND a
   path that 404s. Now https://odoo4projects.com/legal.html. The file's og:url keeps
   its path /legal but its host is lowercased (path fix awaiting a decision).
2. The no-"4" domain typo in reader-visible <pre><code> body text of
   blog/posts/{guide-migrate-enterprise,speed-run-deploy,my-first-post}.html:
   odooprojects.com -> odoo4projects.com. Domain string only, no other wording.
3. Lowercase host in every machine-read value: the robots.txt Sitemap line, the
   homepage + de/ + es/ Organization JSON-LD url / contactPoint.url / offers[].url,
   legal.html og:url, and the four absolute self-URL hrefs in blog posts,
   odoo/support.html and email/trial-confirmation.html. Display text untouched
   (support@ODOO4projects.com stays as written).
4. One BlogPosting per blog post (15), every value taken from the page itself:
   headline = its <h1>, datePublished = its visible post-meta date, url = its own
   canonical, author/publisher = the Organization the site already publishes,
   image = its og:image where one exists (omitted on the 10 posts that have none).

Empire ">950.00", FAQPage on support.html, the blog-chrome change and the bootcamp
date conflict are untouched — decisions pending with the user.
2026-10-27 18:54:28 +00:00
webmaster 28f04e13fe fix(seo): repair the 10 blog canonicals, sitemap.xml, blog/index.json and llms.txt
From seo/out/site-seo-ai-search-audit-2026-10-27.md (§6 items 1, 2, 3a, 5).

- canonical: 10 blog posts declared https://odooprojects.com/... — a live parked
  third-party domain — as their canonical. Now self-referencing on
  https://odoo4projects.com/blog/posts/<slug>.html (1 line each, nothing else).
- sitemap.xml: 27 -> 33 URLs. Added the 6 live pages that were missing
  (support.html, legal.html, community-vs-enterprise-cost, 6-tips,
  odoocommunity-agents, odoo-20-is-live); corrected 13 lastmod values to the
  real last content commit (homepage was 4 months stale); /de/ and /es/
  priority 1.0 -> 0.7 so a translation does not outrank its original.
- blog/index.json: 7 -> 15 posts. The 8 orphan posts are now listed, so every
  post is reachable from the homepage grid.
- llms.txt: removed the link to /blog/ (that URL returns 403) and added a
  "## Blog posts" section listing all 15 posts with date and summary.

Not changed on purpose: FAQPage on support.html, the homepage "price": ">950.00",
the bootcamp start-date conflict, and the blog post chrome (15 files).
2026-10-27 18:48:06 +00:00
oliver 0195038bd7 Update the ODOO Community blog post to the live copy
The post carried the planned/September copy ("scheduled to go online on the
06.10.2026"). Body replaced verbatim with the supplied live copy (1379 bytes,
2 h2, 221 words), post-meta -> October 27, 2026 · News, meta/og description
refreshed, title/canonical/chrome/og:image unchanged.

- blog/index.json: the existing entry moved to first, date 2026-10-27,
  teaser = first 120 chars of the new first paragraph (text splice).
- sitemap.xml: one new <url> as the first 0.6 blog entry (24 -> 25 <loc>).
- work/verify-html.py: page added to FILES (in webmaster/work, not in repo).
2026-10-27 09:03:49 +00:00
oliver 62d9d76bde Add supplied post images to two posts and to the blog overview cards
- blog/posts/odoo-19-to-20-invoice-migration-with-n8n-and-mcp.html: in-post image
  much.png + og:image
- blog/posts/track-the-oca-modules-you-actually-use.html: in-post image
  oca_module_status.png + og:image
- blog/index.json: optional "image" key on those two entries only (text splice)
- script.js: renderBlog() draws .blog-thumb only when the entry carries an image
- style.css: .blog-thumb rule
- sitemap.xml: lastmod 2026-10-24 for the invoice-migration post

Built by profile webmaster (run 20261024_094206_5c4f28, verified PROBLEMS: 0 /
node --check OK); committed by olchi after that run died on an OpenRouter 402.
2026-10-24 09:46:13 +00:00
oliver 7b9db81e82 Publish blog post: Track the OCA Modules You Actually Use — Without Refreshing GitHub Every Day 2026-10-24 08:57:30 +00:00
oliver 76e5645585 Publish blog post: This is how i updated my Invoices from Odoo 19 to Odoo 20 with n8n and much MCP 2026-10-23 09:25:02 +00:00
oliver 93511e893d fix(site): correct prices, drop every discount claim and repair trial copy
Applies the 16 findings the user answered in projects/active/odoo-hosting-2027-landing/
decisions-2026-10-21-user.md, using the wording from
copywriter/out/site-fix-wording-2026-10-21.md.

index.html: Powerhouse 535 -> 595 in the card and in the JSON-LD Offer; delete the
three Save 8%/9%/10% badges and the empty badge div on the Empire card; replace the
'Save 15% with yearly billing' line and the coupon message text (ids kept - script.js
reads them); delete the FREE TRIAL coupon input block; qualify the checkout line as
'Card required to buy, not to start'; fix 'redundant slots' to the real rotating-slot
model; drop the 'coupon codes for startups and NGOs' promise; add Privacy and Terms to
the footer.

email/trial-confirmation.html: stop promising backups, domain mapping and SSL on the
trial (the trial has none); state what the trial is not; copyright 2024 -> 2026;
repoint Privacy/Terms from the 404 /legal/privacy and /legal/terms to the new pages.

support.html: state that custom and OCA modules install from On the Rise up and that
Side Hustle has no module installation.

odoo/upsell.html: '4 weeks free' -> '30 days free'.

blog: the backup speed-run no longer sends readers to a non-existent hosting
dashboard; my-first-post loses the 30-day refund promise and the dashboard domain
step; community-vs-enterprise-cost quotes $214/year instead of $19.40/month;
odoocommunity-agents drops 'per-seat licensing' from the body and both meta
descriptions.

sitemap.xml: add /privacy.html and /terms.html.
llms.txt: publish the Powerhouse price and list the two new pages.

Evidence: every old string verified gone and every new string present in the working
tree; 12 HTML files tag-balanced; JSON-LD and sitemap XML valid.
2026-10-21 23:05:22 +00:00
Reef 729289ef71 Publish blog post: 6 Tips to Leverage the Latest Odoo Management App Update 2026-10-08 15:50:04 +00:00
Reef e926f850f7 Publish blog post: Odoo 20 Is Live on Our Servers — With an MCP Server and Free Backups 2026-10-06 22:06:05 +00:00
Reef af866d87e8 Publish blog post: ODOO Community Is Going Online on ODOO4projects 2026-09-28 09:53:40 +00:00
Reef f7460c129d Download static assets from static.odoo4projects.com (agent.js, agent.css, 4.svg, logo.svg, favicon.png) and serve locally. Update all HTML references. 2026-08-24 20:53:34 +00:00
Reef cc5667bf7b Add country note to blog post, reorder posts with latest on top 2026-06-27 15:31:10 +00:00
Reef 358e480ea6 Add blog post: Odoo Community vs Enterprise cost breakdown with comparison tables 2026-06-27 15:23:19 +00:00
Reef 88e9cbd9f5 Unify all pages with homepage light theme: support, legal, and 9 blog posts (purple primary, light bg) 2026-06-24 21:39:51 +00:00
Reef 7871bacb8a Fix: create missing blog post, move Trusted By section above pricing 2026-06-24 18:44:12 +00:00
Reef ee8d071835 Update blog posts: single post about ODOO Community for AI agents 2026-06-24 15:56:03 +00:00
oliver fa3694bd58 blog 2026-06-24 06:55:38 -03:00