A static site generator for building and publishing your own Technology Radar.
About · Why a Technology Radar? · Features · Screenshots · Quick Start · Project Structure · Configuration · Radar Items · Development · Custom Styling · License
This project is maintained by Porsche Digital and is based on the open-source AOE Technology Radar. The codebase has been substantially rewritten and extended — it is not a drop-in replacement.
Note
Your existing radar items (Markdown files) can be reused as-is, but the configuration needs to be updated to match the new schema.
A Technology Radar makes technology decisions visible across your organization. It gives CTOs, architects, and tech leads a shared vocabulary for evaluating, adopting, and retiring technologies — and keeps engineering teams aligned on what to invest in.
- Visual technology landscape — See your entire technology portfolio at a glance, organized by segment and maturity ring
- Track decisions over time — Full revision history per technology and a trajectory view across releases, so you can see how assessments evolved
- Team visibility — Understand which teams use which technologies, enabling informed staffing and knowledge-sharing decisions
- Searchable and filterable — Find technologies instantly by name, tag, team, or status with real-time highlighting across the radar. Supports configurable multi-select or single-select filtering with shareable filter URLs
- Your branding, your rules — Fully customizable colors, logos, segments, rings, and labels via a single
config.json - Zero infrastructure — Static site that deploys to GitHub Pages, Netlify, or any hosting. No servers, no databases, no runtime dependencies
- Content as code — Technologies are plain Markdown files in Git. Review changes in PRs, track history with commits, collaborate with your existing workflow
Drill into a single segment with a zoomed mini-radar and a grouped technology list.
Each technology has its own page with ring status, description, tags, teams, and full revision history.
Track how technology assessments evolved across releases with the trajectory matrix.
Fully responsive — works on phones and tablets out of the box.
Important
Prerequisites: Node.js 22+
mkdir my-technology-radar && cd my-technology-radar
npm init -ynpm install @porscheofficial/porschedigital-technology-radarScaffolds starter files (radar/, config.json, about.md, public/, custom.scss, .gitignore) into your directory:
npx techradar initEdit the scaffolded files to match your organization:
config.json— branding, segments, rings, colors (see Configuration)radar/— your technology items as Markdown (see Radar Items)about.md— content for the help & about pagepublic/— favicon, images, background imagecustom.scss— optional style overrides
npx techradar dev # Start dev server with file watching
npx techradar build # Build static site → build/
npx techradar serve # Start dev server without file watchingAfter npx techradar build, the static site is in build/. Deploy it to GitHub Pages, Vercel, Netlify, or any static hosting provider.
my-technology-radar/
├── config.json # Your configuration overrides
├── about.md # Content for the help & about page
├── custom.scss # Optional style overrides
├── public/
│ ├── favicon.ico # Your favicon
│ └── images/ # Images referenced in radar items
├── radar/
│ ├── 2024-06-01/
│ │ ├── react.md
│ │ └── kubernetes.md
│ └── 2025-01-15/
│ ├── react.md # Updated entry overwrites previous
│ └── deno.md
├── build/ # Generated static site (after build)
├── .techradar/ # Shadow build dir (auto-generated)
└── .gitignore # Auto-generated with .techradar/, build/, node_modules/
The CLI automatically creates a .gitignore (or extends your existing one) with the entries needed to keep generated directories out of version control.
Tip
Only config.json, about.md, custom.scss, public/, and radar/ need your attention. Everything else is managed by the CLI.
All configuration lives in data/config.json. Any key you omit falls back to the defaults in data/config.default.json. You only need to set what you want to change.
Root
| Key | Description | Default |
|---|---|---|
basePath |
URL path prefix. Set to / for root hosting, or /techradar for a sub-path. |
/ |
baseUrl |
Full origin (scheme + host) where the radar is hosted, e.g. https://opensource.porsche.com. Used for sitemap.xml, canonical links, and Open Graph / Twitter meta tags. The runtime env var NEXT_PUBLIC_BASE_URL overrides this when set (useful for staging deploys). The basePath is appended automatically — do not include it here. |
"" |
editUrl |
If set, shows an edit button on item pages. Supports {id} and {release} placeholders. Example: https://github.dev/org/repo/blob/main/data/radar/{release}/{id}.md |
"" |
headerLogoFile |
Path to a logo image in public/ for the header. Leave empty to use the default Porsche crest. |
"" |
footerLogoFile |
Path to a logo image in public/ for the footer. Leave empty to use the default Porsche wordmark. |
"" |
jsFile |
Path in public/ or URL to a custom JavaScript file to include on every page. |
"" |
backgroundImage |
Path to an image in public/ shown as a subtle background overlay. Leave empty to disable. |
"" |
backgroundOpacity |
Opacity of the background image overlay (0 = invisible, 1 = fully visible). | 0.06 |
imprint |
URL to your legal information / imprint page. | "" |
toggles
| Key | Description | Default |
|---|---|---|
showSearch |
Show the search bar in the header. | true |
showChart |
Show the radar visualization on the homepage. | true |
showTagFilter |
Show the tag filter below the radar. | true |
showTeamFilter |
Show the team filter below the radar. | true |
showBlipChange |
Show a directional arc on Changed blips indicating promotion (inward) or demotion (outward). | true |
showDemoDisclaimer |
Show the demo-data disclaimer banner on the homepage. | false |
multiSelectFilters |
Allow selecting multiple filters per dimension (OR semantics within, AND across). When false, each dimension allows only one active filter at a time. |
true |
colors
A map of CSS color values that theme the entire radar.
| Key | Description | Default |
|---|---|---|
foreground |
Primary text and UI element color | #FBFCFF |
background |
Page background | #0E0E12 |
highlight |
Highlighted text and active elements | #FBFCFF |
content |
Secondary content text | #AFB0B3 |
text |
Tertiary / muted text | #88898C |
link |
Link color | #FBFCFF |
border |
Border and separator color | #404044 |
tag |
Tag background color | #404044 |
segments
An array of segment objects (1 or more). The radar geometry adapts automatically — arc sweep is 360° / N, and labels follow the arcs. 3 to 6 is the comfortable range; beyond 6 the per-segment arc becomes too narrow for readable labels and the blips start to crowd.
Forks using quadrants: in data/config.json continue working but emit [deprecated] config key "quadrants" is renamed to "segments"... at build time. Migration: rename the key.
Markdown frontmatter quadrant: <slug> continues working but emits [deprecated] frontmatter key "quadrant" is renamed to "segment" in <file>. Migration: rename the field.
Both shims will be removed in a future major release. See ADR-0025.
| Key | Description |
|---|---|
id |
Identifier used in radar Markdown files and URLs |
title |
Display title of the segment |
description |
Shown on the homepage and segment detail page |
color |
CSS color for the segment arc and its blips |
rings
An array of ring objects (typically 4), ordered from innermost to outermost.
| Key | Description |
|---|---|
id |
Identifier used in radar Markdown files |
title |
Display title, shown as badge label |
description |
Optional description text |
color |
CSS color for the ring badge |
radius |
Outer boundary of the ring as a fraction of the chart (0 to 1) |
strokeWidth |
Thickness of the ring's arc border in the SVG |
flags
Flags mark items as new, changed, or default (unchanged). Each flag has a single key:
| Key | Description |
|---|---|
title |
Display label for the flag (e.g. "New", "Changed", "Unchanged") |
chart
| Key | Description | Default |
|---|---|---|
size |
Base size of the radar chart in pixels. Increase if you have many items. | 800 |
blipSize |
Radius of each blip dot in pixels | 12 |
social
An array of social link objects shown in the footer.
| Key | Description |
|---|---|
href |
URL to the social profile |
icon |
Icon name. Available: x, linkedin, facebook, instagram, youtube, xing, pinterest, github, gitlab |
labels
| Key | Description | Default |
|---|---|---|
title |
Radar title shown in the header and page titles | "Technology Radar" |
tagline |
Shared subtitle used in the default Open Graph image | "Track what to adopt, trial, assess, and hold." |
imprint |
Label for the imprint link in the footer | "Legal Information" |
footer |
Text shown in the footer | "Based on the open-source Technology Radar by AOE GmbH, extensively modified by Porsche Digital." |
notUpdated |
Warning shown on items not updated in the last 3 releases | "This item was not updated in last three versions of the Radar." |
hiddenFromRadar |
Info shown on items hidden from the radar chart | "This technology is currently hidden from the radar chart." |
searchPlaceholder |
Placeholder text in the search input | "What are you looking for?" |
metaDescription |
HTML meta description for SEO | "" |
Complete config.json for a fictional company
{
"basePath": "/techradar",
"baseUrl": "https://techradar.acme.io",
"editUrl": "https://github.dev/acme/techradar/blob/main/radar/{release}/{id}.md",
"headerLogoFile": "/images/acme-logo.svg",
"footerLogoFile": "/images/acme-wordmark.svg",
"backgroundImage": "/images/bg-pattern.png",
"backgroundOpacity": 0.04,
"imprint": "https://acme.io/legal",
"toggles": {
"showSearch": true,
"showChart": true,
"showTagFilter": true,
"showTeamFilter": false,
"showBlipChange": true,
"multiSelectFilters": true
},
"colors": {
"foreground": "#F0F0F5",
"background": "#1A1A2E",
"highlight": "#E94560",
"content": "#A0A0B0",
"text": "#707080",
"link": "#E94560",
"border": "#2A2A40",
"tag": "#2A2A40"
},
"segments": [
{
"id": "languages-and-frameworks",
"title": "Languages & Frameworks",
"description": "Programming languages and application frameworks used across our stack.",
"color": "#0F9D58"
},
{
"id": "infrastructure",
"title": "Infrastructure",
"description": "Cloud platforms, orchestration, and infrastructure-as-code tools.",
"color": "#4285F4"
},
{
"id": "data-and-ai",
"title": "Data & AI",
"description": "Data pipelines, storage, analytics, and machine learning frameworks.",
"color": "#F4B400"
},
{
"id": "developer-experience",
"title": "Developer Experience",
"description": "Tools and practices that improve developer productivity and satisfaction.",
"color": "#DB4437"
}
],
"rings": [
{
"id": "adopt",
"title": "Adopt",
"description": "Proven in production. Use by default for new projects.",
"color": "#0F9D58",
"radius": 0.5,
"strokeWidth": 5
},
{
"id": "trial",
"title": "Trial",
"description": "Worth pursuing. Use in non-critical projects to build experience.",
"color": "#4285F4",
"radius": 0.69,
"strokeWidth": 3
},
{
"id": "assess",
"title": "Assess",
"description": "Interesting. Explore in spikes or proof-of-concepts.",
"color": "#F4B400",
"radius": 0.85,
"strokeWidth": 2
},
{
"id": "hold",
"title": "Hold",
"description": "Do not start new work with this. Migrate away when practical.",
"color": "#DB4437",
"radius": 1,
"strokeWidth": 0.75
}
],
"flags": {
"new": { "title": "New" },
"changed": { "title": "Changed" },
"default": { "title": "Unchanged" }
},
"chart": {
"size": 900,
"blipSize": 14
},
"social": [
{ "href": "https://github.com/acme", "icon": "github" },
{ "href": "https://linkedin.com/company/acme", "icon": "linkedin" }
],
"labels": {
"title": "ACME Tech Radar",
"tagline": "Track what to adopt, trial, assess, and hold.",
"imprint": "Legal Notice",
"footer": "Built with the Porsche Digital Technology Radar.",
"notUpdated": "This item has not been reviewed in the last three releases.",
"hiddenFromRadar": "This technology is hidden from the radar chart.",
"searchPlaceholder": "Search technologies…",
"metaDescription": "ACME's technology radar — tracking what we adopt, trial, assess, and hold."
}
}Radar items are Markdown files organized by release date under radar/.
radar/
├── 2024-06-01/
│ ├── react.md
│ └── kubernetes.md
└── 2025-01-15/
├── react.md
└── deno.md
Each file has a YAML front-matter header followed by Markdown content:
---
title: "React"
ring: adopt
segment: languages-and-frameworks
tags:
- frontend
- javascript
teams:
- web-platform
- mobile
links:
- url: https://react.dev
name: Official Docs
- url: https://github.com/facebook/react
---
Description of the technology, why it was adopted, and any relevant context.
Supports full **Markdown** formatting.| Attribute | Required | Description |
|---|---|---|
title |
Yes | Name of the technology |
ring |
Yes | Ring placement. Must match one of the id values in config.rings. |
segment |
Yes | Segment assignment. Must match one of the id values in config.segments. |
summary |
No | Custom summary used for meta descriptions and link previews. Falls back to the first 160 characters of the item body. |
ogImage |
No | Custom Open Graph image. Use a relative path under public/ (for example /images/react-card.png) or a full https://... URL. |
tags |
No | List of tags for filtering. |
teams |
No | List of teams currently using this technology. |
links |
No | List of external links. Each entry has a url (required) and optional name. Shown on the detail page. |
featured |
No | Set to false to hide from the radar chart while keeping the item in the overview. Defaults to true. |
The filename (without .md) serves as the item identifier. When the same filename appears in a newer release folder, the newer entry overwrites the previous one — attributes are merged and a new history entry is created.
Place images in public/images/ and reference them in Markdown:
The build generates rich Open Graph / Twitter Card images for link previews.
pnpm run build:ogcreates a shared default card atpublic/og/default.png.- Every item detail page also gets a deterministic 1200×630 PNG at
public/og/<segment>/<id>.png. - Generation is content-hash cached, so unchanged cards are skipped on later builds.
To override the generated image for a single item, set ogImage in front-matter:
ogImage: /images/custom-card.pngRelative paths must point to an existing asset under public/. You can also use a full external URL:
ogImage: https://cdn.example.com/cards/react.pngWhen ogImage is omitted, the generator builds the per-item card automatically. When summary is omitted, the site derives the preview text from the rendered item body.
Use wiki-link syntax to link between radar items. The build resolves each link to the correct URL based on the item's segment:
We use [[typescript]] alongside [[react]] for our frontend stack.
See also [[kubernetes|our K8s setup]] for deployment details.| Syntax | Rendered as |
|---|---|
[[item-id]] |
Link using the item's title as label |
[[item-id|custom label]] |
Link using a custom label |
The item-id is the Markdown filename without the .md extension (e.g., typescript.md → typescript).
Unresolved wiki-links (referencing a non-existent item) are rendered as plain text with a build warning.
Warning
In strict mode (--strict), unresolved wiki-links cause the build to fail.
To work on the radar generator itself:
git clone https://github.com/porscheofficial/porschedigital-technology-radar.git
cd porschedigital-technology-radar
pnpm install # Also runs postinstall → build:icons
pnpm run build:data # Parse Markdown files into data/data.json
pnpm run dev # Start Next.js dev serverThe build pipeline:
build:icons— generates React icon components from SVGs insrc/icons/build:data— parsesradar/Markdown files intodata/data.jsonanddata/about.jsonbuild:og— generates cached Open Graph PNGs inpublic/og/next build— builds the static site intoout/
The pnpm run build command runs all three steps in sequence.
This repository runs two local pre-commit checks through Husky:
lint-staged→biome check --write --no-errors-on-unmatchedfor staged filespnpm run precommit:secrets→ staged-content secret scanning via TruffleHog
The secret scan reads the staged blob content, not the working tree, so it
still catches leaks correctly when you used partial staging such as
git add -p.
trufflehog is optional for local development. If the binary is missing, the
hook prints a warning and exits successfully so contributors in fresh
environments are not blocked.
Install it locally with Homebrew:
brew install trufflehogIf you absolutely must bypass both pre-commit hooks in an emergency, Git still supports:
git commit --no-verifyThat bypass is discouraged; the normal path is to fix the formatting issue or remove the secret from the staged content before committing.
Pass --strict to turn warnings into errors during the data build step.
Consumer projects (using the CLI):
npx techradar --strict build
npx techradar --strict devThis repository (development):
pnpm run build:data --strictIn strict mode, the build fails on:
- Invalid frontmatter (missing or invalid
ring,segment, etc.) - Unresolved wiki-links (e.g.,
[[nonexistent-item]])
This is recommended for CI pipelines to catch issues before deployment.
Tip
Add npx techradar --strict build to your CI pipeline to catch frontmatter issues and broken wiki-links before deployment.
You can add custom SCSS rules in custom.scss.
Note
The project uses CSS Modules with hashed class names. Use element or attribute selectors to target components.
/* Example: change headline fonts */
h1,
h2,
h3 {
font-family: "Times New Roman", Times, serif;
}Changes to custom.scss are picked up automatically in dev mode (with file watching).
This project is open source under the Apache License 2.0.
Originally based on the AOE Technology Radar. Maintained and developed by Porsche Digital.




