src/pages/blog/ and automatically indexed for the blog listing page.
MDX Configuration
The project uses@mdx-js/rollup with rehype-prism-plus for syntax highlighting:
vite.config.ts
rehype-prism-plus automatically handles code syntax highlighting using Prism themes. No additional configuration needed.
Blog Post Structure
All blog posts are MDX files located insrc/pages/blog/ with the following structure:
File Location
Frontmatter Format
Each MDX file starts with ameta export containing frontmatter:
recursion.mdx
Available Frontmatter Fields
Available Frontmatter Fields
- title (required): The post title displayed in listings and the post page
- date (optional): Display date in any format (e.g., “july 14, 2025”, “oct. 28, 2025”)
- description (optional): Meta description for SEO (defaults to “Read this blog post by Abenan.”)
- image (optional): Custom OG image path (defaults to
/og-main.png?v=2) - tags (optional): Array of tags for filtering (e.g.,
["technical"],["personal"]) - readingTime (optional): Manual override for reading time (auto-calculated if not provided)
Adding a New Blog Post
Regenerate reading times
Run the reading time calculation script:This updates
src/pages/blog/reading-times.json with calculated reading times for all posts.MDX Features
Code Highlighting
Code blocks are automatically highlighted usingrehype-prism-plus:
Markdown Features
All standard Markdown features are supported:- Bold text with
**text** - Italic text with
*text* - Links with
[text](url) - Inline code with
`code` - Lists (ordered and unordered)
- Blockquotes with
> - Headings with
#,##,###
Links Between Posts
Link to other blog posts using relative URLs:Reading Time Calculation
Reading times are automatically calculated byscripts/reading-times.mjs:
scripts/reading-times.mjs
Reading times are calculated at 200 words per minute and exclude code blocks and frontmatter.
Running the Script
The script is defined inpackage.json:
src/pages/blog/reading-times.json:
Blog Listing Page
The blog listing page (src/pages/blog/index.tsx) automatically displays all posts:
Features
- Automatic indexing: Posts are imported from
_index.tsusing Vite’simport.meta.glob - Date sorting: Posts are sorted by date (newest first)
- Tag filtering: Filter posts by tags using the tag buttons
- Reading time display: Shows reading time next to each post
Post Index System
Posts are automatically indexed insrc/pages/blog/_index.ts:
How Auto-Indexing Works
How Auto-Indexing Works
import.meta.globloads all.mdxfiles in the directory- Each file’s frontmatter is extracted from the
metaexport - The filename becomes the post slug
- Reading times are merged from
reading-times.json - Posts are exported as an array for the listing page
Dynamic Post Routing
Individual posts are rendered viasrc/pages/blog/[slug].tsx:
SEO Features
- Dynamic meta tags: Title and description from frontmatter
- Open Graph images: Custom or default OG images
- Canonical URLs: Proper canonical links for SEO
- Twitter Cards: Social media preview support
Comments with Giscus
Blog posts include a Giscus comment section powered by GitHub Discussions:Comments are loaded dynamically per post using the pathname mapping, ensuring each post has its own discussion thread.
Styling
Blog posts use Tailwind’s typography plugin (prose classes):
prose classes automatically style:
- Headings
- Paragraphs
- Lists
- Code blocks
- Links
- Blockquotes
Best Practices
Writing Guidelines
Writing Guidelines
- Keep titles lowercase: The portfolio uses a lowercase aesthetic (e.g., “my approach to solving recursive problems”)
- Use tags consistently: Stick to a few key tags like
["technical"],["personal"] - Date format: Use readable formats like “july 14, 2025” or “oct. 28, 2025”
- Code examples: Include practical, working code snippets
- Internal links: Link between related posts for better navigation
Performance Tips
Performance Tips
- Optimize images: Compress images before adding to blog posts
- Limit code blocks: Long code blocks increase reading time calculations
- Use lazy loading: Large images should use lazy loading attributes
- Regenerate reading times: Always run
npm run reading-timesafter content changes
Example Posts
The portfolio includes several example posts:- recursion.mdx: Technical post with code examples and references
- pub-sub.mdx: Short explainer with links to deeper content
- pub-sub-deeper-dive.mdx: In-depth tutorial with live examples
- oss.mdx: Personal reflection on open source
- navigating-the-tech-space-as-a-woman.mdx: Personal essay