An institutional or service-provider site in Bern sits next to the Bundeshaus at Bundesplatz, canton Bern administration and Swisscom headquarters at Alte Tiefenaustrasse. That is not a reason for WordPress to pretend to be admin.ch. It is a reason for the theme, plugins and content model to be written the way a Swiss legal team, a German-speaking editor in Bern and a French-speaking reviewer from canton Vaud expect before anything reaches production.
WPPoland builds this WordPress from a senior Polish team for businesses, public-sector suppliers and organisations with a base, branch or client base in Bern. Scope is WordPress development: block or classic theme, custom plugins, Gutenberg, CPTs, ACF or native blocks, REST integrations and code review on Git. WooCommerce stores and maintenance retainers are separate topics, with links at the end.
#WordPress development in Bundesstadt and canton Bern
Bern is not Basel with pharma and the stock exchange, nor Geneva with the UN and WTO. It is Bundesstadt: seat of the Federal Council, parliament and key federal offices around Bundesplatz. Canton Bern adds its own administration, universities and a dense network of IT suppliers serving public procurement. Swisscom, headquartered in Bern-Ost, is one of the city’s largest technology employers, but a WordPress brief here rarely reads “build us a site like a telecom operator”. More often it reads: inherited theme with three multilingual plugins, DE/FR publications that drift apart after an update, editorial team in Poland, and a reviewer in Bern asking about nFADP, hosting in CH and an accessibility statement before a landing goes live.
For a WordPress site those facts mean three harder requirements than on a typical B2B market. First, formal language: German front in formal Sie, French version in parallel, not machine translation from a Polish brief. Second, decision trail: who approves DE, who approves FR, what goes to staging, what goes to production when a parliamentary session or public-procurement deadline freezes changes. Third, residency and retention: hosting in Switzerland, backups, logs and form integrations are discussed before the first commit, not as a contract appendix after an incident.
Bern Digital Hub at Wylerstrasse and nearby coworking spaces (Impact Hub Bern, Biel/Bienne in the agglomeration) add reviewers who read pull requests and ask whether the consent plugin sends IP addresses to the US without a legal basis. The University of Bern (Universität Bern) and Bern University of Applied Sciences (BFH) produce people who can tell theme from plugin and know that Polylang does not replace an editorial process. Commuters from Biel/Bienne, Thun and Solothurn work in one office in German and French, so a DE/FR front with Polish editorial back office is more common here than a purely Polish front with a German panel.
The typical brief that reaches seniors does not read “make a nice site”. It reads: federal template from five years ago, WPML or Polylang serving German text on the French version after a patch, Gutenberg used like a notepad, and a new official publication created by copying last year’s page and manually swapping the document number. That is a content-model and Git-process problem, not a marketplace-theme problem.
WPPoland is not a contractor for admin.ch or canton Bern. Proximity to the Bundeshaus sets the bar for documentation, roles and bilingual delivery. It does not set a list of government references.
#Block theme, classic theme and custom plugin
A new build in Bern starts with a decision that costs months if deferred: 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, because “we will add FR over the weekend before the deadline” usually ends in hreflang regression and a complaint from legal.
#theme.json, patterns and theme responsibility boundary
A block theme holds tokens: palette, type scale, spacing, content widths. For Bern B2B and public-sector suppliers that means a restrained palette, readable type without ornament and buttons that do not break on long German federal compounds or French administrative phrasing. Block patterns describe repeatable layouts: hero with legal disclaimer, team grid, attributed quote block, footer with Impressum and privacy-policy link aligned with nFADP. Editors assemble pages from patterns instead of asking a developer for a new template on every press release or public consultation.
Full site editing (FSE) makes sense when the editorial team genuinely needs control over header and footer. In practice many institutions and firms in Bern do not want that: the header is brand and compliance, not a playground. Then the block theme stays, but template parts (header, footer) are locked and editors work within patterns and custom blocks. That is a compromise, not a half measure.
Every custom block gets block.json, category, icon and schema attributes. Where content must reach search engines and RSS, render is server-side. React in the editor serves InspectorControls and preview, not a SPA front pretending to be WordPress.
#When a classic PHP theme stays
Inherited installs in Bern are often five to seven years old: child theme on a commercial skeleton, ACF wired into page.php, shortcodes in content, jQuery from the pre-block era, multilingual plugin glued with hooks. Rewriting that to FSE “because it is 2026” costs more than fixing template hierarchy, moving logic into a plugin and adding Gutenberg only where editors actually assemble new landings.
A classic theme stays when:
- conditional logic sits in templates (different menus for media, suppliers, citizens) 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 real problem is plugins, autoload and DE/FR sync, not the template engine.
Even then new pieces ship as blocks, not as more shortcodes. A shortcode in 2019 content stays for migration; new code does not add shortcodes.
#Logic in the plugin, presentation in the theme
The boundary is simple and recorded in the runbook. The theme shows. The plugin knows. CPT for official publications, CRM queue, REST endpoint for intranet, user role “PL editor” without publish_pages on German production: plugin. Colours, grid, hero pattern: theme. If changing the theme removes a federal events calendar, the architecture was wrong.
A custom plugin has its own prefix, PSR-4 autoload, main file with Plugin Name header and semver, and tests where logic matters (event dates, CRM field mapping, form validation). Business logic does not go into the theme’s functions.php, because functions.php dies with the theme and a Bern client changes branding agencies more often than the content model.
Layer comparison used at kickoff:
| Layer | What lives there | Example in Bern |
|---|
| Theme | presentation, tokens, patterns | landing for public consultation, Impressum footer |
| Plugin | CPTs, roles, REST, integrations | publication catalogue, audit logs, DE/FR sync |
| Gutenberg | editing without HTML | disclaimer pattern, person block with department |
| Staging and Git | process, not feature | branch, review, production promotion |
#Gutenberg, CPTs and content model for administration and public sector
Gutenberg without a content model ends with every subpage as a unique block collage and nobody able to produce a list. In Bern lists are concrete: publications, announcements, people, positions, consultation events, office locations (Bundesplatz is not Wylerstrasse, Biel is not Thun). Those are objects, not “more pages in the tree”.
#Custom post types for real objects
CPTs register with their own capabilities, not mapped to post. A editor in Poland should edit a publication, not delete plugins. CPT archives get a template or query pattern; singles get a template that stops editors breaking layout outside the agreed structure. Taxonomies are separate: document type (report, notice, form) does not mix with blog tags.
ACF has a place but not as a block substitute. ACF fields on CPTs suit data that are fields, not layout: publication number, effective date, language version, official PDF attachment. Person 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. A “person with quote” block does not need a field group on every page. It needs attributes and optionally InnerBlocks for biography. Fewer plugins in the admin means less attack surface and fewer conflicts with Swiss consent and cache plugins.
#Server-side blocks instead of shortcodes
A shortcode in content is debt visible only at migration or PDF export. New code in Bern ships as a block with server render: semantic markup, attributes in block comments, filterable output. A publication-list block reads the CPT, caches the query with a transient with explicit TTL and invalidation on save_post, not on every request.
For DE/FR editorial every string in a block goes through WordPress i18n functions. German or French strings in PHP are exceptions, not the rule. Translations live in .po files or the multilingual plugin mechanism, not in a hardcoded array in the theme. Polylang or WPML is added only when there are genuinely two languages on the front. A German panel with content edited from Poland can work with roles and user locale without a full multilingual stack, but a DE/FR front in Bern usually needs the full pair.
Code review on a block checks three things before merge: does the block work with front-end JS disabled, do attributes have types and defaults, does it avoid loading the full editor build on the front. Gutenberg that adds a megabyte of React to an executive profile page does not pass review.
A landing for a parliamentary session, public-consultation deadline or Bern Digital Hub event is not created by copying last year’s page. It is a CPT object with date, language, reference number and pattern. After the deadline the object stays in the archive, not as an orphan subpage in the tree.
#DE/FR bilingual editorial: Polish team, Swiss front
The most common friction in Poland-Bern collaboration is not PHP. It is tone and the language pair. Institutional German uses formal Sie. The French version cannot be a literal translation from a Polish brief or a machine export from DE without native review. That is not solved by a translation plugin alone. It is a language brief, a string list in the theme and an approval process before production.
Practical rules written into theme documentation:
- Interface strings (buttons, form errors, aria-label, placeholder) are in formal Sie on DE and formal vous on FR when the front is bilingual. A Polish variant for an internal panel uses natural Polish B2B register, not a one-to-one copy of Sie or vous.
- Editors in Poland get an admin locale they can work in. That does not have to match the front locale. Mixing user locale and site locale without testing ends with wrong date formats and menus jumping from “Beiträge” to “Wpisy” mid-screen.
- German and French typography: ß, umlauts, French apostrophes in contractions, long compounds. Buttons and menu items reserve width. CSS line breaks must not truncate meaning in PDFs generated from content.
- Impressum, privacy policy (Datenschutzerklärung / politique de confidentialité) and accessibility statement are templates with fields, not blocks an editor can accidentally delete from the tree. In Bern those pages are compliance, not marketing footer. Commercial-register entry (Zefix) and canton Bern data are verified by the client; the theme supplies fields and templates, not “automatic legal compliance”.
Polylang and WPML solve hreflang and language copies. They do not solve process: who approves German text, who approves French, before production. The brief records whether approval sits with the client in Bern, with the Polish content lead, or both in parallel. Staging shows both language versions because “DE broke because someone edited FR” appears only on comparison, not in Lighthouse.
Federal and cantonal communication culture in Bern is more formal than startup copy from a coworking space. Sie in DE, vous in FR in UI, transactional email and form errors. Du or tutoiement may be acceptable on a startup careers page if the brief records it. Default mixing registers in one theme is a bug, not flexibility.
#Accessibility in Swiss and public-sector context
Accessibility in Bern is not one checkbox. Public institutions and many suppliers working for the public sector must account for digital accessibility requirements referencing EN 301 549 and WCAG 2.1 AA (with migration to WCAG 2.2 where the auditor requires it). That is not German BITV or BFSG. The Swiss federal context has its own expectations for accessibility statements, feedback channels and testability before publishing citizen-facing documents.
Private-sector firms in Bern (Swisscom, IT suppliers, law firms handling procurement) often copy the same standards because reviewers on the client side are used to WCAG lists from federal projects. The team does not sell an “admin.ch accessibility certificate”. At kickoff we record which regime applies to the site, then test what can be tested in theme and blocks.
What the team does in code:
- Semantics: one h1, heading order, button as button, link as a, not div with click handler.
- Keyboard and focus: skip repeated navigation, visible focus, no traps in mega menus.
- Contrast and motion: tokens in theme.json, respect for prefers-reduced-motion, no information carried by colour alone.
- Forms: labels tied to fields, errors in text in both languages, not only coloured borders.
- Media: alt text as a required field in editorial process, not “we will fill it later”.
- PDF: if an official publication ships as attachment, the out-of-scope clause for non-web documents goes into the brief. WordPress does not make an accessible PDF from a JPG.
Automated scan (axe, Lighthouse) is a CI gate, not proof of compliance. For public-sector clients or contracts requiring WCAG, we add manual keyboard path and WCAG checklist comparison in both languages. The team does not issue certificates that were not in scope.
If the brief moves to WooCommerce, scope shifts to WooCommerce developer in Bern.
#Security, nFADP, FDPIC and hosting in Switzerland
Proximity to the Bundeshaus and Swisscom does not turn a marketing WordPress site into a federal classification system. The team does not claim “ISO 27001 compliant” or “NCSC certified” unless the client ran that audit. ISO 27001 covers the client’s information-security management system. WordPress should deliver inventory, access trail and update discipline the client can paste into procurement or processor-agreement documentation, not an agency “compliance stamp”.
Posture maintainable in code and process without pretending to be an audit:
- No secrets in Git. Keys, database passwords and CRM tokens go through environment variables or outside the repo. wp-config.php with a password in Git history is an incident, not a minor fix later.
- Admin accounts use 2FA. PL editors do not get install_plugins on production. Roles are cut to what Gutenberg requires.
- XML-RPC stays disabled unless a justified client needs it. File editor in the admin too.
- Headers: HTTPS, HSTS where certificate and CDN allow, CSP matched to real scripts (consent, tag manager, fonts), not copied from a blog post.
- Dependencies: Composer or pinned plugin versions, CVE scan in CI, updates on staging before production. Unpatched Core is worse than skipping a new “security” plugin.
- Backups and restore: backup without tested restore is decoration. Restore test on staging is in the runbook. Backup residency in CH is a contract topic, not a default assumption of global cloud.
- Logs: who logged into wp-admin, which plugin change shipped when. Retention agreed with nFADP and client policy, not “keep everything forever”. After an incident the client may need to notify the Federal Data Protection and Information Commissioner (FDPIC, EDÖB in German); logs must fit a notification form. The agency does not file on behalf of the data controller.
GDPR and nFADP are separate layers in cross-border briefs: form-field minimisation, processor agreement, consent for scripts, hosting location. Hosting “in Switzerland” is a jurisdiction argument, not a magic shield. A form collecting personal data without legal basis and without policy coverage is not fixed by a server in Bern-Ost alone.
Penetration tests are mentioned only when the client has or orders them from a lab. WPPoland does not add certificates it does not hold. Hardening WordPress is a set of pull-request decisions, not a slide about zero incidents.
#Git, staging and code review
This layer separates senior WordPress work from “upload a ZIP over FTP”. In Bern a client with an IT department or public-procurement experience asks about it on the second meeting, especially if the reviewer comes from BFH, Bern Digital Hub or internal IT at Swisscom.
The repository holds the theme and custom plugins. Plugins from WordPress.org 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, DE/FR sync. Pull request has description, screenshots or editor recording, and checklist: i18n, accessibility, no secrets, block does not break classic template if one still lives, both language versions pass regression.
Code review is done by a senior who did not write the branch. Review runs WordPress Coding Standards (PHPCS, WordPress-Core sniffs) but also reads intent: should the CPT be a plugin, does ACF duplicate block attributes, does the hook hang on init without need. PR comments are in English or Polish depending on the client reviewer; Swiss IT in Bern usually prefers English in the diff and DE/FR in editorial documentation.
Staging is a production copy with anonymised data. WP-CLI search-replace on URL, separate keys, crons that send mail to real addresses disabled. Editorial clicks through staging with real Gutenberg patterns in both languages, not on the developer’s localhost. Multilingual and keyboard regression happen here. Production promotion is a documented step: tag or merge to main, asset build, cache warmup, rollback path (previous tag). The team does not “quick upload” one PHP file over SFTP, because nobody can reconstruct what was on production on Friday before a federal publication deadline.
WP-CLI is operational: flush transients, wp scaffold, CPT import, autoload check. It does not replace tests. Where plugin logic matters (dates, mapping, validation), PHPUnit follows. Blocks with non-trivial UI get an editor test on staging, because jsdom will not catch InspectorControls covering Speichern or Enregistrer in the right locale.
Performance budget is part of acceptance, not a separate project. Lighthouse and Core Web Vitals on templates that actually exist: CPT archive, single, hero pattern page in DE and FR. Images in AVIF/WebP through the build pipeline, theme CSS without importing the entire block universe, editor JS not on the front. Redis object cache makes sense when transients and CPT queries show it, not because “that is what you do in Bundesstadt”.
#Bern Digital Hub and the local tech scene
Bern Digital Hub at Wylerstrasse 60A is a reference point for Bern’s digital ecosystem: meetups, networking, projects linking administration, startups and IT suppliers. It is not a WPPoland sales argument. It is a barometer: editorial and IT teams in Bern ask about the repository, staging and whether the theme breaks the editor after a Core update because they heard those questions at local meetups and in BFH corridors.
Impact Hub Bern and nearby initiatives add reviewers who read copy and code. The University of Bern and BFH supply people who can tell theme from plugin and know Polylang does not replace FR approval. Swisscom as an employer sets the bar for suppliers in the chain: questions about data location and log retention appear earlier than on a typical Polish B2B market.
The wider Swiss scene has WordCamp Switzerland and meetups in Zurich or Basel, but a Bern brief does not need to pretend to be Basel banking or Geneva diplomacy. For this city DE/FR bilingual delivery, public sector and canton Bern matter more than a slide about “global organisations”. Themes and plugins from this team must survive questions: where alt text comes from, who approves the French version, whether a form sends data outside CH without legal basis.
#WooCommerce is a separate scope
This page does not build checkout, TWINT gateways or product catalogues. If the brief moves to shop, VAT, PostFinance integration or QR-Rechnung, scope changes owner and is described by the WooCommerce developer in Bern. Pillar without city: WooCommerce developer. Mixing shop and institutional theme in one repository without plugin boundaries is the fastest route to a Woo update breaking a public-consultation landing, or the reverse.
A corporate site with one “shop” button to external Woo can stay in the theme as a link. Cart logic itself does not.
#After launch: handover or maintenance
A development engagement ends with documentation, handover session and Git access for the client team. The runbook describes: how to add a pattern, how to register a new CPT, how to ship a branch, how to rebuild staging, whom to call when the editor will not save, how to publish a DE/FR pair without hreflang regression. If ongoing Core updates, monitoring and on-call are needed after launch, that is WordPress maintenance in Bern, not a hidden annex to the theme. Pillar without city: WordPress maintenance.
Development pricing is individual and delivered in writing after scope is agreed. There is no rate card or “hour packages” on this page. Scope changes (sudden FSE, third language, federal intranet integration) return to the written record before they enter a sprint.
#How to start a project in Bern
A short brief is enough to begin: which theme and plugins exist today, who edits (PL/DE/FR), whether the front should use formal Sie and vous, whether CPTs for publications and events are in scope, whether Bern IT requires Git and staging from day zero, where hosting sits and whether backups must stay in CH. The team reviews the install, lists risks (Gutenberg used as a notepad, secrets in repo, missing accessibility statement, ACF duplicated with blocks, broken DE/FR pair) and proposes a plan with acceptance criteria.
Contact: WPPoland contact form. The service pillar without city in the slug remains at WordPress developer.