Building This Blog with Kobweb: A Complete Technical Journey
Having a technical blog where I can share all the development related experiences & experiments was a long overdue. Even though I was familiar with Javascript frameworks that are available(and are widely used), I was somehow reluctant to build my blog with it. Then came Kobweb. By default, Kobweb will build a blog like https://bitspittle.github.io/kobweb-ghp-demo. I needed some improvement to match my design taste.
This post chronicles the complete technical journey of creating a modern, professional blog using Kobweb - from the initial setup to advanced features like syntax highlighting and dynamic content generation.
Why Kobweb?
As a Kotlin developer who loves Compose, Kobweb felt like a natural choice for building a technical blog. The promise of using familiar Kotlin syntax with Compose-like APIs for web development was too compelling to ignore. Plus, the ability to write blog posts in Markdown while having full programmatic control over the presentation was exactly what I needed.
Phase 1: Foundation Setup
Creating the Initial Project
The journey began with creating a new Kobweb project:
However, the initial setup wasn't smooth sailing. The newly generated project came with some version compatibility issues that needed immediate attention.
Version Compatibility Issues
The generated project used the latest versions of Kobweb and Kotlin, which had some compatibility issues. Here's what I had to downgrade:
The key lesson here: sometimes the bleeding edge isn't worth the pain. Stick with stable, well-tested versions for production projects.
Adding Markdown Support
The next step was enabling markdown(if not enabled already) support for blog posts:
This configuration tells Kobweb to look for markdown files in src/jsMain/resources/markdown/
and automatically generate routes for them.
Phase 2: Dynamic Blog System
One of my primary goals was to eliminate hardcoded blog entries. I wanted the home page to automatically discover and list all blog posts from markdown files.
Auto-Discovery of Blog Posts
The breakthrough came with understanding how Kobweb's markdown integration works. Here's the solution I implemented:
The magic happens in GeneratedBlogData.entries
, which is auto-generated from the markdown files using a custom Gradle task:
This approach means I can simply drop a new markdown file into the markdown/
directory, and it automatically appears on the home page. No hardcoding required!
Phase 3: Professional Code Highlighting
As a technical blog, proper syntax highlighting was non-negotiable. This turned out to be one of the most challenging aspects of the project.
The highlight.js Experiment
My first attempt used highlight.js:
Problems encountered:
- Race conditions with language loading
- Inconsistent
.kts
file highlighting - Complex language registration process
- Theme switching difficulties
The Prism.js Solution
After fighting with highlight.js, I switched to Prism.js with much better results:
Key improvements with Prism.js:
- Reliable autoloader plugin
- Better
.kts
file support (mapped to Kotlin) - Smoother theme switching
- More consistent highlighting results
Phase 4: Advanced UX Features
Interactive Code Blocks
The final version of the code blocks includes several UX enhancements:
Typography and Font Loading
Getting the typography right was crucial for a professional feel:
Typography Strategy:
- Code: JetBrains Mono (professional, readable)
- UI Elements: System fonts (SF Pro, Segoe UI, etc.)
- Body Text: System UI fonts for optimal readability
- Fallback Chain: Comprehensive fallbacks for all font categories
Phase 5: Social Features and Polish
Social Icons Component
No modern blog is complete without social links. I created a reusable social icons component:
Theme System
The blog supports both light and dark themes with smooth transitions:
The theme preference is persisted to localStorage and automatically restored on subsequent visits.
Major Challenges and Solutions
1. Kotlin Script (.kts) Highlighting
Problem: Despite loading kotlin.min.js, .kts
files showed as plain text.
Solution: Switched to Prism.js and ensured proper language mapping:
2. Filename Tab Clipping
Problem: The filename tabs were getting clipped by the code container's overflow: hidden
.
Solution: Position the filename tab outside the main container:
3. Theme Switching Race Conditions
Problem: Code highlighting themes weren't switching properly between light/dark modes.
Solution: Proper cleanup and sequential loading:
4. Horizontal Rule Styling
Problem: Markdown horizontal rules (---
) had unwanted padding that created excessive spacing.
Solution: Added custom CSS styling for hr
elements:
Performance Optimizations
Font Loading Strategy
- Preload: Critical fonts loaded with
rel="preload"
- Font Display: Using
font-display: swap
for graceful fallbacks - System Fonts: Leveraging system fonts for UI elements reduces load time
Code Highlighting
- Lazy Loading: Prism.js autoloader only loads required language modules
- Theme Caching: Prevent duplicate theme loading with proper cleanup
- Minimal Bundle: Only essential Prism.js components are loaded
Build Optimizations
Deployment with GitHub Actions
The blog is automatically deployed to GitHub Pages using a custom workflow: (following contents are taken from https://github.com/bitspittle/kobweb-ghp-demo/tree/main/.github/workflows)
Final Feature Set
✅ Core Blog Features
- Auto-generated blog post listing from markdown files
- Dynamic routing for blog posts
- Frontmatter support (title, description, date, tags)
- SEO-friendly URLs
- Responsive design
✅ Professional Code Blocks
- Syntax highlighting for 10+ languages including Kotlin Script
- Filename tabs with elegant positioning
- Interactive copy buttons with visual feedback
- Light/dark theme support
- Hover effects and smooth animations
- JetBrains Mono font for code, system fonts for UI
✅ Technical Infrastructure
- Prism.js integration with autoloader
- Dynamic theme switching with localStorage persistence
- Professional typography system
- Optimized font loading strategy
- GitHub Actions deployment pipeline
- Component-based architecture
Lessons Learned
1. Library Selection Matters
The switch from highlight.js to Prism.js was a game-changer. Sometimes the more popular option isn't necessarily the better fit for your specific use case.
2. CSS Positioning Can Be Tricky
Understanding the interaction between position: absolute
, overflow: hidden
, and container hierarchies is crucial for complex layouts like the filename tabs.
3. Font Loading Strategy is Critical
A multi-pronged approach (preload + stylesheet + CSS fallbacks) ensures the best user experience across different browsers and connection speeds.
4. Kobweb's Power Lies in Integration
The seamless integration between Kotlin code, Compose-like APIs, and web technologies makes Kobweb a powerful choice for developers already in the Kotlin ecosystem.
What's Next?
This blog setup is now production-ready and highly maintainable. Some potential future enhancements:
- Search functionality using client-side indexing
- Tag-based filtering for blog posts
- RSS feed generation for subscribers
- Comments system integration
- Performance analytics and monitoring
- Testing other markdown features like tables, footnotes, math expressions, and embedded media to ensure comprehensive markdown support
Acknowledgments
This project wouldn't have been possible without the incredible work of the Kobweb team and the broader Kotlin community. Special thanks to:
- Kobweb Framework - For creating such an elegant bridge between Kotlin and web development
- bitspittle's demo repository - For providing excellent examples and inspiration for structuring a Kobweb project
- The Kotlin and Compose teams for the underlying technology that makes this all possible
Conclusion
Building this blog with Kobweb has been an incredibly rewarding experience. Despite some initial challenges with version compatibility and code highlighting, the final result is a professional, performant, and maintainable blogging platform.
The combination of Kotlin's type safety, Compose's declarative UI paradigm, and web technologies creates a powerful development experience. For Kotlin developers looking to build web applications, Kobweb offers a compelling alternative to traditional JavaScript frameworks.
The source code for this blog is available on GitHub, and I encourage you to explore it, learn from it, and build upon it.
Happy blogging! 🚀
This blog post itself is written in Markdown and automatically rendered using the very system it describes. Meta? Absolutely. Cool? I think so.