I tried a few blogging platforms before building this one. I started with Hashnode, but it feels like the project isnāt really maintained anymore. When I tried sharing posts, they wouldnāt fetch proper SEO data, which was pretty annoying. Mediumās markdown support is just⦠not great. Also considered dev.to but Iām not a fan of the interface, plus the overall quality of posts there isnāt really my vibe (not that mine are masterpieces, but you know what I mean). Iām actually not sure if I want to keep going here but just wanted to build something. So I built this one with Astro. Hereās how it works and why I made these choices.
System Overview
Letās start with the big picture, how this blog fits into the broader ecosystem:
graph LR
subgraph "External Actors"
Reader[Blog Reader]
Author[Content Author]
SearchEngine[Search Engines]
end
subgraph "Core System"
Blog[Threads of Thought Blog]
end
subgraph "External Systems"
GitHub[GitHub Repository]
GitHubPages[GitHub Pages]
Giscus[Giscus Comments]
GoogleFonts[Google Fonts]
RSS[RSS Readers]
end
Reader -->|Reads posts, searches content| Blog
Author -->|Writes markdown posts| GitHub
SearchEngine -->|Crawls for indexing| Blog
Blog -->|Deployed via CI/CD| GitHubPages
Blog -->|Comments integration| Giscus
Blog -->|Font loading| GoogleFonts
Blog -->|RSS feed| RSS
GitHub -->|Source code & content| Blog
Why Static Site Generation?
The biggest decision was going with Static Site Generation (SSG) instead of a traditional server or single-page app.
Why SSG?
Performance Benefits:
- Pre-built HTML files serve instantly from CDN (content delivery network - basically copies of your site stored worldwide for faster access)
- No server processing time (pages donāt need to be generated on-demand)
- Minimal JavaScript payload (less code to download)
- Excellent Core Web Vitals scores (Googleās performance metrics)
Security Advantages:
- No server-side attack surface
- No database vulnerabilities
- Content is immutable once deployed
Cost Efficiency:
- Free hosting on GitHub Pages
- No server maintenance
- Scales automatically with CDN (content gets served from servers close to your users)
Trade-offs:
- Build time increases with content volume
- Dynamic features require client-side implementation
- Content updates need full rebuilds
Technology Stack Architecture
graph TB
subgraph "Frontend Technologies"
HTML5[HTML5]
CSS3[Vanilla CSS]
VanillaJS[Vanilla JavaScript]
Shiki[Shiki<br/>Syntax Highlighting]
Lunr[Lunr.js<br/>Search Engine]
end
subgraph "Framework & Build"
Astro[Astro SSG<br/>v5.14.3]
Node[Node.js]
NPM[NPM Package Manager]
end
subgraph "Content & Data"
Markdown[Markdown Files]
YAML[YAML Frontmatter]
JSON[JSON Data Files]
end
subgraph "External Services"
GitHubPages[GitHub Pages<br/>Hosting]
GitHubActions[GitHub Actions<br/>CI/CD]
Giscus[Giscus<br/>Comments]
GoogleFonts[Google Fonts<br/>Typography]
end
Astro --> HTML5
Astro --> CSS3
Astro --> VanillaJS
VanillaJS --> Shiki
VanillaJS --> Lunr
Markdown --> Astro
YAML --> Astro
JSON --> Lunr
Node --> Astro
NPM --> Node
GitHubActions --> GitHubPages
Why Astro?
I actually discovered Astro when I saw another blog mention it was āBuilt with Astroā in the footer. The site was fast and clean, so I decided to check it out. After looking at a bunch of options, I settled on Astro:
What I liked about Astro:
- Zero JavaScript by default, pages are just HTML unless you add JS
- You can use any framework you want (React, Vue, Svelte) or none at all
- Fast builds and great performance
- Simple to get started, no complex configuration needed
vs Next.js:
- Way simpler for static content (no getStaticProps/getStaticPaths boilerplate for every page)
- Better performance for blogs (Next.js ships React runtime even for static content)
- Less configuration overhead (Next.js has tons of options for rendering modes, caching, etc.)
vs Gatsby:
- Builds are actually fast (Gatsbyās builds can take forever with lots of content)
- No GraphQL layer to learn (Gatsby forces you to query everything through GraphQL, even simple data)
- Simpler mental model (no complex plugin ecosystem to navigate)
vs Hugo:
- I know Go much better than JavaScript, but for front-end templating Iām more familiar with JavaScript patterns than Go templates (even though Iād probably pick up Hugoās templating quickly)
- Astroās component syntax feels more familiar coming from a programming background
- Better integration with modern JavaScript libraries and tools
Trade-offs:
- Smaller ecosystem than Next.js
- Less mature than Hugo
- Learning curve for Astro-specific concepts (frontmatter separation, file-based routing, static path generation)
Component Architecture
graph TB
subgraph "Web Application Components"
subgraph "Pages"
IndexPage[Index Page<br/>Homepage with post list]
BlogPost[Blog Post Page<br/>Individual post view]
SearchPage[Search Page<br/>Full-text search]
TagPages[Tag Pages<br/>Posts by tag]
DatePages[Date Pages<br/>Posts by date]
end
subgraph "Layouts"
BlogLayout[BlogPost Layout<br/>Post template]
end
subgraph "Components"
Header[Header Component<br/>Navigation & search]
Sidebar[Sidebar Component<br/>Calendar & tags]
Search[Search Component<br/>Lunr.js integration]
Comments[Comments Component<br/>Giscus integration]
end
subgraph "Utilities"
ReadingTime[Reading Time Calculator]
SearchIndexGen[Search Index Generator]
end
end
IndexPage --> Header
IndexPage --> Sidebar
BlogPost --> BlogLayout
BlogLayout --> Header
BlogLayout --> Sidebar
BlogLayout --> Comments
Header --> Search
SearchPage --> Search
Search --> SearchIndexGen
BlogLayout --> ReadingTime
How I Organized Things
Reusable Stuff:
- Header and Sidebar everywhere for consistency
- Search functionality shared across pages
- One BlogPost layout for all
Utilities:
- Reading time calculator (I really appreciate when this is at the top of any post I read)
- Search index generator (learned something by developing the blog, I had no idea you can do search without something like Elasticsearch⦠back-end dev problems)
- Keeping shared logic in one place
Data Flow Architecture
flowchart TD
subgraph "Content Creation"
A[Author writes Markdown] --> B[Git commit & push]
B --> C[GitHub Repository]
end
subgraph "Build Process"
C --> D[GitHub Actions Trigger]
D --> E[Astro Build Process]
E --> F[Process Markdown Files]
F --> G[Generate Static HTML]
F --> H[Create Search Index]
F --> I[Generate RSS Feed]
F --> J[Create Sitemap]
end
subgraph "Deployment"
G --> K[Deploy to GitHub Pages]
H --> K
I --> K
J --> K
end
subgraph "User Interaction"
K --> L[User visits site]
L --> M[Load static content]
M --> N[Client-side search]
M --> O[Interactive calendar]
M --> P[Comments loading]
end
H --> N
P --> Q[Giscus API]
The Content Pipeline
Markdown Everything:
- All posts are just Markdown files
- YAML frontmatter for the metadata
- Everything lives in Git
Why this works:
- I can write in any editor I want
- Content isnāt locked to any platform
- Easy to backup (itās just files!)
- Code blocks and formatting just work
The build process:
- Astro processes everything at build time
- Search index gets generated automatically
- RSS feed updates itself
- Sitemap gets created for SEO
The downside:
- No real-time updates (need to rebuild)
- Canāt do fancy dynamic stuff easily (but I also donāt do fancy soā¦)
Feature Architecture Deep Dives
Search System
flowchart LR
subgraph "Search Implementation"
A[Blog Posts] --> B[Build Time Processing]
B --> C[Generate search-index.json]
C --> D[Lunr.js Index Creation]
D --> E[Client-side Search]
E --> F[Dropdown Results]
E --> G[Search Page Results]
end
subgraph "Search Components"
H[Search Component] --> I[Search Input]
H --> J[Results Dropdown]
K[Search Page] --> L[Full Results Display]
end
D --> H
D --> K
Search Decisions:
Client-side with Lunr.js:
- No server needed
- Search is instant
- Works even offline
The trade-offs:
- Users download the search index (more bandwidth)
- Wonāt scale to huge sites (but I also will not write that much)
- No search analytics
- Pretty basic ranking
Free alternatives I considered:
- Basic text search: Too clunky (just matching exact words, no ranking, poor user experience)
- Simple grep-style filtering: Works but feels broken compared to real search
Calendar System
flowchart TD
A[Blog Posts with Dates] --> B[Extract Post Dates]
B --> C[Generate Calendar Grid]
C --> D[Mark Days with Posts]
D --> E[Interactive Calendar]
E --> F[Month Navigation]
E --> G[Year Navigation]
E --> H[Click to View Posts]
H --> I[Date-based Routing]
Calendar Decisions:
Made it interactive:
- JavaScript calendar with month/year navigation
- Allows month/year navigation
- Clickable dates link to posts
Implementation:
- Vanilla JavaScript (no framework dependency)
- Post dates extracted at build time, passed to client
- Fully client-side calendar generation (avoids build-time date issues)
- Calendar initializes with current date when page loads
Trade-offs:
- More complex than static calendar
- Requires JavaScript enabled
- Additional client-side code
- Slight delay on initial load while calendar generates
Comments System
flowchart TD
A[Blog Post Page] --> B[Comments Component]
B --> C[Giscus Integration]
C --> D[GitHub Discussions API]
D --> E[Load Comments]
E --> F[Display Comments]
F --> G[User Interaction]
G --> H[GitHub OAuth]
H --> I[Post Comments]
Comments Decisions:
Went with Giscus:
- Uses GitHub Discussions (free!)
- No extra accounts needed
- Taps into the GitHub community
- Good moderation built-in
vs Disqus:
- No privacy concerns or ads
- Cleaner integration
vs Self-hosted:
- Way less maintenance headache
The downside:
- Only GitHub users can comment
- Dependent on GitHub
- Limited customization
Deployment Pipeline
flowchart TD
A[Developer writes content] --> B[Git commit to main branch]
B --> C[GitHub webhook triggers]
C --> D[GitHub Actions workflow starts]
subgraph Build["Build Process"]
D --> E[Checkout code]
E --> F[Setup Node.js]
F --> G[Install dependencies]
G --> H[Run astro build]
H --> I[Generate static files]
end
subgraph Deploy["Deployment"]
I --> J[Deploy to GitHub Pages]
J --> K[Update DNS]
K --> L[Site live]
end
subgraph Verify["Verification"]
L --> M[Health checks]
M --> N[RSS feed updated]
M --> O[Search index updated]
M --> P[Sitemap updated]
end
Deployment Setup
GitHub Actions because:
- Works perfectly with GitHub Pages
- Free for public repos
- Simple YAML config
How it works:
- Push to main ā automatic deployment
- No manual steps needed
- Fast feedback when I mess something up
Nice things:
- Zero-downtime deployments
- Rolls back if build fails
- Everything is version controlled
Performance & Security Architecture
graph TB
subgraph Security["Security Measures"]
A[Static Site Generation<br/>No server vulnerabilities]
B[GitHub Pages HTTPS<br/>SSL/TLS encryption]
C[Content Security Policy<br/>XSS protection]
D[No sensitive data<br/>Client-side only]
end
subgraph Performance["Performance Optimizations"]
E[Pre-built static files<br/>Fast loading]
F[CDN delivery<br/>GitHub Pages CDN]
G[Optimized images<br/>Proper sizing]
H[Minimal JavaScript<br/>Vanilla JS only]
I[Font optimization<br/>Google Fonts preload]
end
subgraph Monitoring["Monitoring"]
J[GitHub Pages analytics]
K[RSS feed validation]
L[Search functionality testing]
end
Performance Stuff
Keep JavaScript minimal:
- Only load whatās actually needed
- Vanilla JS for simple things
- Make it work without JS first
Images:
- Proper sizing (no giant images)
- Lazy loading
- WebP when possible
Fonts:
- Google Fonts with preload
- Font-display: swap for faster loading
- Not too many font variations
Security
Static sites are pretty secure:
- No server code to exploit
- No database to hack
- Each deploy is immutable
Content Security Policy:
- Restrict where scripts can come from
- Prevent XSS
- Control external resources
What I Learned
Whatās Working Great
- Astroās performance - Zero JS by default is amazing
- Markdown workflow - Writing is smooth and content is portable
- GitHub integration - Write ā push ā deployed, no fuss
- Component reuse - Easy to maintain and update
What Could Be Better
My knowledge of front-end- Search limitations - Client-side search wonāt scale forever
- Build times - Will get slower as I write more
- Dynamic stuff - Limited options for real-time features
- Analytics - Pretty basic compared to server-side options
Future Plans
Might upgrade to:
- Astroās newer features (view transitions, content collections)
- Server-side search if this gets too slow
- Better analytics setup
Keeping an eye on:
- Build times as content grows
- Whether pagination needs improvement (currently shows 8 posts per page)
- CDN performance
Wrapping Up
This whole setup prioritizes simplicity and performance over fancy features. Astro gives me great performance and a nice developer experience, while keeping everything maintainable. Plus, since I already keep my notes in Obsidian as markdown files, the workflow feels natural, I can draft posts there and just copy them over.
The main thing I learned is that your architecture should match your actual needs. For a personal blog where I want to focus on writing and performance, this works really well. If I needed real-time features or complex user interactions, Iād probably make different choices.
The whole system is simple enough that I can actually understand it (as a backend dev whoād rather avoid frontend whenever possible), deploy with a git push, and it scales automatically without me having to babysit servers.
Comments