
This Website
Building my personal website and blog using Deno and Fresh. A reflection on the potential, the learning curve, and the rewarding outcome.
Tech Stack
The Project: This Website
This project entry describes the creation of the very website you're currently browsing. As a developer keen on exploring modern web technologies, I decided to build my personal website, blog, and portfolio platform using the Deno runtime and the Fresh web framework.
Motivation: Betting on Potential
Why Deno and Fresh? I was drawn to their potential and core philosophies:
- Deno's Simplicity: A secure runtime with web standards baked in, TypeScript as a first-class citizen, and an excellent set of integrated tools (formatter, linter, task runner).
- Fresh's Approach: The file-based routing felt intuitive, and the "Islands Architecture" promised performance by shipping minimal JavaScript to the client by default, only hydrating interactive components.
- TypeScript Focus: I enjoy working with TypeScript. Most of my work is typed unless I begrudgingly have to use Python 😄
I believed this stack could offer a productive and performant way to build modern web applications, and building my own site felt like the perfect way to dive deep and truly learn its ins and outs. This was a sizeable commitment because I've iterated on some version of my own website for years now without anything concrete. Also, it felt good learning something AI hadn't quite caught up to and couldn't easily replicate.
The Journey: Navigating New Waters
Building this site was a rewarding but definitely challenging experience. While the core Fresh patterns are indeed quite easy to grasp once you understand them, venturing beyond the basic examples required significant exploration and problem-solving.
Challenges Encountered:
- Finding Specific Examples: For certain features, like managing shared state across different interactive islands (solved using Preact Signals) or handling specific deployment configurations, I often found myself needing to piece together information from various sources or experiment extensively. The ecosystem, while growing, doesn't yet have the sheer volume of tutorials and Stack Overflow answers that older frameworks might.
- Configuration Nuances: Early on, I encountered issues with client-side code attempting to access Deno APIs which are server-only. Understanding this boundary and properly structuring configuration was a key learning. Deciphering error logs (or their absence) was sometimes misleading at best, and figuring out the correct error propagation chain took some debugging.
- Iteration: Features like the theme system required refinement. Moving from a mixed approach to a purely Tailwind-driven theme definition (
tailwind.config.ts
) ultimately provided much better consistency. Discovering@headlessui/react
later was helpful, though integrating it seamlessly with Preact via compatibility layers required careful setup indeno.json
.
What Worked Beautifully
Despite the challenges, many aspects of the Deno/Fresh stack shone brightly:
- File-Based Routing: Extremely intuitive. Creating new pages or API endpoints is as simple as creating a file in the
routes/
directory. - Islands Architecture: This concept delivered on its promise. Interactive components (
ThemeToggle
,SearchBar
,ContactForm
, etc.) are isolated, and the rest of the site remains fast, static HTML where possible. - Preact & Signals: Preact's simplicity and performance, combined with Preact Signals for state management, felt like a lightweight and effective combination for handling client-side interactivity.
- Deno Tooling:
deno fmt
,deno lint
,deno check
, etc. provided a cohesive development experience right out of the box. I seriously did not anticipate using it as much as I ended up doing. - Tailwind CSS: Integrating Tailwind via the Fresh plugin was straightforward, and using
@apply
and thetheme()
function withinstyles.css
alongside the config file allowed for powerful and maintainable styling. Migrating from the olderTwind
dependency to the official Tailwind plugin was a significant improvement, enabling more established patterns.
Key Features Implemented
This project involved building several core components and features:
- Content Rendering: Parsing Markdown files with front matter for blog posts and projects.
- Routing: Dynamic routes for individual posts/projects (e.g.,
/blog/[slug]
). - Components: Reusable UI elements like Cards, Navigation, Footer, GlassMorphism effect.
- Islands: Theme Toggling, Search Bar, Contact Form (with Resend integration), Table of Contents, Back To Top button, Share Button, Hero Animation, etc.
- Styling: Dark/Light modes, responsive design via Tailwind CSS.
- Image Processing: Automated script (
tasks/process_images.ts
) for resizing and converting images placed alongside content. - Basic SEO/Infra: Dynamically generated Sitemap (
/sitemap.xml
), Open Graph meta tags.
Conclusion
Investing the time to build this site with Deno and Fresh was definitely worth it. While there was a learning curve, especially when navigating less-documented territory, the core development experience proved to be productive and enjoyable. The Fresh framework's patterns, particularly file-based routing and the islands architecture, are indeed quite elegant and easy to work with once grasped.
The result is a performant personal platform that I have full control over and a much deeper understanding of this modern web stack.
Future Plans
Future plans might include migrating content persistence to Deno KV for content management robustness.
Known-Issue(s)
- Search is non-functional at the moment - returns mock data.