import * as React from "react";
import { notFound } from "next/navigation";
import { blogPosts } from "../../../src/data/blogPosts";
import { Tag } from "../../../src/components/Tag";
import { CodeBlock } from "../../../src/components/ArticleBlockquote";
import { H2 } from "../../../src/components/ArticleHeading";
import {
Paragraph,
LeadParagraph,
} from "../../../src/components/ArticleParagraph";
import { UL, LI } from "../../../src/components/ArticleList";
import { FileExamplesList } from "../../../src/components/FileExamplesList";
import { FileExampleManager } from "../../../src/data/fileExamples";
import { BlogPostClient } from "../../../src/components/BlogPostClient";
import { PageHeader } from "../../../src/components/PageHeader";
import { Section } from "../../../src/components/Section";
export async function generateStaticParams() {
return blogPosts.map((post) => ({
slug: post.slug,
}));
}
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = blogPosts.find((p) => p.slug === slug);
if (!post) {
notFound();
}
const formattedDate = new Date(post.date).toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
});
const wordCount = post.description.split(/\s+/).length + 100;
const readingTime = Math.max(1, Math.ceil(wordCount / 200));
const showFileExamples = post.tags?.some((tag) =>
[
"architecture",
"design-patterns",
"system-design",
"docker",
"deployment",
].includes(tag),
);
// Load file examples for the post
let groups: any[] = [];
if (showFileExamples) {
const allGroups = await FileExampleManager.getAllGroups();
groups = allGroups
.map((group) => ({
...group,
files: group.files.filter((file) => {
if (file.postSlug !== slug) return false;
return true;
}),
}))
.filter((group) => group.files.length > 0);
}
return (
•{readingTime} min read
{post.tags && post.tags.length > 0 && (
{post.tags.map((tag, index) => (
))}
)}
{slug === "first-note" && (
<>
This blog is a public notebook. It's where I document things I
learn, problems I solve, and tools I test.
Why write in public?
I forget things. Writing them down helps. Making them public
helps me think more clearly and might help someone else.
What to expect
Short entries, usually under 500 words
Practical solutions to specific problems
Notes on tools and workflows
Mistakes and what I learned
>
)}
{slug === "debugging-tips" && (
<>
Sometimes the simplest debugging tool is the best one. Print
statements get a bad reputation, but they're often exactly
what you need.
Why print statements work
Debuggers are powerful, but they change how your code runs.
Print statements don't.
{`def process_data(data):
print(f"Processing {len(data)} items")
result = expensive_operation(data)
print(f"Operation result: {result}")
return result`}
Complete examples
Here are some practical file examples you can copy and
download. These include proper error handling and logging.
>
)}
{slug === "architecture-patterns" && (
<>
Good software architecture is about making the right decisions
early. Here are some patterns I've found useful in production
systems.
Repository Pattern
The repository pattern provides a clean separation between
your business logic and data access layer. It makes your code
more testable and maintainable.
Service Layer
Services orchestrate business logic and coordinate between
repositories and domain events. They keep your controllers
thin and your business rules organized.
Domain Events
Domain events help you decouple components and react to
changes in your system. They're essential for building
scalable, event-driven architectures.
Complete examples
These TypeScript examples demonstrate modern architecture
patterns for scalable applications. You can copy them directly
into your project.
>
)}
{slug === "docker-deployment" && (
<>
Docker has become the standard for containerizing
applications. Here's how to set up production-ready
deployments that are secure, efficient, and maintainable.
Multi-stage builds
Multi-stage builds keep your production images small and
secure by separating build and runtime environments. This
reduces attack surface and speeds up deployments.
Health checks and monitoring
Proper health checks ensure your containers are running
correctly. Combined with restart policies, this gives you
resilient, self-healing deployments.
Orchestration with Docker Compose
Docker Compose makes it easy to manage multi-service
applications in development and production. Define services,
networks, and volumes in a single file.
Complete examples
These Docker configurations are production-ready. Use them as
a starting point for your own deployments.