Loading portfolio
All Work

Changelog UI

A static, editorial changelog interface for developer audiences: MDX release notes, URL-synced tag filters, an RSS feed, and keyboard nav.

Design + Build · SoloVisit live site
Backend
0
Sample entries
0
Tag types
0
Runtime deps
0
02(Context)

This changelog is a self-contained, reading-first surface for developers scanning for the one change that affects them: MDX-authored release notes, shareable tag-filtered views, an RSS feed, and keyboard navigation. Most changelogs are a plain markdown file or a CMS bolt-on; this one treats a changelog as editorial content that deserves real writing. Built to show design-to-code execution as a portfolio piece, not a real product.

03(Design)

Entries are typeset, not listed. A real type scale, generous measure, and rhythm make a release note read like a short article rather than a commit message. The system is three fonts on a warm near-black palette with an amber accent, and a highlighted release gets an amber left border and a larger timeline dot to mark a major version.

Filter state lives in the URL, not just in component state. A filtered view like ?tags=feature,fix is a shareable link, back and forward work, and the server re-renders from the URL so a direct load is always correct.

One tag config is the single source of truth. A tag's color, border, and label are defined once and reused by both the inline badges and the filter chips, so the visual language cannot drift between the two surfaces.

04(Engineering)

Next.js 14 App Router with TypeScript and Tailwind v4. The content source is a typed in-memory array of entries, each carrying a version, date, tags, a highlight flag, and a markdown body; there is no database. The root page is an async server component that reads the tags param, filters the array server-side, and hands the result to a client feed. Each body is rendered from markdown to HTML at request time through next-mdx-remote, with custom overrides for code blocks and links, and a single route handler emits an RSS 2.0 feed from the same array.

Source
Typed entries
Markdown bodies, no database
→
→
Render
RSC + MDX
Markdown to HTML, custom components
stack   Next.js · TypeScript · Tailwind · MDX (next-mdx-remote) · date-fns
05(Why end-to-end)
Because I owned both the type system and the MDX pipeline, I could override the element components so authored markdown renders straight into the design (letter-spaced section headers, code blocks wrapped in a hover copy button, external links that open safely), with no separate styling pass between writing a note and shipping it. The CMS bolt-on it is reacting against would have given non-developers a way in; a typed array in the repo means the only way to publish is a commit.
The case for one person, end to end
06(Outcome)

Public and live at changelog.javiertpadilla.com. Eight sample entries across five filterable tags, URL-synced shareable filters, an RSS 2.0 feed at /rss, MDX rendering with copy-enabled code blocks, and j/k keyboard navigation, all statically served with no backend.

0
Trackers
07(Key decisions)

Filter state lives in the URL

Chose
The tag filter serialised into the URL as ?tags=feature,fix, with the server re-reading that param and filtering before the feed renders.
Over
Holding the selected tags in component state, the default for a filter UI of this size.
Because
A filtered view is then a shareable link, back and forward behave, and a cold load of that URL is always correct.
Cost
Filtering stops being a local interaction. The root page has to be an async server component that reads the param and filters server-side before handing anything to the client feed, so the simplest possible state change now goes through the server.

Entries are a typed array, not a database

Chose
A typed in-memory array of entries carrying version, date, tags, highlight flag and markdown body, read by both the feed and the RSS route handler.
Over
A database or the CMS bolt-on most changelogs reach for.
Because
It keeps the whole surface statically served with no backend and the runtime dependency list at five.
Cost
Publishing is a code change. Nobody who cannot edit the source and redeploy can add an entry, which is a large part of why the eight entries that ship are sample content and why this is a portfolio piece rather than a real product.
08(What I'd do differently)

The subscribe form is honest fiction right now: it fakes a success toast and never sends the email, so I'd wire it to a real endpoint or relabel it as decorative before calling the demo done. The RSS feed also hardcodes the wrong base host, so its links point off-domain; that base URL wants to be one config value. The decision I'd keep is making the URL the single source of truth for filters, so every view is shareable and the back button just works.

Next project
PlotWise ↗
Product design · UI/UX / Next.js · TypeScript · Supabase
← Back to selected work