Skip to content

porscheofficial/porschedigital-technology-radar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,141 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Porsche Digital Technology Radar

GitHub Pages Deploy npm version npm downloads TypeScript Next.js OpenSSF Scorecard CodeQL Conventional Commits License

A static site generator for building and publishing your own Technology Radar.

🔗 Live Showcase

Screenshot of the Technology Radar

Table of Contents

About · Why a Technology Radar? · Features · Screenshots · Quick Start · Project Structure · Configuration · Radar Items · Development · Custom Styling · License

📖 About

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.

💡 Why a Technology Radar?

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.

✨ Features

  • 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

📸 Screenshots

Segment Detail

Drill into a single segment with a zoomed mini-radar and a grouped technology list.

Segment detail page

Technology Detail

Each technology has its own page with ring status, description, tags, teams, and full revision history.

Technology detail page

History & Changelog

Track how technology assessments evolved across releases with the trajectory matrix.

History page

Mobile

Fully responsive — works on phones and tablets out of the box.

Mobile view

🚀 Quick Start

Important

Prerequisites: Node.js 22+

1. Create a new project

mkdir my-technology-radar && cd my-technology-radar
npm init -y

2. Install the radar as a dependency

npm install @porscheofficial/porschedigital-technology-radar

3. Initialize the project

Scaffolds starter files (radar/, config.json, about.md, public/, custom.scss, .gitignore) into your directory:

npx techradar init

4. Customize

Edit 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 page
  • public/ — favicon, images, background image
  • custom.scss — optional style overrides

5. Run

npx techradar dev     # Start dev server with file watching
npx techradar build   # Build static site → build/
npx techradar serve   # Start dev server without file watching

6. Deploy

After npx techradar build, the static site is in build/. Deploy it to GitHub Pages, Vercel, Netlify, or any static hosting provider.

📁 Project Structure (consumer)

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.

⚙️ Configuration

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.

Backward compatibility

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 ""

Full example

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

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.

Front-matter attributes

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.

Versioning

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.

Images

Place images in public/images/ and reference them in Markdown:

![Architecture diagram](/images/architecture.png)

Open Graph images

The build generates rich Open Graph / Twitter Card images for link previews.

  • pnpm run build:og creates a shared default card at public/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.png

Relative paths must point to an existing asset under public/. You can also use a full external URL:

ogImage: https://cdn.example.com/cards/react.png

When 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.

Cross-linking blips

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.mdtypescript).

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.

🛠️ Development (contributing to the generator)

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 server

The build pipeline:

  1. build:icons — generates React icon components from SVGs in src/icons/
  2. build:data — parses radar/ Markdown files into data/data.json and data/about.json
  3. build:og — generates cached Open Graph PNGs in public/og/
  4. next build — builds the static site into out/

The pnpm run build command runs all three steps in sequence.

Pre-commit hooks

This repository runs two local pre-commit checks through Husky:

  • lint-stagedbiome check --write --no-errors-on-unmatched for staged files
  • pnpm 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 trufflehog

If you absolutely must bypass both pre-commit hooks in an emergency, Git still supports:

git commit --no-verify

That bypass is discouraged; the normal path is to fix the formatting issue or remove the secret from the staged content before committing.

Strict mode

Pass --strict to turn warnings into errors during the data build step.

Consumer projects (using the CLI):

npx techradar --strict build
npx techradar --strict dev

This repository (development):

pnpm run build:data --strict

In 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.

🎨 Custom Styling

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).

📄 License

This project is open source under the Apache License 2.0.

Originally based on the AOE Technology Radar. Maintained and developed by Porsche Digital.

About

A static Technology Radar generator by Porsche Digital — visualize, track, and share technology decisions across your organization.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors