- F2: 'We publish exactly what you write' -> 'We publish what you write —
after we check it: your photo, your email address and for spam' (the page's
own consent line + photo check + spam gate made the absolute false)
- claims sweep: drop the 'no claim we cannot back' meta-claim and the
'not through an agency' absolute; state the individual rule as the
declaration we ask for, and make the card's individual tag read
'(as declared)' to match the OCA tag
- F3: directory lede now says the individual rule is a declaration, not a fact
- F4: 'How this works' 110 -> 44 words (three short lines, no relay promise)
- F5: count framed as 'a number we recorded' (owner-typed, not derived);
photo hint agrees with its '(optional)' label; kicker 'ODOO COMMUNITY
FREELANCERS' -> 'ODOO FREELANCERS' and the meta/og drop 'Odoo Community'
so an Enterprise client is not invited to self-exclude
- F1: the request and invite forms SHIP DARK — their endpoint constants are
empty and the forms stay hidden behind a plain 'not open yet' line
(no submit, so no false confirmation); the invite copy carries the
one-click opt-out line the ICP asked for before the form returns
The new '#request' link in the closing CTA was inheriting the site-wide brass-deep
link colour on the midnight background (3.6:1). It uses brass-bright now, so the
page holds its zero-added impeccable profile (14, same as before the change).
- languages/specialities now POST as comma-separated STRINGS ("English,German"),
not arrays; the build script splits them into separate filter options and tags.
- the client request form is no longer inert: it posts to odoo_experts_quote with
an explicit freelancer pick-list (never an implicit all) and a client address.
- new invite-a-friend form posts to odoo_experts_invite_friend (sender name +
friend email); we send the invitation, not the sender's address.
- both new forms show success only on a returned 200 (n8n answers 200 before the
workflow runs) and promise no timing.
- build-directory.py: render the pick-list, fix the country option casing.
- pages stay drafts (noindex, not in sitemap/llms, no inbound links).
- hide the inert client request form; announce it as coming soon with an email
fallback (no reachable error state, no submit that refuses a completed brief)
- soften the contact claim to 'where a freelancer published their details' and
make a card with no contact say so instead of showing an empty space
- move the admin add/edit panel off the public page to its own draft page
(/odoo-community-developers/admin/), unlinked, reachable only by URL
- admin edit: load-and-confirm the record before writing, and read-modify-write
the booleans so an untouched OCA_member/is_individual keeps its current value
- application form: add Country + Odoo versions (the filters' inputs), GitHub and
OCA profile URLs, and an explicit email-publication consent line
- tighten 'How this works' from ~120 words to two short options + one caveat
- build-directory.py: skip records with no Name; render GitHub/OCA links and the
no-contact line; read Country via alias
Odoo freelancer directory for our clients, built as a draft (noindex, out of
sitemap.xml and llms.txt, no inbound links, no announcement surface, no tracking).
- The list is rendered at BUILD TIME from the single freelancer webhook
(GET/POST .../odoo_experts) so it works with JavaScript disabled; the page
script only filters that HTML.
- Filters (country, odoo_versions, languages, specialities) are printed only when
the live data actually supports them, so a filter that returns nothing never
ships. No record has them yet, so none render today.
- Three forms: freelancer application (POST, no id -> create), admin add/edit
(POST with id -> update), and a client request form whose endpoint is a single
inert constant until the workflow exists.
- No reviews, no ratings, no claims beyond what a freelancer wrote and the count
from our own records. No competitor named.