Public Access
fix(freelancer-directory): apply the ICP re-review — claims sweep, F1 gate
- 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
This commit is contained in:
1 parent
c55c707694
commit
4d5d59f3bd
2 files changed
+78
-41
No files matched your search
@@ -233,7 +233,7 @@
|
|||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="adClients">Projects on ODOO4projects</label>
|
<label for="adClients">Projects on ODOO4projects</label>
|
||||||
<input id="adClients" name="odoo4projects_clients" type="number" min="0" />
|
<input id="adClients" name="odoo4projects_clients" type="number" min="0" />
|
||||||
<span class="hint">Our own count, not the freelancer's.</span>
|
<span class="hint">A number we record ourselves — not the freelancer's, not a rating.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="adFocus">Focus</label>
|
<label for="adFocus">Focus</label>
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Find an Odoo Freelancer for Your Project</title>
|
<title>Find an Odoo Freelancer for Your Project</title>
|
||||||
<meta name="description" content="Browse independent Odoo freelancers for your project and write to one directly, using the contact details they have published. Odoo Community specialists." />
|
<meta name="description" content="Browse independent Odoo freelancers for your project and write to one directly, using the contact details they have published." />
|
||||||
<!-- DRAFT: not indexed, not linked, not in sitemap.xml / llms.txt. All five draft
|
<!-- DRAFT: not indexed, not linked, not in sitemap.xml / llms.txt. All five draft
|
||||||
conditions hold (noindex · not in sitemap · not in llms.txt · no inbound links ·
|
conditions hold (noindex · not in sitemap · not in llms.txt · no inbound links ·
|
||||||
no announcement surface). Remove this robots meta on go-live. -->
|
no announcement surface). Remove this robots meta on go-live. -->
|
||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="canonical" href="https://odoo4projects.com/odoo-community-developers/" />
|
<link rel="canonical" href="https://odoo4projects.com/odoo-community-developers/" />
|
||||||
<meta property="og:title" content="Find an Odoo freelancer for your project" />
|
<meta property="og:title" content="Find an Odoo freelancer for your project" />
|
||||||
<meta property="og:description" content="Independent Odoo Community freelancers you can write to directly, using the contact details they publish on their card." />
|
<meta property="og:description" content="Independent Odoo freelancers you can write to directly, using the contact details they publish on their card." />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:url" content="https://odoo4projects.com/odoo-community-developers/" />
|
<meta property="og:url" content="https://odoo4projects.com/odoo-community-developers/" />
|
||||||
<meta name="twitter:card" content="summary" />
|
<meta name="twitter:card" content="summary" />
|
||||||
@@ -403,6 +403,27 @@
|
|||||||
.form-noscript a {
|
.form-noscript a {
|
||||||
color: var(--brass-deep);
|
color: var(--brass-deep);
|
||||||
}
|
}
|
||||||
|
/* A relay form whose route is not built yet: the form is hidden and this plain
|
||||||
|
line stands in its place — not a warning, just the current state. */
|
||||||
|
.form-notlive {
|
||||||
|
max-width: 860px;
|
||||||
|
margin: 1.25rem auto 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--ink-soft);
|
||||||
|
}
|
||||||
|
.form-notlive a {
|
||||||
|
color: var(--brass-deep);
|
||||||
|
}
|
||||||
|
.section-dark .form-notlive {
|
||||||
|
color: rgba(255, 255, 255, 0.78);
|
||||||
|
}
|
||||||
|
.form-lede {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--ink-soft);
|
||||||
|
}
|
||||||
.form-field input,
|
.form-field input,
|
||||||
.form-field textarea,
|
.form-field textarea,
|
||||||
.form-field select {
|
.form-field select {
|
||||||
@@ -641,7 +662,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p class="hero-kicker">ODOO COMMUNITY FREELANCERS</p>
|
<p class="hero-kicker">ODOO FREELANCERS</p>
|
||||||
<h1>Find an Odoo freelancer for your next project</h1>
|
<h1>Find an Odoo freelancer for your next project</h1>
|
||||||
<p class="hero-sub">Independent Odoo specialists you can hire for the piece you cannot do yourself — a custom module, a migration, an integration, an app your business needs. Write to a freelancer directly, using the contact details they publish on their card.</p>
|
<p class="hero-sub">Independent Odoo specialists you can hire for the piece you cannot do yourself — a custom module, a migration, an integration, an app your business needs. Write to a freelancer directly, using the contact details they publish on their card.</p>
|
||||||
<div class="hero-actions">
|
<div class="hero-actions">
|
||||||
@@ -656,9 +677,9 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">How this works</h2>
|
<h2 class="section-title">How this works</h2>
|
||||||
<div class="oc-body">
|
<div class="oc-body">
|
||||||
<p><strong>Write to a freelancer directly.</strong> Each card carries what that freelancer published — their focus, their languages, the work they take on, and their contact details where they chose to publish them. We do not rate them and we do not recommend one over another.</p>
|
<p><strong>Write to a freelancer directly —</strong> each card carries what they published, and their contact details where they published them.</p>
|
||||||
<p><strong>Or let us ask them for you.</strong> Post your brief once and pick the freelancers you want it to reach. We forward it to them with no name attached, and we send their answers back to you — see <a href="#request">Post a request</a> below.</p>
|
<p><strong>Or email us your brief</strong> and we pass it to the freelancers you name.</p>
|
||||||
<p>Either way the work is agreed between you and the freelancer. We publish the listings; the project and the contract are yours.</p>
|
<p>Either way, the work is agreed between you and them.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -667,7 +688,7 @@
|
|||||||
<section class="section-dark" id="directory">
|
<section class="section-dark" id="directory">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">Freelancers available</h2>
|
<h2 class="section-title">Freelancers available</h2>
|
||||||
<p class="dir-lede">Everyone listed here works as an individual, not through an agency. Where a card shows a number of projects, that is a count from our own records — not a rating, a score or an endorsement. We make no claim about a freelancer beyond what they wrote and what we can count ourselves.</p>
|
<p class="dir-lede">Listings are for freelancers who work on their own — that is the declaration we ask each of them for, and we do not verify it. Where a card shows a number of projects, that is a number we recorded — not a rating, a score or an endorsement. We make no claim about a freelancer beyond what they wrote and what we can count ourselves.</p>
|
||||||
|
|
||||||
<!-- Rendered at build time from our freelancer webhook (one call, no CRM),
|
<!-- Rendered at build time from our freelancer webhook (one call, no CRM),
|
||||||
so the list works with JavaScript disabled. The filter controls below are
|
so the list works with JavaScript disabled. The filter controls below are
|
||||||
@@ -693,7 +714,7 @@
|
|||||||
<ul class="dev-tags">
|
<ul class="dev-tags">
|
||||||
<li class="dev-tag">OCA member (as declared)</li>
|
<li class="dev-tag">OCA member (as declared)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<dl class="dev-facts"><div><dt>Projects on ODOO4projects</dt><dd>4 projects — a count from our own records</dd></div></dl>
|
<dl class="dev-facts"><div><dt>Projects on ODOO4projects</dt><dd>4 projects — a number we recorded</dd></div></dl>
|
||||||
<p class="dev-contact-none">No contact details published for this freelancer.</p>
|
<p class="dev-contact-none">No contact details published for this freelancer.</p>
|
||||||
</article>
|
</article>
|
||||||
<!-- DIRECTORY-LIST-END -->
|
<!-- DIRECTORY-LIST-END -->
|
||||||
@@ -706,20 +727,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Client request / anonymous get-quote — WIRED to the quote route
|
<!-- Client request / anonymous get-quote. The route it posts to
|
||||||
(odoo_experts_quote). The freelancer selection is an explicit pick-list over
|
(odoo_experts_quote) is a STUB the user has yet to build, so the form ships
|
||||||
the directory, built at build time — NEVER a free-text box and NEVER an
|
DARK: its endpoint constant is empty and the form stays hidden behind the
|
||||||
implicit "all". n8n answers 200 BEFORE the workflow runs and also on a bad
|
"not open yet" line below — no way to submit, so no false confirmation. When the
|
||||||
payload, so this form shows the success state ONLY on a returned 200 and
|
workflow exists, set ODOO_EXPERTS_QUOTE_WEBHOOK and the note hides itself.
|
||||||
promises no timing the response cannot substantiate. Rebuild the pick-list with:
|
The freelancer selection is an explicit pick-list over the
|
||||||
|
directory, built at build time — NEVER a free-text box and NEVER an
|
||||||
|
implicit "all". Rebuild the pick-list with:
|
||||||
python3 /root/workspace/webmaster/work/build-directory.py -->
|
python3 /root/workspace/webmaster/work/build-directory.py -->
|
||||||
<section class="section-light" id="request">
|
<section class="section-light" id="request">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">Post a request</h2>
|
<h2 class="section-title">Post a request</h2>
|
||||||
<div class="oc-body">
|
<p class="form-notlive" id="requestNotLive">Not open yet. Email <a href="mailto:hello@odoo4projects.com?subject=Post%20a%20request">hello@odoo4projects.com</a> with your brief and the freelancers you want it to reach — we will pass it on by hand and send their answers back to you.</p>
|
||||||
<p>Pick the freelancers you want to hear from, describe the work in your own words, and leave an address for the answers. We forward your brief to them with <strong>no name attached</strong>, collect what they send back, and pass it on to you. The freelancers answer when they can — we do not promise a time.</p>
|
<div class="dir-forms" id="requestFormWrap" hidden>
|
||||||
</div>
|
|
||||||
<div class="dir-forms">
|
|
||||||
<form class="form-card" id="requestForm" novalidate>
|
<form class="form-card" id="requestForm" novalidate>
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<fieldset class="form-field full dir-pickfield">
|
<fieldset class="form-field full dir-pickfield">
|
||||||
@@ -755,7 +776,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">Are you an Odoo freelancer? Get listed</h2>
|
<h2 class="section-title">Are you an Odoo freelancer? Get listed</h2>
|
||||||
<div class="oc-body">
|
<div class="oc-body">
|
||||||
<p>If you work as an independent Odoo developer and want clients to find you here, apply below. We publish exactly what you write — no rating, no ranking, and no claim we cannot back. We ask for your email so we can confirm it is really you before your listing goes live. The directory is for freelancers working on their own; it is not open to agencies.</p>
|
<p>If you work as an independent Odoo developer and want clients to find you here, apply below. We publish what you write — after we check it: your photo, your email address and for spam. No rating and no ranking. We ask for your email so we can confirm it is really you before your listing goes live. The directory is for freelancers working on their own — we ask each applicant to declare that; it is not open to agencies.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="dir-forms">
|
<div class="dir-forms">
|
||||||
<form class="form-card" id="applyForm" novalidate>
|
<form class="form-card" id="applyForm" novalidate>
|
||||||
@@ -824,7 +845,7 @@
|
|||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="apImage">Photo <span class="hint">(optional)</span></label>
|
<label for="apImage">Photo <span class="hint">(optional)</span></label>
|
||||||
<input id="apImage" name="Image" type="file" accept="image/*" />
|
<input id="apImage" name="Image" type="file" accept="image/*" />
|
||||||
<span class="hint">A photo of a person is personal data. It is checked before it is published.</span>
|
<span class="hint">Leave it out if you prefer. If you add one it goes on your card, and it is checked before it is published.</span>
|
||||||
</div>
|
</div>
|
||||||
<label class="form-check">
|
<label class="form-check">
|
||||||
<input type="checkbox" name="OCA_member" value="1" />
|
<input type="checkbox" name="OCA_member" value="1" />
|
||||||
@@ -848,15 +869,17 @@
|
|||||||
<!-- Invite a friend (form 4) — freelancer-facing, placed next to the application
|
<!-- Invite a friend (form 4) — freelancer-facing, placed next to the application
|
||||||
form: it is a freelancer-to-freelancer action, not something a client does.
|
form: it is a freelancer-to-freelancer action, not something a client does.
|
||||||
WE send the invitation from our own address; the sender's address sends
|
WE send the invitation from our own address; the sender's address sends
|
||||||
nothing. POSTs to the invite route (odoo_experts_invite_friend). -->
|
nothing. The route it posts to (odoo_experts_invite_friend) is a STUB the user
|
||||||
|
has yet to build, so the form ships DARK: empty endpoint constant, hidden behind
|
||||||
|
the "not open yet" line below — no submit, no false confirmation. The invitation
|
||||||
|
must carry a visible one-click opt-out before this form is switched on. -->
|
||||||
<section class="section-light" id="invite">
|
<section class="section-light" id="invite">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">Know another Odoo freelancer?</h2>
|
<h2 class="section-title">Know another Odoo freelancer?</h2>
|
||||||
<div class="oc-body">
|
<p class="form-notlive" id="inviteNotLive">Not open yet. Email <a href="mailto:hello@odoo4projects.com?subject=Invite%20a%20freelancer">hello@odoo4projects.com</a> a name and an address and we will invite them by hand — the invitation says who suggested them and carries a one-click opt-out.</p>
|
||||||
<p>Send us your name and a fellow freelancer's email address. <strong>We</strong> email them one invitation to sign up — from ODOO4projects, not from your address — and we tell them you suggested it. We use their address for that invitation only.</p>
|
<div class="dir-forms" id="inviteFormWrap" hidden>
|
||||||
</div>
|
|
||||||
<div class="dir-forms">
|
|
||||||
<form class="form-card" id="inviteForm" novalidate>
|
<form class="form-card" id="inviteForm" novalidate>
|
||||||
|
<p class="form-lede">Send us your name and a fellow freelancer's email address. <strong>We</strong> email them one invitation to sign up — from ODOO4projects, not from your address — and we tell them you suggested it. The invitation carries a one-click opt-out, and we use their address for that invitation only.</p>
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="ivName">Your name</label>
|
<label for="ivName">Your name</label>
|
||||||
@@ -883,7 +906,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="section-title">Start</h2>
|
<h2 class="section-title">Start</h2>
|
||||||
<div class="cmp-lead">
|
<div class="cmp-lead">
|
||||||
<p>Browse the freelancers and write to one directly from their card — or <a href="#request">post your brief</a> and we will forward it to the freelancers you pick, with no name attached.</p>
|
<p>Browse the freelancers and write to one directly from their card — or email us your brief and we will pass it to the freelancers you pick.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="cmp-cta-actions">
|
<div class="cmp-cta-actions">
|
||||||
<a href="#directory" class="btn btn-brass btn-lg">Browse the freelancers</a>
|
<a href="#directory" class="btn btn-brass btn-lg">Browse the freelancers</a>
|
||||||
@@ -962,12 +985,13 @@
|
|||||||
============================================================================ */
|
============================================================================ */
|
||||||
var ODOO_EXPERTS_WEBHOOK =
|
var ODOO_EXPERTS_WEBHOOK =
|
||||||
"https://n8n.odoo4projects.com/webhook/ODOO4projects/odoo_experts";
|
"https://n8n.odoo4projects.com/webhook/ODOO4projects/odoo_experts";
|
||||||
// The anonymous get-quote flow (client → us → freelancers → back to the client).
|
// The two relay routes below are STUBS the user has yet to build. While an
|
||||||
var ODOO_EXPERTS_QUOTE_WEBHOOK =
|
// endpoint is empty, the form that posts to it stays hidden behind a plain
|
||||||
"https://n8n.odoo4projects.com/webhook/ODOO4projects/odoo_experts_quote";
|
// "not open yet" line (see #requestNotLive / #inviteNotLive) — the visitor can
|
||||||
// A freelancer invites a friend to sign up.
|
// never submit, so the page can never confirm an action nothing performs.
|
||||||
var ODOO_EXPERTS_INVITE_WEBHOOK =
|
// Set the URL to switch a form on; its note then hides itself. Nothing else changes.
|
||||||
"https://n8n.odoo4projects.com/webhook/ODOO4projects/odoo_experts_invite_friend";
|
var ODOO_EXPERTS_QUOTE_WEBHOOK = "";
|
||||||
|
var ODOO_EXPERTS_INVITE_WEBHOOK = "";
|
||||||
|
|
||||||
// Wire shape, per the user: `languages` and `specialities` are COMMA-SEPARATED
|
// Wire shape, per the user: `languages` and `specialities` are COMMA-SEPARATED
|
||||||
// STRINGS ("English,German"), NOT arrays — so the workflow can split one field.
|
// STRINGS ("English,German"), NOT arrays — so the workflow can split one field.
|
||||||
@@ -1072,6 +1096,17 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Switch a relay form on only when its route exists. While the endpoint is
|
||||||
|
empty the form stays hidden and the "not open yet" note stands — no submit,
|
||||||
|
no false confirmation. Set the endpoint constant to reveal the form. */
|
||||||
|
function wireRelay(formWrapId, noteId, endpoint) {
|
||||||
|
if (!endpoint) return;
|
||||||
|
var wrap = document.getElementById(formWrapId);
|
||||||
|
var note = document.getElementById(noteId);
|
||||||
|
if (wrap) wrap.hidden = false;
|
||||||
|
if (note) note.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Directory filtering (an enhancement over the build-time HTML) ---- */
|
/* ---- Directory filtering (an enhancement over the build-time HTML) ---- */
|
||||||
function initFilters() {
|
function initFilters() {
|
||||||
var bar = document.getElementById("dirFilters");
|
var bar = document.getElementById("dirFilters");
|
||||||
@@ -1155,11 +1190,10 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Form 3: anonymous client request (posts to the quote route) ----
|
/* ---- Form 3: anonymous client request. SHIPS DARK — the route is a stub, so
|
||||||
The client picks the freelancers, writes the brief and leaves an address for
|
wireRelay keeps it hidden until ODOO_EXPERTS_QUOTE_WEBHOOK is set; these
|
||||||
the answers. n8n returns 200 BEFORE the workflow runs and also on a bad
|
handlers only run once the workflow exists. The client picks the freelancers,
|
||||||
payload, so a 200 is the only signal we have — the form cannot tell success
|
writes the brief and leaves an address for the answers. */
|
||||||
from failure. Hence: success only on a returned 200, and no promised timing. */
|
|
||||||
function initRequestForm() {
|
function initRequestForm() {
|
||||||
var form = document.getElementById("requestForm");
|
var form = document.getElementById("requestForm");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
@@ -1208,9 +1242,10 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Form 4: invite a friend (posts to the invite route) ----
|
/* ---- Form 4: invite a friend. SHIPS DARK — the route is a stub, so wireRelay
|
||||||
Two fields: the sender's name and a friend's email. WE send the invitation,
|
keeps it hidden until ODOO_EXPERTS_INVITE_WEBHOOK is set. Two fields: the
|
||||||
from our own address — never from the sender's — and we say who suggested it. */
|
sender's name and a friend's email. WE send the invitation, from our own
|
||||||
|
address — never from the sender's — and we say who suggested it. */
|
||||||
function initInviteForm() {
|
function initInviteForm() {
|
||||||
var form = document.getElementById("inviteForm");
|
var form = document.getElementById("inviteForm");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
@@ -1240,6 +1275,8 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wireRelay("requestFormWrap", "requestNotLive", ODOO_EXPERTS_QUOTE_WEBHOOK);
|
||||||
|
wireRelay("inviteFormWrap", "inviteNotLive", ODOO_EXPERTS_INVITE_WEBHOOK);
|
||||||
initFilters();
|
initFilters();
|
||||||
initApplyForm();
|
initApplyForm();
|
||||||
initRequestForm();
|
initRequestForm();
|
||||||
|
|||||||
Reference in new issue
Block a user