Blogo is a production-ready blog that demonstrates what you can build with hsx, a server-side JSX runtime for Deno. It proves you don't need React, Next.js, or any client-side framework to build fast, modern web applications.
See it live: blogo.timok.com
hsx is a server-side JSX runtime that gives you React's developer experience without shipping JavaScript to the browser. Write JSX components, get HTML strings. Zero client-side rendering. Zero hydration. Zero bundle.
// This is hsx, not React
const PostCard = ({ title, excerpt }: Props) => (
<article class="post-card">
<h2>{title}</h2>
<p>{excerpt}</p>
</article>
);
// Renders to pure HTML string on the server
const html = renderVNode(<PostCard title="Hello" excerpt="World" />);
// Output: <article class="post-card"><h2>Hello</h2><p>World</p></article>The browser receives HTML. Not JavaScript instructions to build HTML. Just HTML.
Modern web development has become absurdly complex. React alone ships ~40KB minified, and that's before your app code. Then you need a meta-framework for SSR, a bundler, a build step, hydration logic, and state management. For what? To render HTML.
hsx takes a different path:
- Zero client-side JavaScript for rendering - The browser receives HTML, ready to display
- Familiar JSX syntax - Write components exactly like React, minus useState/useEffect complexity
- Server-side composition - Components compose where your data lives
- Type safety - Full TypeScript support with proper JSX types
- HTMX synergy - Semantic aliases make HTMX feel native to JSX
Blogo demonstrates how hsx and HTMX work together. hsx renders the initial HTML, HTMX handles dynamic updates without page reloads:
// hsx provides semantic aliases for HTMX attributes
<a
href="/posts"
get="/posts" // Maps to hx-get
target="#content" // Maps to hx-target
swap="innerHTML" // Maps to hx-swap
pushUrl="true" // Maps to hx-push-url
>
Load Posts
</a>;The result feels like a SPA but works without JavaScript. Progressive enhancement, not progressive complexity.
Components return VNodes (virtual DOM nodes). The renderVNode() function
recursively converts them to HTML strings:
// Component tree
const Page = () => (
<Layout title="Home">
<PostList posts={posts} />
</Layout>
);
// Convert to HTML
const htmlString = renderVNode(<Page />);
// For pre-rendered HTML (like markdown), bypass escaping
import { html } from "./render-vnode.ts";
{
html(post.content);
} // Renders as-isThis blog showcases hsx capabilities in a real application:
- Server-side JSX components - Layout, PostView, PostList, TagCloud, SearchResults
- HTMX integration - SPA-like navigation without client-side routing
- Markdown rendering - Using
html()for safe raw HTML injection - Dynamic content - Search, filtering, pagination via HTMX partial updates
- Progressive enhancement - Works fully without JavaScript, enhanced with HTMX
- Markdown posts with YAML frontmatter
- Tag-based categorization and filtering
- Full-text search with modal and results page
- Light/dark theme toggle
- Syntax highlighting with Highlight.js
- Mermaid diagram support
- RSS feeds
- SEO optimization with structured data
- Deno v2.x or higher
# Clone and setup
git clone https://github.com/srdjan/blogo.git
cd blogo
deno task setup
# Start development server
deno task devOpen http://localhost:8000
deno task dev # Development server with hot reload
deno task start # Production server
deno task test # Run tests
deno task check # Type check
deno task fmt # Format code
deno task lint # Lint codesrc/
app/main.ts # Entry point
http/ # Routes, server, middleware
render-vnode.ts # hsx VNode to HTML renderer
components/ # JSX components (Layout, PostView, etc.)
domain/ # Business logic
ports/ # Dependency interfaces
lib/ # Core utilities (Result types, etc.)
content/posts/ # Markdown blog posts
public/ # Static assets
Add markdown files to content/posts/:
---
title: Your Post Title
date: 2025-01-15
tags: [Technology, Tutorial]
excerpt: Brief description
---
# Your Content
Write markdown here. Supports code blocks, Mermaid diagrams, images.Blogo deploys to Deno Deploy with zero configuration:
- Push to GitHub
- Connect repository at dash.deno.com
- Set entry point:
src/app/main.ts - Deploy
Every push to main triggers automatic deployment.
| Layer | Technology |
|---|---|
| Runtime | Deno v2.x |
| Rendering | hsx (server-side JSX) |
| Interactivity | HTMX v2.x |
| Styling | Modern CSS (nesting, container queries, logical properties) |
| Content | Markdown with marked |
| Syntax | Highlight.js |
| Diagrams | @rendermaid/core |
| Hosting | Deno Deploy |
Built with hsx by Claude, GPT, and Srdjan.
Fork it, deploy it, make it yours.
MIT
