← Back to Blog

January 2025 Devlog

January 31, 2025
devlognextjsfhir
Next.js migration and FHIR R4 subscription resources — code snippets and architecture overview

What I've Been Working On

January was a productive month. Between client work and some personal projects, I finally got around to something I've been putting off for a while: migrating this portfolio off a single index.html file and into a proper Next.js 14 app.

Migrating to Next.js

The original site was a static HTML file with Tailwind loaded via CDN — perfectly functional, but not exactly a great showcase for someone who builds production web apps for a living. The migration involved:

  • Scaffolding a Next.js 14 project with the App Router and TypeScript
  • Extracting all the hardcoded content into typed data files under src/lib/data/
  • Breaking the monolithic HTML into composable Server Components
  • Replacing CDN Tailwind with a proper tailwind.config.ts setup including the typography plugin

The App Router's server-first model is a good fit here since there's no dynamic data — everything is static and can be rendered at build time.

Setting Up MDX Devlogs

With the Next.js foundation in place, I added an MDX-powered blog pipeline. Posts live as .mdx files in src/content/blog/, parsed at build time using gray-matter and rendered with next-mdx-remote/rsc.

// src/lib/blog.ts
export function getPostBySlug(slug: string): BlogPost {
  const filePath = path.join(CONTENT_DIR, `${slug}.mdx`);
  const raw = fs.readFileSync(filePath, "utf-8");
  const { data, content } = matter(raw);
  return { slug, content, ...(data as Omit<BlogPost, "slug" | "content">) };
}

Static params are generated via generateStaticParams(), so every post gets its own pre-rendered route at /blog/[slug].

FHIR R4 Subscription Resources

On the healthcare side, I've been digging into FHIR R4 Subscription resources for a client project. The R4 model uses a topic-based push pattern where a server notifies subscribers when matching resources change. A few things worth noting:

  • The Subscription.criteria field in R4 is a FHIRPath expression, giving you fine-grained control over what triggers a notification
  • Notification channels include rest-hook, websocket, and emailrest-hook is the most common in production
  • R4B and R5 introduced SubscriptionTopic as a first-class resource, which makes the intent much clearer than the R4 string-based criteria

Still working through the backpressure and retry semantics on the receiving end. More on that next month.


That's the January wrap-up. The portfolio is live and the devlog pipeline is working — you're reading the proof.