Stage Support is a Kraków company handling technical production of events — concerts, conferences, corporate galas, television productions — run by Krzysztof Pezda since 2013. Alongside events, the company rents out its own sound and lighting equipment, some of it built by the owner himself.
The old site was a single-page business card with no production portfolio, no visibility in Google, and no way for anyone to send an enquiry. I built a new site from scratch, based on Next.js, extended it with a panel for self-managing content, full SEO, a contact form, and deployment to a server.
📋 Project metrics
- Status: Completed, the site runs on a staging environment, awaiting final materials from the client before moving to the target domain
- Role: Full-Stack Developer / Architect — the whole project from strategy to deployment
- Scope: Strategy and content planning, admin panel (CMS), frontend implementation, SEO, contact form, accessibility, testing, production deployment
- Goal: Turn a static business card into a site that generates enquiries from clients on its own and lets the owner publish new productions without a developer's help
🚀 How the project came together
We started (together with the client) by understanding what Stage Support actually is — not an event agency that only coordinates, but a company that physically rigs the sound, hangs the lighting, and operates the console. That distinction had to be visible in every layer of the site: in the content, in the portfolio structure, in the design itself.
From there the work went in several directions in parallel: bilingualism of the site (Polish and English, each under its own URL), a custom content management system built on Strapi so the owner could independently add productions, client testimonials, and the offer without writing code. Every publish in the panel automatically refreshes the site — no need to wait for a redeploy.
The next big stage was visibility: metadata, structured data recognised by Google, a sitemap, a file for search engines. On top of that, the site is prepared so that language models like ChatGPT or Perplexity can cite it correctly when someone asks about a technical event producer in Kraków — an increasingly important channel that most local business sites completely forget about.
Then a contact form collecting specific information about the event (event type, date, number of people, location) together with spam protection and a rate limit, adding Google Analytics with proper cookie consent, and a round of accessibility fixes — so the site could be operated by keyboard, by screen reader, and so colour contrast met the WCAG standard. Finally automated tests, deployment configuration on the server (Docker, automatic build and deploy on every code change), and data backup.
🎯 Business problem
Krzysztof has been producing premium events for over a decade, but online you'd struggle to see it. The old site had no portfolio, no trace of SEO, and someone searching Google for "technical conference production Kraków" landed on event agencies, not on Stage Support.
❌ Specific problems
- No portfolio. Every delivered gala, concert, or conference is potential material that attracts further clients and helps in search — but adding a new production required a developer, so nobody did it.
- Two different businesses, one invisible site. Alongside events the company rents out sound and lighting equipment — sometimes to other companies in the same industry. Clients looking for specific gear to rent had no chance of finding Stage Support.
- Zero contact path. There was no structured form, no phone visible on mobile, no clear "ask for a quote" button.
- No visibility in search engines and in AI. Competing for local phrases in Google requires properly described productions and structured data. And increasingly clients ask not Google, but ChatGPT or Perplexity — and there too Stage Support didn't exist.
- No accessibility. Cultural institutions and public offices that run tenders for event production require compliance with accessibility standards — and the old site didn't even have the basics.
💡 How it was solved
- The site refreshes itself after a panel publish. When the owner adds a new production and publishes it, the CMS sends a signal to the site, which immediately clears the relevant part of the cache and shows the new content — without waiting for a periodic refresh or a manual redeploy. The mechanism is a deliberate compromise: pages render dynamically on every visit (because bilingualism requires precise canonical addresses and hreflang per URL), but the data from the panel is cached, so the site doesn't query the panel on every refresh — only after a publish, when the cache is selectively invalidated.
- An admin panel without surprises. All data fetched from the CMS passes through a validation layer, so if someone leaves a field empty in the panel or enters something unusual, the site doesn't crash — it simply shows a sensible fallback.
- Solving the translations problem in the panel. The CMS the site is built on has a flaw: new Polish content doesn't automatically create its English counterpart, and relations (e.g. "this production is tagged as a concert") don't copy across language versions. I wrote a mechanism that automatically creates an English skeleton of new content (for an editor to translate manually) and keeps relations synchronised between the Polish and English versions.
- SEO in two directions at once. Classic SEO (titles, descriptions, structured data recognised by Google, sitemap) plus preparing the site so AI assistants can understand and cite it correctly — a file for bots, clearly described productions with specifics (who, where, when, what gear), an FAQ with concrete answers.
- A form collecting meaningful context, not a generic "contact us". Event type, date, number of people, location — straight away you know what the client is asking about. The form has bot protection and a rate limit per IP per hour, and the data goes automatically to the company webhook, not to a database.
- Google Analytics only after consent. In line with GDPR — the tracking script doesn't load until the user accepts the cookie banner.
- Accessibility checked automatically and manually. The site passes with zero errors in an automated accessibility audit (axe-core) across all pages in both languages — keyboard, screen readers, colour contrast, tap target size on mobile.
- Two business lines, two paths. The event offer and equipment rental have separate pages, separate SEO, and separate contact paths, because they reach completely different audiences.
📈 Result
| Area | Before | After deployment |
|---|---|---|
| Web presence | Static business card with no portfolio | Full site with productions, updated independently by the owner |
| Content management | Required a developer | CMS panel — the owner adds content themselves, no code |
| Time to publish new content | Site redeploy | Automatic refresh in under a minute after publishing |
| Google visibility | No structured data | Full metadata, structured data, sitemap |
| AI visibility (ChatGPT, Perplexity) | None | Site prepared for citation by AI assistants |
| Contact | No form, no clear CTA | A form collecting event context + phone visible on mobile |
| Equipment rental | Invisible at all | A separate section with equipment categories and specs |
| Accessibility | Not checked | Zero errors in an automated accessibility audit, in Polish and in English |
| Languages | Polish only | Polish and English, with matching URL addresses |
"The company had a decade of productions behind it, but online you couldn't see any of it. I built a site that shows the portfolio, refreshes itself after every publish, and lets the owner work without a developer."
🛠️ Technical challenges
- A flaw in the CMS translations. Strapi (the system the content panel is built on) has a problem: relations between content (e.g. "this production is about a concert in Kraków") don't automatically copy between the Polish and English versions, even though media files do. I wrote two background mechanisms: one creates an English skeleton of new content right after the Polish version is added, the other keeps relations synchronised across language versions on every change.
- The site builds even without the content panel running. If the CMS is briefly unavailable during a build, the build still passes — the site simply shows the content later, once the panel is back and the first request comes in.
- Content refresh without unnecessary waiting. A publish in the panel sends a signal that immediately clears the relevant part of the site's cache — so new content is visible practically at once, not after an hour of waiting for an automatic refresh.
- Two language versions, each under its own address, without duplicating code. The Polish and English versions have separate URL prefixes (
/pl/,/en/), with their own translated subpage names. Hitting an address without a prefix redirects to the right language version based on browser settings. The language switcher always leads to the same content in the other language, not to the homepage. - Automatic backup with fast restore. Backup scripts for the database and media files run every night, with archive integrity verification. Restoring everything after a failure takes literally a few seconds.
🛠️ Architecture and tech stack
- Frontend: Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS
- Content panel (CMS): Strapi v5 + PostgreSQL, custom Polish-English synchronisation mechanisms
- SEO: automatic metadata, structured data (Schema.org), sitemap, a file for search engine and AI bots
- Contact form: server-side validation, spam protection, rate limiting, Make.com integration
- Analytics: Google Analytics 4, only after user cookie consent
- Accessibility: WCAG 2.2 AA compliance, zero errors in an automated audit
- Tests: unit and integration tests plus end-to-end tests simulating real user actions in the browser
- Deployment: Docker, automatic build and deploy on every code change, VPS server, site uptime monitoring, daily backup
🎨 Key design decisions
- A "technical, not eventy" design. A white-grey base with one strong colour accent (orange), clean typography, a grid-based layout — the whole thing should communicate the precision and professionalism of a technical producer, not the colourfulness of an event agency.
- The offer as one page with sections, not separate subpages. Each service has its own section with an anchor link — easier to scroll through and easier to manage in the panel.
- Productions as concrete case studies, not marketing copy. Client, venue, date, number of people, challenges, outcome, gear used, photo gallery — this format works well both in Google and in AI tools, because it's factual, not empty of content.
- Equipment rental as a separate section with categories. No separate subpage per product — one page with tabs (sound, lighting, video, stage) and a specs table is enough.
- Accessibility from the start, not as a fix at the end. Goal: zero errors in an automated accessibility audit, so the site can also be recommended to public institutions that require it in tenders.
Artifacts
- Site (staging): https://stagesupport.rafalmajewski.dev/pl
- Target address: stagesupport.pl (after the client delivers final materials)
- Source code: RafalWojciechRolsky/stage-support-v2
