A foundation site on Rue de Varembé, a think-tank report landing near Place des Nations, or an advisory-firm service page on Quai du Mont-Blanc is not a reason for WordPress to pretend it is a UN enterprise system or a bank transaction platform. It is a reason for the block theme, Gutenberg patterns, CPT and plugins to be written the way a Geneva legal team, a multilingual editorial desk and a Polish developer publishing from Warsaw expect: French front with formal vous, not tu.
WPPoland builds this WordPress from a senior Polish team for companies, foundations and organisations with a headquarters, branch or donor base in Geneva. Scope is WordPress development: block or classic theme, custom plugins, Gutenberg, CPT, ACF or native blocks, REST integrations and code review on Git. WooCommerce shop builds and maintenance retainers are separate topics, with links at the end.
#WordPress development in Geneva
Geneva is not only the lake and watchmaking. It is the densest node of international organisations on the planet: Palais des Nations, WTO and WHO headquarters, ICRC, dozens of UN specialised agencies and hundreds of NGOs with offices in Canton de Genève. Alongside that sits Geneva Financial Centre: private banking, wealth management, family offices and regulatory advisory within a few tram stops of Rive. Geneva Digital Hub at Rue du Stand 5 adds startups and scale-ups that ship digital products but still need a site that survives a compliance audit.
For WordPress those facts mean three hard requirements a ThemeForest template will not meet. First, multilingual setup: FR-CH and EN as a minimum, often DE-CH or extra locales for donors and partners. Second, register: a French interface uses formal vous, not tu; a German variant, if present, uses Sie, not du. Third, compliance: revFADP / nDSG has applied since 1 September 2023, and the financial sector listens to FINMA cyber-security guidance on third-party risk and operational resilience. A marketing site is usually not a FINMA-supervised system, but a donor portal or application form already is.
The typical brief that reaches senior developers does not read “make a pretty site”. It reads: inherited theme with a page builder, editorial teams in Poland and Geneva, three languages on the front, Gutenberg used like a classic editor, and a new publication for a UN conference built by copying last year’s page and manually swapping the PDF. That is a content-model and Git-process problem, not a template problem.
#Block theme, classic theme and custom plugin
A new build in Geneva starts with a decision that costs months if wrong: whether presentation lives in a block theme with theme.json, in classic PHP templates, and what goes into a plugin. That decision is written down before the first commit.
#theme.json, patterns and the theme boundary
A block theme holds tokens: palette, type scale, spacing, content widths. For Geneva B2B and NGO work that means a restrained palette, a readable face without ornament, and buttons that do not break on French compounds like Déclaration d’accessibilité or Politique de confidentialité. Block patterns describe repeatable layouts: hero with legal disclaimer, expert grid, attributed quote block, event card with date and locale, footer with mentions légales. An editor assembles a conference landing or report page from patterns instead of asking a developer for a new template on every Council session.
Full site editing (FSE) makes sense when the editorial team genuinely needs control over header and footer. In practice many foundations and financial institutions do not want that: the header is brand and compliance, not a playground. Then the block theme stays, but header and footer templates are locked and editors work inside patterns and custom blocks. That is a compromise, not a half measure.
Every custom block gets block.json, a category, an icon and attributes with schema. Where content must reach search and RSS, rendering is server-side. React in the editor serves InspectorControls and preview, not a front-end SPA pretending to be WordPress. The developer.wordpress.org handbook is the API contract, not a training slide deck.
#When a classic PHP theme stays
Inherited installs in Geneva are often five or seven years old: child theme on a commercial skeleton, ACF wired into page.php, shortcodes in content, jQuery from before blocks, a separate page copy for every annual report edition. Rewriting that to FSE “because 2026 expects it” costs more than fixing template hierarchy, pulling logic into a plugin and adding Gutenberg only where editors actually assemble new landings.
A classic theme stays when:
- conditional logic lives in templates (different menu for donor, journalist or institutional partner) and moving it to
theme.json simplifies nothing;
- the editorial team publishes hundreds of pages in the classic editor and FSE training would be a bigger risk than debt;
- the child theme is thin and the problem is plugins and autoload, not the template engine.
Even then new pieces ship as blocks, not as more shortcodes. A shortcode from 2019 stays until migration. New code does not add more.
#Function in the plugin, presentation in the theme
The boundary is simple and recorded in the runbook. The theme knows how to display. The plugin knows. Publication CPT, donor CRM queue, REST endpoint for intranet, a “PL editor” role without publish_pages on the French production site: plugin. Colours, grid, hero pattern: theme. If changing the theme removes the report archive or expert list, the architecture was wrong.
A custom plugin gets its own prefix, PSR-4 autoload, a main file with Plugin Name header and semver, and tests where logic matters (event dates, donor field mapping, application-form validation). Business logic does not land in the theme’s functions.php, because functions.php dies with the theme and a Geneva foundation changes branding agencies more often than content models.
Layer comparison at kickoff:
| Layer | What lives there | Example in Geneva |
|---|
| Theme | presentation, tokens, patterns | conference landing, footer with mentions légales |
| Plugin | CPT, roles, REST, integrations | report, event, expert, audit logs |
| Gutenberg | editing without HTML | publication pattern, person block, programme card |
| Staging and Git | process, not a feature | branch, review, promote to production |
#Gutenberg, CPT and multilingual setup for UN, NGO and finance
Gutenberg without a content model ends with every subpage as a unique block collage and nobody able to produce a list. In Geneva lists are concrete: publications, reports, events, experts, positions, partners, donor programmes, press releases. Those are objects, not “another page in the tree”.
#Custom post types instead of copied landing pages
CPTs register with their own capabilities, not mapped to post. An editor in Poland should edit an expert card or event entry, not delete plugins. CPT archives get a template or query pattern. Single objects get a template that cannot blow the layout outside the agreed structure. Taxonomies stay separate: event type (conference, briefing, webinar) does not mix with blog tags. Policy topic (climate, health, trade) does not mix with a financial adviser’s product taxonomy.
ACF has a place, but not as a block substitute. ACF fields on CPTs work for data that is data, not layout: publication date, report number, original language, PDF file, embargo flag, partner identifier. Expert or article layout is assembled in Gutenberg. Mixing ACF Flexible Content with full block editor on the same object creates two sources of truth and an editor who does not know where to click.
Where ACF is unnecessary, block attributes in block.json are enough. An “expert with quote” block does not need a field group on every page. It needs attributes and optionally InnerBlocks for the bio. Fewer plugins in the admin means less attack surface and fewer conflicts with French consent and cache plugins.
A conference landing copied from last year is debt that surfaces in October when the Council meets in Geneva. A CPT object with year, room and locale fields survives the next edition without copying the tree. The template reads the object. The editor changes the date, not HTML.
#WPML, Polylang and hreflang that does not break
The multilingual stack is chosen for language count and editorial process, not developer preference:
| Language count | Stack | Workflow |
|---|
| 2 (FR-CH plus EN) | Polylang | manual translation, editor per language |
| 3-4 (FR-CH, EN, DE-CH, optional ES) | WPML plus String Translation | editor per language, shared memory |
| 4 plus machine drafts | WPML plus translation connector | machine draft, human review before publish |
FR-CH is not FR-FR. Swiss French uses different administrative terms, spelling on some words and a different official register. A pipeline that outputs Parisian French sounds wrong near Place des Nations even with correct grammar. DE-CH, if included, is not DE-DE: no eszett (ß), Helvetisms (Tram, Velo, parkieren) and reference to Schweizer Duden, not Mannheim.
Minimum hreflang configuration for CH:
fr-CH, en (or en-CH), optional de-CH
x-default pointing at the switcher or FR-CH
- return links on every language version
xhtml:link annotations in the sitemap as a redundant layer
Polylang and WPML emit hreflang correctly when configured properly. Breakage almost always sits in custom code that strips annotations from <head> on cached pages, or CDN rules varying on cookies instead of URL.
The most common friction in Poland-Geneva collaboration is not PHP. It is register. A French UI for a foundation site uses formal vous. A Polish editor translating from an informal headline at home publishes copy that sounds like a gym newsletter near Jet d’eau. That is a language brief and a theme string list, not a plugin fix.
Rules written into theme documentation:
- Interface strings (buttons, form errors,
aria-label, placeholders) are French with vous when the front is FR-CH. The English variant, if present, is also formal. A Polish variant, if created, does not copy vous one-to-one but uses natural institutional Polish.
- A German variant, if present, uses Sie, not du. Documentation example: “Bitte geben Sie Ihre E-Mail-Adresse ein”, not “Gib deine E-Mail ein”.
- Editors in Poland get an admin locale they can work in. That does not have to match the front language.
- Mentions légales, politique de confidentialité and déclaration d’accessibilité are templates with fields, not blocks the editor can delete from the tree. The EN version gets its own fields, not a machine translation of French legal text.
Polylang and WPML solve hreflang and language copies. They do not solve process: who approves French text before production. The brief records whether approval sits with the client in Geneva, the foundation editorial desk or the Polish content lead. Staging shows locales side by side, because the regression “FR broke because someone edited EN” only appears on comparison.
For NGOs and think tanks a glossary follows. Programme names, donor initiative titles and job titles must not be overwritten by a translator plugin. The dictionary lives in theme documentation and .po files. DeepL overnight is not an editorial process.
#Accessibility: WCAG 2.2, EN 301 549 and Geneva public context
Accessibility in Geneva is not one statute. International organisations and public bodies in Canton de Genève refer to EN 301 549 and WCAG 2.1 AA as the web layer (as of August 2026 WCAG 2.2 is the reference point for new audits). Private sector, especially finance with an application form or donor portal, treats accessibility as reputational and operational risk even without the same regime as a government office.
The team does not sell a certification that was not earned. An axe scan in CI is a gate, not proof of compliance. If no external audit happened, the offer does not carry a badge.
What the team does in code:
- Semantics: one
h1, heading order, button as button, link as a, not a clickable div.
- Keyboard and focus: skip repeated navigation, visible focus, no traps in mega menu or briefing-registration modal.
- Contrast and motion: tokens in
theme.json, respect for prefers-reduced-motion, no information carried by colour alone. Autoplay in a report hero does not bypass that rule.
- Forms: labels tied to fields, errors in text, not only border colour. EN consent must not vanish because a template calls an old filter.
- Media: alt text as a required field in editorial process. A report without chart description or caption does not pass acceptance when the brief mentions accessibility.
- PDF: if an annual report, terms or rules ship as attachment, the “documents outside the web” clause goes into the brief. WordPress will not make an accessible PDF from a JPG.
A conference at Place des Nations is a local barometer. An organisation landing with broken focus or unlabelled forms in Council week is a product error, not a “UX ticket after the conference”. Development takeaway: axe in CI plus manual keyboard path on the publication pattern before the tag reaches production.
#revFADP, FDPIC, FINMA and hosting in Switzerland
The revised Federal Act on Data Protection (revFADP / nDSG) took effect on 1 September 2023. It is GDPR-aligned but not identical: stricter on consent for profiling, lighter on documentation thresholds for SMEs, explicit on data export outside the EEA. For WordPress that means: documented privacy policy in every language version, cookie consent with default reject, processing register and clarity on subprocessors (analytics, mail, CDN) outside Switzerland.
Supervision sits with the Federal Data Protection and Information Commissioner (FDPIC / EDÖB) in Bern. Art. 19 requires identity of the controller, purpose, recipients and, on cross-border transfer, country and safeguards. A personal data breach is reported by the controller when there is likely high risk to personality or fundamental rights; the processor reports to the controller, not the portal. The FDPIC DataBreach portal accepts controller reports and assigns a Report-ID. FDPIC guidance on Art. 24 was updated in April 2025.
GDPR still applies to processing aimed at people in the EU. A Geneva company site with EU traffic therefore has two layers, not one. A cookie plugin copied from a German shop (opt-in everywhere) is not automatically “nDSG-compliant”, and no banner is not automatically legal when tracking, profiling or transfer to an inadequate country is in play. Development does not sell legal advice. It keeps on-site tools aligned with what stands in the Datenschutzerklärung / politique de confidentialité, and ensures consent logs still write after a GTM or consent-plugin update.
For Geneva financial-sector clients FINMA cyber-security guidance adds incident reporting, third-party risk and operational resilience. An advisory information site usually does not meet that directly, but a client portal or application form already does. That is flagged on day one, not at launch.
Hosting in CH makes sense for Geneva clients who want data sovereignty. Infomaniak (headquartered in Geneva) is a common choice with green energy and Swiss data centres. Hostpoint, Cyon and Metanet cover other profiles: SME, regulated deployments with ISO 27001 documentation. Edge through Cloudflare or Fastly with origin in CH is the typical compromise between performance and residency.
Secrets do not live in Git. Keys, database passwords and CRM or donor-system tokens go through environment variables or outside the repo. wp-config.php with a password in Git history is an incident, not a later tidy-up. Admin accounts have 2FA. PL editors do not get install_plugins on production. XML-RPC stays disabled unless a justified client needs it.
#Git, staging environment and release freeze
This is the layer that separates senior WordPress work from uploading a ZIP over FTP. A client with IT in Geneva asks about it on the second meeting, especially when foundation compliance or a bank legal team wants a trace of who deployed a change.
The repository holds the theme and custom plugins. WordPress.org plugins and core do not live as copied folders in Git unless there is a hard reason (fork, patch, air-gap). One feature branch per change: new block, new CPT, a11y fix. A pull request has description, editor screenshots or recording and a checklist: i18n, accessibility, no secrets, whether the block breaks a classic template if one still lives.
Code review is done by a senior who did not write the branch. Review reads WordPress Coding Standards (PHPCS, WordPress-Core sniffs) but also intent: should the CPT be a plugin, does ACF duplicate block attributes, does a hook hang on init without need. PR comments are in English or Polish depending on the client-side reviewer. Geneva IT usually wants French in editorial documentation and English in the diff.
Staging is a production copy with anonymised data. WP-CLI search-replace on URL, separate keys, crons disabled that mail real donors or journalists. Editorial clicks staging with real Gutenberg patterns, not a developer localhost. Multilingual regression (FR-CH/EN/DE-CH), keyboard regression and hreflang regression happen here. Promotion to production is a documented step: tag or merge to main, asset build, cache warmup, rollback path (previous tag).
Release freeze around major UN conferences or annual report publication is a developer decision, not only operations. During Council session, climate summit or report launch week, production does not get a new theme.json, new CPT, URL map change or header rebuild. A security patch that cannot wait goes through staging as hotfix, with rollback written before anyone presses deploy.
Performance budget is part of acceptance, not a separate project. Lighthouse and Core Web Vitals on templates that actually exist: publication CPT archive, single report, hero-pattern page, EN locale. Images in AVIF/WebP through the build process, theme CSS without importing the entire block universe, editor JS not on the front. Redis and object cache make sense when transients and CPT queries show it, not because “that is what you do by Lac Léman”.
#WooCommerce is a separate scope
This page does not build checkout, gateways or product catalogues. If the brief moves to shop, TWINT, Swiss QR-Rechnung or MWST rates, scope changes owner and is described on the WooCommerce developer in Geneva page. Pillar without city: WooCommerce developer. Mixing shop with a foundation theme or advisory site in one repository without plugin boundaries is the fastest route to a Woo update breaking a conference landing, or the reverse.
A corporate site with one “boutique” button linking to external Woo can stay in the theme as a link. Cart logic does not. A donor portal that looks like a shop but is a donation form is not Woo. That is CPT, form and integration, covered in this brief.
#After delivery: handover or maintenance
A development engagement ends with documentation, a handover session and Git access for the client team. The runbook describes: how to add a pattern, register a new CPT, cut a branch, rebuild staging, who to call when the editor will not save, which conference dates block release. If after launch Core updates, monitoring, WAF and standing operator duty are needed, that is WordPress maintenance in Geneva, not a hidden annex to the theme.
Development pricing is individual and issued in writing after scope is agreed. This page has no rate card or hour packages. Scope change (a second language suddenly, donor-system or intranet integration) returns to the written record before it enters the sprint.
#How to start a project in Geneva
A short written brief is enough to begin: which theme and plugins exist today, who edits (PL/FR/EN), whether the front should use formal vous, whether CPT for publications, reports or events is in scope, whether Geneva-side IT requires Git and staging from day zero, which conference dates sit on the calendar. The team reviews the install, lists risks (Gutenberg used like a notepad, secrets in the repo, missing déclaration d’accessibilité, ACF duplicated with blocks, landings copied every year, hero autoplay without prefers-reduced-motion) and proposes a plan with acceptance criteria.
Contact: WPPoland contact form. The service pillar without city in the slug remains at WordPress developer.