The homepage cards gave no domain count to Side Hustle or On the Rise and
gave three to Powerhouse, while the in-app plan page (odoo/upsell.html) and
the published terms.html both say one domain for Side Hustle and three for
On the Rise and Powerhouse. Cards now read 1 / 3 / 3; PRODUCT.md and
llms.txt carry the same counts so no future page has to guess.
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.
New page odoo-hosting-2027.html (feature + lifetime-cost comparison tables,
Odoo Online exclusion, Enterprise growth path, JSON-LD). Links it from the
homepage pricing CTA, adds it to sitemap.xml, adds llms.txt for AI-SEO.
Updates the homepage footer tagline to name AI Agents and N8N
automations explicitly. Markup-preserving: existing <strong> emphasis
on "stability" and "power" is unchanged; no structural, style or
layout changes.
- Buy Now product IDs aligned to the Odoo shop (54/55/56), matching odoo/upsell.html
- support.html contact form: rewire from dead ODOO4projects.com/website/form endpoint to n8n CRM webhook; remove /web/csrf_token prefetch; show success only on res.ok (previously always showed 'submitted' even when nothing was delivered)
- /contactus links (footer nav, Schema contactPoint, order widget fallback, trial email) retargeted to support.html#contact; canonical/og:url corrected to /support.html
- Custom Quote and footer contact handlers hardened with res.ok checks
- buyNow basket target verified: 20.odoo4projects.com/shop/post_basket (200)
- Dark text (#171c26) for all form fields in modal on ivory background
- Explicit colors for labels, inputs, placeholders
- Close button (X) now visible with midnight background
- Change section header to 'Order & Pricing'
- Add 'Get Custom Quote' button that opens modal with name, email, requirements fields
- Requirements field has placeholder: 'Describe your requirements (how many users? onsite, cloud? how many workers?)'
- Submit to https://n8n.odoo4projects.com/webhook/ODOO4projects/crm with UTM tracking
- Empire 'Get Custom Quote' button now opens modal instead of Order Widget
- Add CSS for modal overlay, form styling, and mobile responsiveness
- includes spin_up_free_trial skill with MCP server reference
- defines six server locations (Manchester, Sydney, Mumbai, São Paulo, Meppel, Boston)
- provides workflow steps and clear instructions for conversational agents
- Replace hidden form POST (target='_blank') with silent fetch() that
ignores the response — no new window opens
- Send boolean values directly instead of serializing to 'true'/'false' strings
- Update subtitle: 'Download your PDF in minutes.' -> 'We will send the report in minutes.'
- Add email input field after textareas, before checkboxes
- Email required via both HTML 'required' attribute and JS validation
- POST email field to webhook as 'email' key
- Add .biz-field input[type='email'] CSS (inline + external) matching textarea style
- Update success message: 'We will email you the report once it is ready. AI generation typically takes 1-2 minutes.'
- Remove reference to new window / auto-download (no longer opens window)
- Replace fetch() with hidden form POST + target='_blank' so the webhook's
auto-download HTML page opens in a new tab/window
- Send form-encoded fields (not JSON) since webhook expects POST form data
- Update success message: 'A new window has opened with your personalized
Odoo project plan. The download will start automatically after research
is complete.'
- Remove dead bizDownloadBtn references (button no longer needed)
- Add 3 checkboxes between textareas and submit button:
- I already have a homepage (bizHasHomepage)
- I already use ODOO (bizUsesOdoo)
- I already have a developer for modules (bizHasDeveloper)
- POST to /webhook/report instead of old webhook UUID
- Include checkbox boolean values in request body
- Add .biz-checkbox-group and .biz-checkbox CSS (inline + external)
- Replace .final-cta section with .biz-wizard section
- Three textarea fields: Business Description, My Goals, Current Challenges
- On submit, POSTs to webhook endpoint that triggers AI Agent to
generate a personalized Odoo project plan PDF
- On success, shows download button if webhook returns download_url
- Inline + external CSS: midnight background, brass-accented form fields
- Scroll animation observer updated to target .biz-wizard .container
- Remove all .final-cta CSS from style.css and inline critical styles
- Remove billing-toggle-wrap HTML (switch + labels)
- Update all 4 pricing cards to show yearly prices by default
with / year period and save percentage
- Simplify openOrderWidget() to always use yearly pricing only
- Remove billing toggle JS block (updatePrices, setBilling, event listeners)
- Remove billing toggle CSS (billing-toggle-wrap, .toggle-*, .toggle-switch)
- Update order widget default display to / year
- Update CTA note to 'Save money, less administration'
- Inline all above-the-fold CSS (hero, server-banner, buttons, layout) as
inline <style> in <head> to eliminate render-blocking style.css
- Load full style.css via media='print' onload pattern (async, non-blocking)
- Move GSAP from <head> to before </body> (right before script.js)
- Preconnect to cdnjs.cloudflare.com
- Override Font Awesome 6 font-display to 'swap' to prevent FOIT
- features-grid changed to repeat(3, 1fr) for 2x3 layout
- 6th cell is a Free Trial card with midnight bg, brass border
- Email input, location dropdown (preselected to best ping server),
brass Send button
- POST to webhook as JSON {email, location}
- On success: form hides, success message shown
- Responsive: 3col -> 2col -> 1col
- Header changed to 'Our Server Locations'
- Cards hardcoded in HTML with just city name + region
- Removed all ping JS (IIFE, pingServer, markBest, etc.)
- Removed server-ping-wrap, best-badge, server-best, ping-spinner,
status-dot, server-optimal CSS
- Removed empty server-optimal div
- Removed card entrance animation (static display)
- Added GSAP 3.12.5 from CDN
- Card stagger entrance now uses gsap.fromTo with 0.6s duration, 0.09 stagger
- Carousel slide uses gsap.timeline: old slides out right (3s), new slides
in from right (3s), label slides in (2.5s after 0.3s offset)
- All animations use power2.out easing
- Image brightness: opacity 0.12→0.25, filter brightness(1.15) saturate(1.1)
- ::after overlay changed from solid midnight @ 0.6 to gradient
(midnight→transparent @ 0.5) — brighter image with smooth falloff
- Replaced city placards with a full server status banner
- Grid of 6 server cards (Amsterdam, Boston, Manchester, Mumbai, São Paulo, Sydney)
- JS pings each server via Image() timing, shows ms latency
- Best server highlighted with brass glow, shadow, and 'Best' badge
- 'Your optimal server location: <city> (<ms> ms)' with bounce animation
- Staggered card entrance animation on page load
- Responsive: 6-col -> 3-col -> 2-col grid