Astro 5 SSR with the @astrojs/node standalone adapter and TypeScript strict mode
stefanbraum.de — Astro Portfolio Template
By braum-me
Source code for a personal portfolio and blog site built on Astro 5 SSR with the Node adapter, featuring a forest-green dark theme, German/English bilingual support, and dynamic OG image generation, self-hostable via Docker.
Explore the design
Compare the page layouts and mobile experience. Open any screenshot for a closer look.
Actual screenshot captured by the server browser.
All pages & views 3
Screenshots show visual appearance; interactive behavior may differ.
What stands out
A quick read of the recorded project description.
Tailwind 4 forest-green dark theme with self-hosted Inter, Geist, and JetBrains Mono variable fonts
Bilingual i18n with German as default and English under /en/, with dictionary structure kept consistent by types
Blog managed as Markdown articles via Astro Content Collections, with RSS output
Dynamic OG images generated at /api/og.png via Satori and @resvg/resvg-js
Includes a Dockerfile and docker-compose example, supporting Coolify self-hosted deployment
Template Details
This repository contains the complete source code for the personal site stefanbraum.de, positioned as a combined portfolio and blog. The stack centers on Astro 5, using the @astrojs/node adapter in standalone mode for server-side rendering, TypeScript in strict mode, and styling provided by Tailwind 4 via @tailwindcss/vite. The site's default language is German (root path /), with an English mirror under /en/; UI copy lives in src/i18n's de.ts and en.ts, and a Translations type enforces that both dictionaries share the same structure. Blog post bodies themselves are not language-specific, and the /en/blog listing page explicitly notes that posts are in German. Blog content is managed as Markdown articles via Astro Content Collections, while src/data holds typed data for cases, skills, timeline, and certifications. Visually, the site uses a forest-green dark theme, self-hosts Inter, Geist, and JetBrains Mono variable fonts, uses GSAP and ScrollTrigger for entrance animations, and implements an ambient shader and skill orb effect with lazy-loaded Three.js. Dynamic OG images are generated by Satori with @resvg/resvg-js at the /api/og.png endpoint. Code formatting and linting are handled by Biome, and pnpm is used for package management. For deployment, a Dockerfile is provided, building a non-root Node 22 Alpine image; the standalone server reads HOST and PORT from environment variables, defaults to port 4321 inside the container, has no persistent state, and logs to stdout. It can also be deployed to Coolify following the README steps. The README also states that the MIT license covers only code and configuration, while content such as blog posts, case descriptions, and i18n copy remains the author's copyright; if forking as a template, you must replace it with your own content.
Is it right for your project?
Use Cases
- Building a combined personal portfolio and blog site to showcase cases, skills, timeline, and certifications
- A personal website that needs German and English UI but keeps blog bodies in a single language
- Developers who want to self-host an Astro SSR site via Docker or Coolify
- Blog projects that need dynamically generated social-share OG images and an RSS feed
Suitable For
- Front-end developers familiar with Astro, TypeScript, and Tailwind
- Users who want to publish a personal site based on MIT-licensed code after replacing it with their own content
- Personal projects that need a self-hosted, stateless container deployment
Getting started & customization
Use these recorded setup notes alongside the repository instructions for your chosen version.
- 1
Install dependencies with pnpm; pnpm dev starts the development server at http://localhost:5556 by default
- 2
Copy .env.example to .env; in production, at least set PUBLIC_SITE_URL for canonical, OG, and RSS
- 3
Optionally configure UMAMI_SCRIPT_URL and UMAMI_WEBSITE_ID to connect self-hosted Umami analytics
- 4
The Docker image runs as non-root Node 22 Alpine; the standalone server reads HOST and PORT, with a default container port of 4321
- 5
The MIT license covers only code and configuration; content such as blog posts, case descriptions, and i18n copy must be replaced with your own
License & source material
Usage conditions & limitations
Free to use · keep license noticeThis entry covers the free version in the public repository under the MIT license; the free scope is the code of this version and does not mean external services or third-party assets are free.
Must comply with when using
- You may use, modify, commercialize, and distribute this version's code for free.
- When distributing copies or substantial portions of the code, retain the original author's copyright notice and the full MIT license notice.
- The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.
Additional costs & items to verify
- The MIT license covers only code and configuration; content such as blog posts, case descriptions, and i18n copy remains the author's copyright and is not licensed with the code.
- If using this project as a template fork, you must replace the blog posts in src/content/blog/, the case descriptions in src/data/, and the copy in src/i18n/ with your own content.
- Optional self-hosted Umami analytics requires you to provide the Umami script URL and site ID; not configuring it does not affect site operation.
- Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses and cannot be judged solely by the code's MIT license.
- External services such as domains, hosting, databases, payments, or AI may incur separate charges.
View Original Text Basis
Permission is hereby granted, free of charge
Original License Text
Die MIT-Lizenz deckt nur Code und Konfiguration ab.
Original README
bitte den Content (Blog-Posts in `src/content/blog/`, Case-Beschreibungen in `src/data/`, Texte in `src/i18n/`) durch eigenen ersetzen
Original README
https://github.com/braum-me/stefanbraum.de/blob/main/LICENSEhttps://github.com/braum-me/stefanbraum.de/blob/main/README.mdUMAMI_SCRIPT_URL
Original README
Compiled by DeepSeek based on repository license and README ·2026-10-01. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.
Project checks & description sources
Template Information
- Source platforms
- GitHub
- Documentation and maintenance reference score
- More documented · 85 / 100
- Technologies
- Astro
- Website type
- Portfolio · Blog
How this score is calculated
Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.
What to verify for this project
- Repository update recorded
- 2026-09-28
- Screenshot last checked
- 2026-10-01
A demo link is listed. Check it with your own content and viewport sizes; its presence does not confirm that forms, authentication or payments work.
The catalog identifies Astro as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.
Use a selection guide →How this description was prepared
AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.
Automatically checked against source and license rules; no manual editorial review.
Inspect the recorded source material
SHA-256: e470ac906a5cbdc2e77721dca2c2fc2d7f413d02785a14db291e4b04239a6a6e
2026-10-01T13:33:33.311Z
Source file / repository# stefanbraum.de
Personal site source. Astro 5 SSR with the Node adapter, TypeScript strict, Tailwind 4. Forest-green dark theme, two locales (`de` default, `en` under `/en/`), self-hosted blog, dynamic OG-image generation.
**Live:** [stefanbraum.de](https://stefanbraum.de)

## Stack
- [Astro 5](https://astro.build) with `@astrojs/node` (standalone mode)
- TypeScript strict (`noUnusedLocals`, `noUncheckedIndexedAccess`)
- Tailwind 4 via `@tailwindcss/vite`
- Self-hosted variable fonts (Inter, Geist, JetBrains Mono)
- [Satori](https://github.com/vercel/satori) + `@resvg/resvg-js` for dynamic OG images
- GSAP + ScrollTrigger for entry animations
- Three.js (lazy-loaded) for ambient shader and skill sphere
- Astro Content Collections for the blog (Markdown)
- [Biome](https://biomejs.dev) for format + lint
- pnpm
## Local development
```bash
pnpm install
pnpm dev # http://localhost:5556
pnpm check # astro check (type errors, accessibility hints)
pnpm build # production build
pnpm lint # biome
pnpm format # biome format --write
```
## Project layout
```
src/
├─ components/ # Astro components (Hero, Cases, Skills, etc.)
├─ content/blog/ # Markdown posts (Astro Content Collection)
├─ data/ # Typed data (cases, skills, timeline, certifications)
├─ i18n/ # Locale dictionaries (de, en) + helpers
├─ layouts/ # BaseLayout
├─ pages/ # Route handlers
│ ├─ api/og.png.ts # Dynamic OG image endpoint
│ ├─ blog/ # Blog listing + detail
│ ├─ en/ # English mirror routes
│ └─ rss.xml.ts # RSS feed
├─ scripts/ # Client-side animation
└─ styles/global.css
```
## Environment
Copy `.env.example` to `.env` and fill the values you need. All variables are optional except `PUBLIC_SITE_URL` for production.
| Variable | Purpose |
| ------------------ | -------------------------------------------------- |
| `PUBLIC_SITE_URL` | Canonical site URL (used in canonical, OG, RSS) |
| `UMAMI_SCRIPT_URL` | Self-hosted Umami script URL (analytics, optional) |
| `UMAMI_WEBSITE_ID` | Umami site ID (analytics, optional) |
## Deploy
The included `Dockerfile` produces a non-root, production-ready Node 22 Alpine image. The standalone server reads `HOST` and `PORT` from the environment.
### Container basics
- Internal port: `4321` (Astro Node-Adapter standalone default)
- Bind host: `0.0.0.0` (set via `HOST` env)
- Healthcheck endpoint: `/` returns 200
### docker-compose
```yaml
services:
web:
build: .
environment:
HOST: 0.0.0.0
PORT: 4321
PUBLIC_SITE_URL: https://example.com
ports:
- "4321:4321"
```
### Coolify
1. New Resource → Public Repository → repository URL
2. Branch: `main`
3. Build pack: `Dockerfile` (auto-detected)
4. Port mapping: container exposes `4321`
5. Environment variables: at minimum set `PUBLIC_SITE_URL`. Coolify injects `HOST=0.0.0.0` automatically; otherwise add it explicitly
6. Deploy
The container has no persistent state. Logs go to stdout.
## Internationalization
Astro 5 native i18n.
- `de` (default) → `/`
- `en` → `/en/`
UI strings live in `src/i18n/de.ts` and `src/i18n/en.ts`. Blog post bodies are language-neutral; the listing on `/en/blog` carries an explicit notice that posts are in German.
To translate a string, edit both dictionaries. The `Translations` type in `de.ts` enforces structural parity.
## License
MIT — see [LICENSE](./LICENSE).
Inhalte (Briefings, Blog-Posts, Texte): © 2026 Stefan Braum, alle Rechte vorbehalten. Die MIT-Lizenz deckt nur Code und Konfiguration ab. Wer den Stack als Template forken will: gerne, aber bitte den Content (Blog-Posts in `src/content/blog/`, Case-Beschreibungen in `src/data/`, Texte in `src/i18n/`) durch eigenen ersetzen.
Explore similar templates
Compare previews and descriptions within the same stack and category.

astrowind
AstroWind is a free, open-source Astro starter theme using Astro and Tailwind CSS, released under the MIT license.
Astro · Blog

astro-paper
AstroPaper is a minimal, responsive, accessible, and SEO-friendly Astro blog theme. Articles are stored as Markdown/MDX in src/content/posts/, with subdirectories affecting URLs.
Astro · Blog

fuwari
Fuwari is a static blog template built with Astro and Tailwind CSS for personal blogs. It manages posts as Markdown files in src/content/posts/, with frontmatter for title, date, description, cover, tags, categories, draft status, and language.
Astro · Blog

Firefly
Firefly is a clean personal blog theme forked from Astro and Fuwari, offering four background modes, single/double sidebar and list/grid layouts, Pagefind client-side full-text search, and a six-language UI.
Astro · Blog

astro-theme-cactus
Astro Cactus is an Astro-based blog and portfolio theme that uses Markdown/MDX content collections to manage posts, notes, and tags, with frontmatter type-checked by a schema.
Astro · Portfolio

astrofy
Astrofy is a free and open-source personal portfolio website template built with Astro and TailwindCSS, with built-in blog, CV timeline, project showcase, store, and RSS feed modules.
Astro · Portfolio
