A corporate site in Basel sits next to Roche on Grenzacherstrasse, the Novartis Campus on Fabrikstrasse, DayOne accelerators in the BaselArea cluster, the Art Basel calendar at Messe Basel, and a trilingual region where impressum must match Zefix, not a German Amtsgericht entry. That is not a reason for WordPress to pretend it is a GxP system or a Novartis-class clinical portal. It is a reason for the block theme, plugins and content model to be written the way Basel compliance expects and the way a Polish editorial team works when the front ships in DE, FR and EN.
WPPoland builds this WordPress from a senior Polish team for businesses in Basel and across the life sciences cluster. The scope is WordPress development: block or classic theme, custom plugins, Gutenberg, CPT, ACF or native blocks, REST integrations and code review on Git. WooCommerce stores, TWINT checkout and a maintenance retainer are separate topics, with links at the end.
#WordPress development for businesses in Basel and the life sciences cluster
Basel combines three forces that rarely meet at this scale in one city. First, pharma and biotech: Roche and Novartis set the bar for documentation, partner onboarding and scientific recruitment. Around them grows an ecosystem of CROs, suppliers, spin-offs and accelerators promoted by BaselArea (baselarea.swiss). Second, trilingual operations: Basel-Stadt uses German as the official language, the border region with France (Weg bis nach Saint-Louis) translates regulatory and B2B copy into French, and English is the working language in life sciences. Third, Switzerland as a jurisdiction: the revised Federal Act on Data Protection (nDSG), data residency in CH, hosting with Cyon in Basel, Infomaniak or Metanet, not the cheapest VPS across the ocean.
For a WordPress site these facts do not mean the theme should count clinical samples or sync with a LIMS. They mean three harder requirements. Content may be regulated (Datenschutzerklärung, impressum with UID and Firmenwortlaut from Zefix, DE/FR/EN versions). The guest-facing interface must stay consistent across languages without broken hreflang. Hosting, log retention and the question of origin in Switzerland are kickoff topics, because someone nearby will ask about nDSG, about the Federal Data Protection and Information Commissioner (FDPIC, EDÖB in German) or about cross-border data transfer.
A typical brief that reaches seniors in Basel does not read “make a nice site”. It reads: inherited theme with 35 plugins, editorial team in Poland, compliance in Basel-Stadt, Gutenberg used like a classic notepad, and a new life sciences conference landing built by copying last year’s page and hand-editing dates. That is a content-model and Git process problem, not a marketplace template problem.
WPPoland is not a supplier to Roche, Novartis or BaselArea. Proximity to the pharma cluster sets the documentation, role and Git bar. It does not set a reference list.
#Block theme, classic theme and custom plugin
A new build in Basel starts with a decision that costs months if it is deferred: whether presentation lives in a block theme with theme.json, in classic PHP templates, and what belongs in a plugin. That decision is written down before the first commit.
#theme.json, patterns and the theme responsibility boundary
A block theme holds tokens: palette, type scale, spacing, content widths. For Basel B2B in life sciences that means a restrained corporate palette, a readable face without ornament, and buttons that do not break on German compounds like Forschungspartnerschaft or French connectors in section titles. Block patterns describe repeatable layouts: hero with a legal disclaimer, people grid, attributed quote block, footer with impressum aligned to Handelsregisteramt des Kantons Basel-Stadt. Editors assemble pages from patterns instead of asking a developer for a new template on every DayOne cluster event or every edition of a scientific publication.
Full site editing (FSE) makes sense when the editorial team genuinely needs control over header and footer. In practice many businesses in Basel 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 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 a schema. Where content must reach search and RSS, rendering is server-side. React in the editor serves InspectorControls and preview, not a SPA pretending to be WordPress. The Block Editor Handbook is the reference when designing blocks, not a marketing blog.
#When a classic PHP theme stays
Inherited installations in Basel are often five to seven years old: child theme on a commercial skeleton, ACF wired into page.php, shortcodes in body copy, jQuery from before blocks. Rewriting that to FSE “because it is 2026” costs more than fixing template hierarchy, pulling logic into a plugin and adding Gutenberg only where editors actually build new landings.
A classic theme stays when:
- conditional logic lives in templates (different menu for a CRO partner, an investor, a candidate) 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 and autoload, not the template engine.
Even then new pieces ship as blocks, not as more shortcodes. A shortcode in 2019 content waits for migration; new code does not add another.
#Function in a plugin, look in the theme
The boundary is simple and recorded in the runbook. The theme knows how to show. The plugin knows. Scientific publications CPT, CRM queue, REST endpoint for an intranet, a “PL editor” role without publish_pages on German production: that is a plugin. Colours, grid, hero pattern: that is the theme. If the events calendar disappears after a theme change, the architecture was wrong.
A custom plugin gets its own prefix, PSR-4 autoload, a main file with Plugin Name and semver version, and tests where logic matters (event dates, CRM field mapping, form validation). Business logic does not land in the theme’s functions.php, because functions.php dies with the theme and a Basel corporate site changes branding agencies more often than its content model.
Layer comparison used at kickoff:
| Layer | What lives there | Example in Basel |
|---|
| Theme | presentation, tokens, patterns | life sciences conference landing, impressum footer |
| Plugin | CPT, roles, REST, integrations | publication catalog, CRM queue, audit logs |
| Gutenberg | editing without raw HTML | disclaimer pattern, leadership person block |
| Staging and Git | process, not a feature | branch, review, production promotion |
#Gutenberg, CPT and ACF in the content model
Gutenberg without a content model ends with every subpage as a unique block collage and nobody able to produce a list. In Basel the lists are concrete: scientific publications, events, people, roles, office locations (Kleinbasel is not Grenzach, Novartis Campus is not Messe Basel). These are objects, not “another page in the tree”.
#Custom post types for real objects
CPTs register with their own capabilities, not mapped to post. A Polish editor should edit a publication, not delete plugins. CPT archives get a template or query pattern; singles get a layout that does not let editors break structure. Taxonomies are separate: event type (congress, webinar, conference) does not mix with blog tags.
ACF has a place, but not as a block substitute. ACF fields on a CPT work for data that is fields, not layout: start date, BaselArea cluster location, presentation language, PDF terms file. 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 maybe InnerBlocks for the bio. Fewer plugins in the admin means less attack surface and fewer conflicts with consent and cache plugins.
#Server-side blocks instead of shortcodes
A shortcode in body copy is debt you only see at migration. New code in Basel ships as a block with server render: semantic markup, attributes in the block comment, filterable output. An events list block reads the CPT, caches the query in a transient with explicit TTL and invalidation on save_post, not on every request.
For trilingual editorial work every string in a block goes through WordPress i18n functions. A German string in PHP is an exception, not the rule. Translations live in .po files, not in a hardcoded array in the theme. WPML or Polylang is added only when three front languages (DE, FR, EN) are real. A DE admin with PL content can be handled with roles and user locale without a full multilingual stack.
Code review on a block checks three things before the branch merges: does the block work with JS disabled on the front preview, 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 a board member page does not pass review.
A life sciences conference landing or a Messe Basel event page is not built by copying last year’s page. It is a CPT object with date, location, language and pattern. After the event the object stays in the archive, not as an orphan subpage in the tree.
#Basel: pharma, trilingual operations and the Art Basel freeze
Basel is not a financial hub above the Rhine or a container port on the Elbe. Life sciences, trilingual operations and a calendar that changes deployment priorities matter here. Those three axes set technical priorities for WordPress that must work in Basel, not only carry the city name in the title.
#Life sciences: Roche, Novartis and the ecosystem around them
Roche headquarters sit on Grenzacherstrasse. Novartis Campus is on Fabrikstrasse. Around them grows an ecosystem of CROs, suppliers, spin-offs and accelerators such as DayOne at BaselArea. That is not a WPPoland client list and not a GxP certification promise. It is market geography, and from it follows a simple point: a “corporate” site in Basel is often the entry to partner onboarding, scientific recruitment or results publication that someone else governs.
Basel Digital Hub and BaselArea promote the region as a life sciences cluster with access to three countries: Switzerland, Germany and France in the Dreiländereck. For WordPress that implies a second axis: copy and forms must work in German, often in French and in English, without broken hreflang and without impressum copied from a Zurich or Geneva template.
The University of Basel, the Department of Biosystems and University Hospital Basel (USB) set a different bar than a “visiting card agency site”. Their communication is a separate world. For firms that neighbour that cluster, Datenschutzerklärung, impressum and CH hosting are checked earlier than CTA button colour.
A Friday patch that disables a recruitment form with CV upload leaves HR with an empty inbox during a campaign week. REST integrations and webhooks therefore live in a plugin with tests, not in the theme’s functions.php.
#Art Basel freeze: a calendar that changes deployment priorities
Art Basel fills Messe Basel and the region every June: galleries, hotels, catering, transport, media. Event-related sites and restaurants, hotels and services within a few kilometres of Messeplatz see traffic spikes that do not appear in “normal” CrUX.
The development runbook for clients in Basel treats the Art Basel window as a period of elevated operational risk. That week does not schedule theme deployments, new blocks or plugin changes unless it is a security hotfix with written product-owner approval. Staging receives changes; production waits until the Monday after the fair. That is not event superstition. It is an agreed deployment freeze that a pharma compliance officer recognises from their own change-management procedures.
#SwissIX and hosting in Switzerland
SwissIX connects Swiss data centres. For a site operator in the Basel region, origin in CH shortens the path to users in the country and to networks that peer at the exchange anyway. DNS or certificate failure shows up immediately; monitoring must catch more than “ping the homepage”.
Personal data under nDSG raises the question: which jurisdiction hosts the server and the backup. Cyon operates from Basel and is one hoster local operators recognise without explaining “why not AWS in Virginia”. Infomaniak builds infrastructure in Switzerland. Metanet has in-country centres. The hosting conversation at kickoff is substantive, not cosmetic. Is production in CH? Does a copy leave the country overnight? Does the CDN terminate TLS in Switzerland, the EU or the USA?
#Trilingual DE/FR/EN operations
The Polish team knows WordPress. The client in Basel asks something else: whether the French version has the same impressum as German, whether hreflang points to de-CH not de-DE, whether consent copy matches the Datenschutzerklärung in all languages, whether an editor in Saint-Louis cannot publish a draft to production.
#Multilingualism is architecture, not a one-time setup
WPML, Polylang or a block theme with its own i18n routing needs regression after every translation-plugin, theme or page-builder update. The staging checklist covers: save a post in DE, preview FR, switch EN, hreflang tags in page source, URL map without duplicate canonicals, forms with required fields per locale.
Basel-Stadt has German as the official language, but the border region with France translates regulatory and B2B copy into French. English is the operational language in life sciences. A template copied only from the German market (Amtsgericht, USt-IdNr, Straße with ß) onto a Basel AG or GmbH site is an error a local lawyer spots faster than Lighthouse.
Swiss German is not German from Germany. In official and site copy: ss instead of ß (Strasse, not Straße), MWST instead of MwSt, Gross instead of groß. The French version must keep company data (UID, registered office) aligned with German even when marketing copy is local.
Practical rules written into theme documentation:
- Interface strings (buttons, form errors, aria-label, placeholder) use formal German on the DE front if that is the agreed register. French and English versions are formal too. A Polish variant, if added, uses natural Polish B2B register, not a one-to-one German copy.
- Polish editors get an admin locale they can work in. That does not have to match the front. Mixing user locale and site locale without testing ends with wrong date formats and a menu that jumps from Beiträge to Wpisy mid-screen.
- Impressum, Datenschutz and accessibility statements are templates with fields, not blocks an editor can accidentally delete from the tree. In Basel those pages are compliance elements, not marketing footnotes.
Polylang and WPML solve hreflang and language copies. They do not solve process: who approves German text before production. The brief records whether approval sits with the client in Basel or with the Polish content lead. Staging shows all three language versions, because regression “DE broke because someone edited FR” only shows on comparison, not in Lighthouse.
#Handelsregister, Zefix and the Basel-Stadt register
Impressum and footer are not “type the company name from a business card”. In canton Basel-Stadt the register is held by Handelsregisteramt des Kantons Basel-Stadt (Clarastrasse 28). The federal name index is Zefix (Zentraler Firmenindex). UID in format CHE-xxx.xxx.xxx is issued by the Federal Statistical Office; on VAT invoices the same number takes an MWST suffix. Firmenwortlaut, registered office and legal form must match the extract, not the Figma branding.
That is not the Zurich or Geneva register. An impressum template copied from Handelsregisteramt des Kantons Zürich or a Geneva office onto a Basel-Stadt company is an error a local lawyer spots faster than an LCP regression. The block theme holds these fields in a locked footer template.
#Accessibility: WCAG 2.1 AA and the Swiss context
Accessibility in Basel is not one statute. Public sector and research institutions increasingly require WCAG 2.1 at AA level. Private life sciences treats accessibility as reputation and partner onboarding, even without a formal obligation like Germany’s BFSG. The team does not sell an “accessibility certificate” without testing. At kickoff we record which regime applies to the site, then test what can be tested in the theme and blocks.
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 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 not only border colour. A recruitment form with CV upload must work by keyboard and screen reader.
- Media: alt text as a required field in the editorial process, not “we will add it later”.
- PDF: if terms, a product sheet or an annual report ships as an attachment, document accessibility enters the brief. WordPress will 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 that require WCAG, we add manual keyboard paths and comparison against the WCAG checklist. The team does not promise AAA unless the brief requires it and the budget allows.
Forms with personal data (recruitment, partner portal, newsletter with profile) are tested in three language versions. A validation error in French must read clearly in French, not as a machine-translated German string.
#Security for sites in the life sciences cluster
Proximity to Roche and Novartis does not make a marketing WordPress a GxP system or a certified clinical environment. The team does not claim the site “meets GxP” or “is ISO 27001 certified”. Most corporate WordPress sites in Basel are not standalone subjects of those regimes. Some sit next to organisations that are. Then WordPress must deliver inventory, access trail and Git discipline the client can paste into their own documentation.
A posture that can be maintained 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 for 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. The 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.
- Backups and restore: a backup without a tested restore is decoration. Restore test on staging is in the runbook.
- Logs: who logged into wp-admin, which plugin change went out. Retention agreed under nDSG, not “keep everything forever”.
The revised nDSG entered into force on 1 September 2023. Supervision sits with the Federal Data Protection and Information Commissioner (FDPIC, Eidgenössischer Datenschutz- und Öffentlichkeitsbeauftragter EDÖB). For sites processing personal data we prepare consent configuration, processor agreements and data minimisation for verification with the process owner. GDPR still applies to processing aimed at people in the EU. A corporate site in Basel with traffic from the Union therefore has two layers, not one.
Hosting “in Switzerland” (Cyon, Infomaniak, Metanet) is an argument about jurisdiction, not a magic shield. A Kleinbasel company will not fix a plugin that stores candidate CVs in wp_posts without access limits.
#Git, staging and code review
This is the layer that separates senior WordPress work from “upload a ZIP over FTP”. In Basel a client with an IT department asks about it on the second meeting, especially if the reviewer comes from Basel Digital Hub or internal IT at a CRO supplier.
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. A pull request has a description, screenshots or a screen recording from the editor, 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; Swiss IT in Basel usually prefers English in the diff and German in editorial documentation.
Staging is a copy of production with anonymised data. WP-CLI search-replace on the URL, separate keys, crons that send mail to real candidates disabled. Editorial clicks through staging with real Gutenberg patterns, not a developer’s localhost. Trilingual regression (DE, FR, EN), keyboard regression and recruitment-form regression with CV upload 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 “quickly upload” one PHP file over SFTP, because then nobody can reconstruct what ran on production the Friday before Art Basel.
WP-CLI is an operational tool: flush transients, wp scaffold, CPT import, autoload check. It does not replace tests. Where a plugin counts (dates, mapping, validation), PHPUnit follows. Blocks with non-trivial UI get an editor test on staging, because jsdom will not catch InspectorControls covering the Speichern button in German locale.
The 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. 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 pharma companies do”.
For a B2B site in Basel, time to first byte from a corporate network in CH and from a pharma campus matters, not only mobile on the Rhine. Monitoring from one US region lies. A measurement point in Switzerland or at least Central Europe is part of the operational contract, not an add-on. Poland and Basel share CET/CEST, so weekday diagnostics overlap.
A corporate site run by a Polish team, recruiting scientists and regulatory specialists in the Basel region, form with CV upload, DE/EN/FR versions, consent aligned with the Datenschutzerklärung. A forms-plugin update plus a multilingual-plugin patch waited in the production queue.
On staging, cloned from production with translations, CV upload in the FR version returned 500 after the new plugin version changed the file-size limit. In parallel hreflang pointed to de-DE instead of de-CH because the theme overwrote tags after an SEO plugin update. On production the same set would have shipped during HR’s campaign week. Recruiters would have had an empty inbox; candidates an error with no ticket number.
Staging stopped promotion. Rollback on the test copy confirmed the forms plugin alone was innocent when the theme no longer called a removed hook and locale mapping matched the runbook. The theme got a fix; the checklist (DE, FR, EN, upload, mail to HR, consent log) passed; only then production. There is no company name here because this is the shape of an event, not a logo case study. There is a mechanism: copy first, production second. Without a copy you get a post-mortem and manual CV collection from email.
The same shape returns with consent plugins, object cache serving an old careers page, and a “small” update in Art Basel week that loads the origin at peak traffic. Basel does not forgive that more quietly than another market. It looks worse because someone nearby asks about nDSG and Zefix.
#WooCommerce is a separate scope
This page does not build checkout, gateways or a product catalog. If the brief moves to a shop, MWST, QR-Rechnung, TWINT or a payment gateway, scope changes owner and is described on the WooCommerce developer in Basel page. Pillar without city: WooCommerce developer. Mixing a shop with a corporate theme in one repository without a plugin boundary is the fastest way for a Woo update to break a life sciences conference 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, a handover session and Git access for the client team. The runbook describes: how to add a pattern, register a new CPT, ship a branch, rebuild staging, whom to call when the editor will not save. If ongoing Core updates, monitoring and on-call are needed after go-live, that is WordPress maintenance and support in Basel, not a hidden annex to the theme. Pillar without city: WordPress maintenance.
Development pricing is individual and issued in writing after scope is agreed. There is no price list or “hour packages” on this page. Scope change (sudden FSE, a third language, intranet integration) returns to the written record before it enters the sprint.
#How to start a project in Basel
A short brief is enough to begin: which theme and plugins exist today, who edits (PL/DE/FR/EN), whether the front needs DE/FR/EN, whether a CPT for publications and events is in scope, whether Basel IT requires Git and staging from day zero, whether hosting must stay in Switzerland. The team reviews the installation, lists risks (Gutenberg used as a notepad, secrets in the repo, missing accessibility statement, ACF duplicated with blocks, impressum with German ß) and proposes a plan with acceptance criteria.
Contact: WPPoland contact form. The service pillar without a city slug stays at WordPress developer.