Skip to content

Commit 5e98645

Browse files
Codestzclaude
andcommitted
feat: add 3 new blog posts and Callout/ProcessFlow MDX components
Add blog posts for MCPX (CLI vs MCP), SPARC methodology, and Tessl spec-driven development. Create Callout and ProcessFlow MDX components following the Neo-Brutalist design system. Update featured posts to highlight the new content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 77d04ea commit 5e98645

15 files changed

Lines changed: 1176 additions & 4 deletions

mdx-components.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
FileTree,
88
TokenComparison,
99
ToolCall,
10+
Callout,
11+
ProcessFlow,
1012
} from '@/components/mdx';
1113
import { Mermaid } from '@/components/mdx/Mermaid';
1214

@@ -26,6 +28,8 @@ export const mdxComponents: MDXComponents = {
2628
FileTree,
2729
TokenComparison,
2830
ToolCall,
31+
Callout,
32+
ProcessFlow,
2933
// Headings
3034
h1: ({ children }) => (
3135
<h1 className="mb-4 sm:mb-6 mt-6 sm:mt-8 font-heading text-3xl sm:text-4xl font-bold uppercase text-foreground">
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use client';
2+
3+
import { Quote, Info, AlertTriangle, Lightbulb } from 'lucide-react';
4+
import { cn } from '@/lib/utils';
5+
import type { CalloutProps } from './Callout.types';
6+
7+
const typeConfig = {
8+
quote: { icon: Quote, label: 'Quote' },
9+
info: { icon: Info, label: 'Info' },
10+
warning: { icon: AlertTriangle, label: 'Warning' },
11+
tip: { icon: Lightbulb, label: 'Tip' },
12+
};
13+
14+
/**
15+
* Callout Component - Styled Quote/Info Box
16+
* Neo-Brutalist callout with secondary-colored header
17+
* Uses bg-elevated for content, secondary for accents
18+
* Supports author attribution for quote type
19+
*/
20+
export function Callout({ children, author, role, type = 'quote', className }: CalloutProps) {
21+
const config = typeConfig[type];
22+
const IconComponent = config.icon;
23+
24+
return (
25+
<div
26+
className={cn(
27+
'my-8 overflow-hidden rounded-none border-[4px] border-foreground bg-bg-elevated shadow-[8px_8px_0px_0px] shadow-black',
28+
className
29+
)}
30+
>
31+
{/* Header bar */}
32+
<div className="flex items-center gap-2 px-4 py-2 border-b-[4px] border-foreground bg-secondary">
33+
<IconComponent size={14} className="text-secondary-text" strokeWidth={3} />
34+
<span className="font-mono text-[10px] font-bold uppercase tracking-widest text-secondary-text">
35+
{config.label}
36+
</span>
37+
</div>
38+
39+
{/* Content */}
40+
<div className="border-l-[6px] border-l-secondary p-4 sm:p-6">
41+
<p className="text-sm sm:text-base leading-relaxed text-foreground italic">
42+
&ldquo;{children}&rdquo;
43+
</p>
44+
45+
{author && (
46+
<div className="mt-4 flex items-center gap-3 border-t-[2px] border-foreground pt-3">
47+
<div className="h-8 w-8 flex items-center justify-center border-[2px] border-foreground bg-secondary font-mono text-xs font-black text-secondary-text">
48+
{author.charAt(0).toUpperCase()}
49+
</div>
50+
<div>
51+
<span className="font-mono text-xs font-bold uppercase tracking-wider text-foreground block">
52+
{author}
53+
</span>
54+
{role && (
55+
<span className="font-mono text-[10px] text-muted uppercase tracking-wider">
56+
{role}
57+
</span>
58+
)}
59+
</div>
60+
</div>
61+
)}
62+
</div>
63+
</div>
64+
);
65+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface CalloutProps {
2+
children: string;
3+
author?: string;
4+
role?: string;
5+
type?: 'quote' | 'info' | 'warning' | 'tip';
6+
className?: string;
7+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { Callout } from './Callout';
2+
export type { CalloutProps } from './Callout.types';
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use client';
2+
3+
import { ArrowDown } from 'lucide-react';
4+
import { cn } from '@/lib/utils';
5+
import type { ProcessFlowProps } from './ProcessFlow.types';
6+
7+
/**
8+
* ProcessFlow Component - Visual Step-by-Step Phases
9+
* Neo-Brutalist numbered flow for showing methodologies and workflows
10+
* Uses card pattern with secondary-colored header, thick borders, offset shadow
11+
*/
12+
export function ProcessFlow({ title, steps, className }: ProcessFlowProps) {
13+
return (
14+
<div
15+
className={cn(
16+
'my-8 overflow-hidden rounded-none border-[4px] border-foreground bg-bg-elevated shadow-[8px_8px_0px_0px] shadow-black',
17+
className
18+
)}
19+
>
20+
{/* Header */}
21+
{title && (
22+
<div className="border-b-[4px] border-foreground bg-secondary px-4 py-2">
23+
<span className="font-mono text-[10px] font-bold text-secondary-text uppercase tracking-widest">
24+
{title}
25+
</span>
26+
</div>
27+
)}
28+
29+
{/* Steps */}
30+
<div className="p-4 sm:p-6 space-y-0">
31+
{steps.map((step, index) => (
32+
<div key={index}>
33+
<div className="flex items-start gap-4">
34+
{/* Step number badge */}
35+
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center border-[3px] border-foreground bg-secondary font-mono text-base font-black text-secondary-text">
36+
{index + 1}
37+
</div>
38+
39+
{/* Step content */}
40+
<div className="flex-1 min-w-0 pt-1">
41+
<h4 className="font-mono text-sm sm:text-base font-bold uppercase tracking-wide text-foreground">
42+
{step.icon && <span className="mr-2">{step.icon}</span>}
43+
{step.title}
44+
</h4>
45+
<p className="mt-1 text-xs sm:text-sm leading-relaxed text-muted">
46+
{step.description}
47+
</p>
48+
</div>
49+
</div>
50+
51+
{/* Connector */}
52+
{index < steps.length - 1 && (
53+
<div className="flex items-center justify-start pl-[18px] py-2">
54+
<ArrowDown size={16} className="text-muted" strokeWidth={3} />
55+
</div>
56+
)}
57+
</div>
58+
))}
59+
</div>
60+
</div>
61+
);
62+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface ProcessStep {
2+
title: string;
3+
description: string;
4+
icon?: string;
5+
}
6+
7+
export interface ProcessFlowProps {
8+
title?: string;
9+
steps: ProcessStep[];
10+
className?: string;
11+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { ProcessFlow } from './ProcessFlow';
2+
export type { ProcessFlowProps, ProcessStep } from './ProcessFlow.types';

src/components/mdx/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ export { TokenComparison } from './TokenComparison';
1414
export type { TokenComparisonProps, TokenApproach, TokenStep } from './TokenComparison';
1515
export { ToolCall } from './ToolCall';
1616
export type { ToolCallProps, ToolCallResult } from './ToolCall';
17+
export { Callout } from './Callout';
18+
export type { CalloutProps } from './Callout';
19+
export { ProcessFlow } from './ProcessFlow';
20+
export type { ProcessFlowProps, ProcessStep } from './ProcessFlow';

src/content/blog/building-portfolio-with-ai.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: 'How I leveraged Claude Code, Gemini, and AI-driven development to
44
publishedAt: '2026-02-08'
55
category: 'ai'
66
tags: ['ai', 'claude', 'gemini', 'portfolio', 'nextjs', 'development-workflow']
7-
featured: true
7+
featured: false
88
type: 'experiment'
99
author: 'Esteban Estrada'
1010
thumbnail: '/images/blog/portfolio-blog.png'

0 commit comments

Comments
 (0)