BlogDigitalisation
My Web Stack for SMEs: Static First, Dynamic Where Needed
By Dominik Pototschnig20 min

In this article
My web stack does not start with technology logos. It starts with four boundaries: content, interaction, data and acceptance. Only once those boundaries are clear do I decide which tools are genuinely necessary.
For a company website made up mainly of public content, my usual starting point is: start static. Content pages are turned into HTML during the build, an automated generation process. Dynamic features can be added through a focused API, or server interface; in the snapshot, the contact route demonstrates this approach. A database only becomes part of the runtime path when data genuinely needs to be stored permanently. Before publication, automated checks—known as gates—verify that agreed technical rules are still being met.
This is not a universal blueprint. If an editorial team genuinely needs a browser-based editor, a CMS, or content management system, may be the better choice. If personalised content or information that must be current on every request is central to the product, on-demand rendering or a web app may be more appropriate. The right stack is not the largest one. It is the smallest one that can reliably meet the actual requirements.
Reviewed, non-public repository snapshot (version-controlled project state): commit 0d9f708, 15 September 2026. The source snapshot is not evidence of the production configuration.
Four boundaries instead of eight logos
Stack discussions often begin with names: Astro or Next.js? PostgreSQL or something else? Tailwind or traditional CSS? A different order is more useful when making an investment decision.
1. Content: what needs to be delivered?
If service pages, blog posts, case studies and company information remain the same for every visitor between two releases, those pages can be built in advance. If content changes only after editorial approval, that alone does not mean it must be regenerated on every request.
2. Interaction: what needs to respond to input?
A contact form is dynamic even when the surrounding page is static. It must validate input, trigger a defined server process and show the visitor a reliable status. That does not automatically mean every content page needs an application server.
3. Data: what needs to be stored permanently?
Not every interaction needs its own database. Forwarding information to a configured service has different requirements from a customer portal with accounts, permissions and persistent state. Persistence should be a justified architectural decision, not a default checkbox in a starter project.
4. Acceptance: how do we know a change is ready for approval?
“It looks good on my computer” is not a complete approval process. Links, metadata, language relationships, form behaviour, types and mobile presentation can be checked automatically for defined cases. Such tests do not eliminate every risk. They do, however, make specifically agreed errors visible before publication.
Architecture preselection in 60 seconds
- Public content stays the same between builds, and the publishing process suits the team: start static.
- Business teams need to edit and publish content themselves in the browser: evaluate a CMS.
- Core content must be current or personalised on every request: evaluate on-demand rendering or a web app.
- Requirements differ between sections: evaluate a hybrid rather than forcing the entire site into one operating model.
That is the decision-maker’s view. Investment should only be approved once the minimum scope, total-cost envelope, target date, internal capacity, a named owner for operations and the most important risks have been accepted. If any of these are materially unclear, the next step is not automatically implementation. It may be clarification, a pilot or stopping the initiative.
The following sections show how the current Wogenfels stack implements this separation technically—and where its limits lie. I describe the wider business context under Digitalisation for businesses.
The technical reasoning: the stack in the repository
The following table is a dated snapshot of the actual project state, not a shopping list for every website.
| Layer | Components as at 15 September 2026 | Role and boundary within the project |
|---|---|---|
| Tooling base | Bun 1.4.2, workspaces | Runtime, package manager and central path for tests and tooling; the version pin and lockfile remain necessary |
| Content output | Astro 7 | Static build, routes, Markdown content collections, languages and image processing; no SSR adapter |
| Design | Tailwind CSS 4, local Starwind components | Semantic design tokens and reusable UI building blocks; updates and verification remain project responsibilities |
| Interaction | Hono 4 on Bun, Zod 4 | Separate API and validated input boundaries only for features that require server logic |
| Data | Prepared Drizzle/PostgreSQL package using Bun SQL | Provides typed access and migrations; the snapshot does not show any production route using database persistence |
| Acceptance | Linting, types, tests, build, SEO audit, formatting and Playwright | Checks defined rules and browser journeys before publication |
Bun supports workspaces and includes its own test runner in bun test. In the Wogenfels project, Bun is pinned to version 1.4.2; the installed library versions come from the lockfile rather than open version ranges. This reduces the number of central runners used by the repository. It is not a benchmark for speed or cost.
Why I start public content pages statically
Astro’s configuration reference describes output: "static" as a build mode in which pages are pre-rendered by default. That is the mode used by this project. Blog posts, service pages and other public content are therefore not assembled into HTML only when someone requests them.
For a content-led SME website, this is a plausible starting point when two conditions are met:
- Public content can remain the same between releases.
- Changes can pass through a controlled build and approval process.
In this delivery path, a content page does not need an application server to render it again for every visitor. It still needs hosting, a properly configured web server or CDN and an accountable publishing process. A connected API and external services remain separate operational components.
The static build therefore removes one specific runtime task from content delivery: repeatedly generating the same public page. Image sizes, CSS, JavaScript, content and operations still need deliberate design.
Static does not mean motionless
The current frontend has no client-side UI framework islands, but it does use focused browser scripts and API calls. Navigation, consent, forms and booking flows can be interactive even though the initial page is delivered as static HTML.
The useful distinction is therefore:
- Build content in advance when it stays the same between releases.
- Run interactions deliberately when input or an external state requires them.
- Render on demand when the page itself must be current or personalised at request time.
Astro documents on-demand rendering, meaning rendering when a request arrives, using an adapter for cases including personalised content or information that must be current on every request. The reviewed Wogenfels frontend does not include such an adapter. That is a decision for this website, not a verdict against the operating model.
Content, languages and images belong in the same build contract
Blog posts are stored in the project as Markdown within a validated Astro content collection. Content Collections connect content to a schema and can be queried with getCollection(). In the Wogenfels project, getStaticPaths() turns this content into the post routes.
This is deliberately centred on code and the build process. A new article is not edited live in a public admin area; it is versioned as a reviewed file and then built. That approach suits planned publishing and technical acceptance. It is less suitable when many editors need to publish content frequently without access to the repository and build process.
Two languages involve more than two copies of the text
German appears without a language prefix under /; English is under /en/. Astro’s internationalisation routing supports an unprefixed default language. Translated slugs and the relationships between them are additionally mapped in one central place in the project; they are not an automatic Astro feature.
Both language versions share components and structured rules, limiting duplicated structural work. Content parity does not happen automatically, however. Titles, descriptions, slugs, technical terms, links, images and claims must be checked in each language.
An image is part of the page, not decoration added after the build
Local images pass through a shared component based on Astro’s asset pipeline. Astro can process imported local images and generate responsive variants. The project generates AVIF and WebP output, sets fixed dimensions and distinguishes the prioritised hero image from lazy-loaded content graphics.
A tool cannot prevent an unsuitable subject or poor alt text. It can enforce technical rules—a known source, dimensions, variants and loading priority—at a common boundary.
Tailwind and local components: more control, more responsibility
In this project, Tailwind CSS is more than a collection of short class names. Brand colours, spacing and semantic roles are defined as shared tokens. Tailwind 4 describes @theme variables as the basis for generated utilities; its official Vite integration processes the classes used in the project.
The practical value lies in a shared language: a warning surface, primary button or text colour is styled according to its function rather than through arbitrarily repeated individual values. This can make consistent changes easier. Good design, clear states and accessibility still need to be verified directly.
For foundational UI components, the project uses Starwind. Starwind supports Astro with Tailwind CSS 4, and its CLI adds components to the project. Once added, the components used here are local files within the repository.
This is a deliberate trade-off:
- Control: the markup and styling live in the project and can be connected to its design system.
- Responsibility: updates, local changes, accessibility and regressions must be checked within the project.
“We own the code” does not mean “we never need to maintain it again.”
Dynamic behaviour starts at a clear API boundary
A static website can accept data and initiate business processes. It should simply make clear where the static part ends.
For this purpose, the Wogenfels project runs a separate Hono application on Bun. Hono supports Bun as a runtime and provides request validation. The specific contact route accepts JSON and checks it against a Zod schema before business processing begins. Zod’s safeParse() returns a result that distinguishes success from failure.
The API defines control points for logging, security headers, permitted origins, request limits and protection against unwanted write requests from third parties. This describes boundaries in the code, not the security of an unknown production environment.
The contact form illustrates the architectural idea. The entire sequence below is a recommended pattern for a robust implementation, not proof of a production result:
- Hosting, a web server or a CDN should deliver the pre-built HTML to the browser.
- Only the specific input should be sent to the API as a structured request.
- The API should validate and inspect that request at defined boundaries.
- An external provider should only be used when the corresponding configuration is present.
- The API should return a defined success status, and the interface should verify it before displaying success.
This means the entire website need not become dynamic simply because one form is dynamic. Conversely, a form does not become secure or GDPR-compliant merely because the content page is static. Data categories, providers, legal basis, contracts, consent, retention, access and operations must still be assessed for the specific processing. This technical classification is not a substitute for legal review and does not constitute legal advice.
Data package prepared—persistence only when genuinely needed
The repository prepares a data package with Drizzle ORM, Bun’s native SQL client and the PostgreSQL dialect. Drizzle documents the connection through Bun SQL. Drizzle Kit can generate SQL migrations from schema changes and apply migrations that have not yet been run.
However, the reviewed snapshot does not show any production route using database persistence. Outside the data package, only a startup test loads the database package. There is no database import in the frontend or in the static route generators either. The build, type checking and content output are designed to work without a running database.
A database makes sense when the use case requires durable, structured data—for example accounts, permissions, business states or traceable process statuses. At that point, schema, migrations, access, backups, retention and deletion all belong in the decision.
For a content-only section, a database would not add value merely because the technology has been prepared. Availability is not evidence of a requirement.
SEO and quality as a verifiable contract
Technical SEO consists of relationships that can easily drift apart during a change: title and description, canonical URL, hreflang, Open Graph image, structured data, internal links, sitemap, robots.txt, language and image attributes.
The shared layout generates canonical URLs, hreflang, Open Graph metadata and JSON-LD. The sitemap, robots.txt and llms.txt are derived from central data. A dedicated SEO checker reads the completed build and verifies defined rules for metadata, headings, language relationships, images, links, structured data and the sitemap.
For me, this is the difference between “we have SEO fields” and “we have a verifiable SEO contract”: a rule is not merely documented; it can stop the build with a concrete finding. This gate reduces technical omissions within its rule set. It does not assess search demand, the quality of the offer or rankings.
Browser gates for behaviour, not just files
The root checks include linting, types, unit and integration tests, the build, the SEO audit, formatting checks and Playwright end-to-end tests. Playwright can configure test web servers, while its web assertions automatically wait until an expected condition is met or the timeout expires.
In this project, browser runs verify defined journeys and presentations in Chromium, including mobile views, navigation, languages, forms and metadata. They provide evidence for those scenarios, not for every conceivable browser or failure case. Selecting the right risks therefore matters more than a high test count.
When a CMS or on-demand rendering is a better fit
The Wogenfels stack addresses a particular class of requirements. It would be the wrong choice if its core way of working conflicts with the client’s day-to-day reality.
| Starting point | Plausible first option | What must be assessed |
|---|---|---|
| Public content stays the same between builds | Start static | Does the repository/build publishing process suit the team? |
| Browser-based editing is a core requirement | Evaluate a CMS, such as WordPress | Which roles, extensions, data flows and operational tasks does it create? |
| Core content must be current or personalised on every request | Evaluate on-demand rendering or a web app | Which pages actually require this mode? |
| Requirements differ between areas | Evaluate a hybrid | Are the boundary, responsibility and approval process documented for each area? |
WordPress provides a browser-based block editor. When multiple business teams need to create, review and publish content in the browser on an ongoing basis, an editorial system is a genuine requirement—not an “old-fashioned” answer.
Astro names personalised content or information that must be current on every request as cases for on-demand rendering. If prices, permissions or signed-in views fall into this category, that mode may be suitable. A hybrid can pre-build public pages while running a clearly separated app area dynamically.
The working template before choosing technology
Answer these five questions in writing before comparing proposals by framework name:
- Content: Which pages stay the same between releases, and how often do they change?
- Editorial process: Who creates, reviews and publishes content—and do they work in a browser or through a repository/build process?
- Interaction and data: Which features need server logic, which data must persist, and which providers are involved?
- Timeliness: Which content genuinely needs to be current or personalised on every request?
- Acceptance: Which core journeys, language relationships, metadata, error states and mobile views must be verifiably checked before every release?
Responsibility belongs in the architecture
Enter names or clearly defined roles for every task. A means the Accountable client who decides, provides the budget and accepts the result. C means the Creator or implementer who plans, builds, documents and hands over the work. O means the Operator who monitors, runs and restores the system. One person may hold several roles; “the service provider” or “internal” alone is not precise enough for escalation and budgets. A good digitalisation partner makes these boundaries visible before implementation.
| Task | Roles and names | Handover evidence and escalation target |
|---|---|---|
| Content approval and translation | A: ___ / C: ___ / O: ___ | ___ |
| Publishing and fallback path | A: ___ / C: ___ / O: ___ | ___ |
| Dependencies and security updates | A: ___ / C: ___ / O: ___ | ___ |
| Operational monitoring, incidents and availability | A: ___ / C: ___ / O: ___ | ___ |
| Backup and restoration | A: ___ / C: ___ / O: ___ | ___ |
| Providers, contracts and privacy review | A: ___ / C: ___ / O: ___ | ___ |
| Data export, handover and exit | A: ___ / C: ___ / O: ___ | ___ |
If a business-critical row remains unresolved, the stack is not finished—only the demo is.
Milestones through to operational handover
| Milestone | Deliverable, objective, dependency and internal capacity | Acceptance and ownership of transition and fallback |
|---|---|---|
| Concept approval | ___ | ___ |
| Content/data handover | ___ | ___ |
| Pilot | ___ | ___ |
| Business acceptance | ___ | ___ |
| Operational handover | ___ | ___ |
Compare total costs without inventing imaginary figures
The cost of a web stack is not contained in the framework’s name. Copy and complete the following template for every option, using the same period and scope:
| Field | Unit or calculation | Input |
|---|---|---|
| Common period and scope | Months, pages, languages, core features and exclusions | ___ |
| One-off external work | Discovery + design + content + migration + integrations + tests + training | ___ € |
| Recurring costs | Monthly amounts × months: hosting, runtime, database, providers and so on | ___ € |
| Internal work | Hours per role × internal cost rate | ___ € |
| Change, handover and exit | Expected effort for updates, export, documentation and replacement | ___ € |
| Risk allowance | Justified amount for named residual risks | ___ € |
| Total cost | One-off + recurring + internal + change/exit + risk allowance | ___ € |
| Assumptions and source | Proposal version, volume assumptions, exclusions and uncertainties | ___ |
| Accountable person and date | Name and date of the most recent review | ___ |
A low-cost hosting proposal can become expensive if the editorial process does not fit. A powerful CMS may be commercially sensible when it enables daily editing by business teams. A lean static stack can be impractical if every copy change permanently depends on an overstretched development team.
Without a specific scope, team, providers and operating model, euro amounts in this article would merely create false precision. The better preselection question is: What ongoing work does the architecture create—and who will take responsibility for it?
What I deliberately do not promise
This stack is a well-justified choice for the Wogenfels website described here. It does not justify general guarantees:
- Astro or a static build is not automatically faster, more secure or stronger for SEO than every alternative.
- Technical metadata and an SEO audit do not guarantee rankings.
- Tests do not guarantee an error-free system; they assess the selected scenarios.
- Starting static does not determine GDPR compliance. The specific data flow, providers, contracts, configuration and operations still require assessment.
- Local UI components do not remove the obligation to update them.
- Snapshot
0d9f708from 15 September 2026 proves neither a later state nor the production configuration.
These boundaries are part of demonstrating competence: good architecture explains not only what it can do, but also when it does not fit.
Quick answers about web stacks for SMEs
Why use Astro for an SME website?
In the reviewed Wogenfels snapshot 0d9f708, Astro is a suitable choice because its static configuration can pre-build the public content pages. This only holds while those pages remain largely unchanged between releases and the build process suits the team.
Can a static website process forms and data?
Yes. Here, “static” describes the delivery of the content page. In the snapshot, the contact form calls a separate Hono API running on Bun. Persistent storage must be treated separately: the Drizzle/PostgreSQL package has been prepared technically, but the snapshot does not show any production route using database persistence. The API and data flow still need their own assessment.
When do WordPress, a CMS or on-demand rendering make more sense?
A CMS is more plausible when browser-based editing and editorial autonomy are core requirements. On-demand rendering or a web app is more plausible when core content must be current or personalised at request time.
Conclusion: architecture reveals itself at the boundaries
The current Wogenfels stack separates pre-built content, focused interaction, prepared persistence and technical acceptance. Whether that division suits another SME depends on its editorial process, timeliness requirements, data, responsibilities and total cost—not the logos in the stack.
The next checkpoint should therefore not be a framework proposal but a one-page, versioned architecture brief. It uses the same scope and period for every option. It names requirements and excluded options; three business-critical journeys, including failure consequences and fallback paths; named roles; milestones; acceptance criteria; and total-cost assumptions. The most important risks include likelihood, impact, mitigation, the decision required for any residual risk and an accountable person. No critical task remains without an A, C and O assignment.
Named people with business and budget accountability confirm the version and date. The outcome must be unambiguous: Go, Pilot, Clarify or Stop. Only then should the appropriate proposal or deliberately limited trial follow.
You can find an overview of the practical implementation under Services. For the joint assessment, bring your content rhythm, editorial roles, interactions, data that must persist and current acceptance criteria. These inputs can be turned into the architecture brief during a no-obligation introductory meeting—before a framework has been chosen.
Sources and currency
The official technical sources were checked directly on 15 September 2026. They document product capabilities, not the superiority of the Wogenfels stack. Claims about the versioned project state refer to the non-public snapshot 0d9f708; it is therefore not linked as a reader source.
- Astro:
outputconfiguration, Content Collections, Images, Internationalisation, On-demand rendering - Bun: Workspaces, Test runner
- Tailwind CSS: Theme variables, Vite integration
- Hono and Zod: Hono on Bun, Hono validation, Zod basics
- Drizzle: Bun SQL connection, Generate migrations, Apply migrations
- Starwind UI: Installation, CLI
- Playwright: Test configuration, Assertions
- WordPress: Block editor
- Web stack
- SME website
- Astro
- Bun
- Hono
- Tailwind CSS
More articles
Process Order Emails with AI: An Architecture Case Study
A reviewed development snapshot shows how order emails and PDFs can become controlled ERP proposals—with human review and Xentral integration.
Hermes Agent or n8n? How SMEs Can Build a Controlled AI Employee
Hermes Agent or n8n? See when SMEs should use an agent, a fixed workflow, or a controlled combination of both.
Which AI Models Can Run Locally? Memory, Costs and SME Use Cases
Which AI models can run locally? An SME guide to model size, RAM/VRAM, quantisation, useful tasks, hardware tiers and total cost of ownership.
