Welcome to DuckyCoding! 🦆
After months of planning, coding, forgetting about this, coming back, refactors and countless cups of coffee, I’m thrilled to finally launch DuckyCoding - my new home on the web where I’ll be sharing insights, tutorials, and experiences from my journey in software development.
But before we dive into the exciting content that’s coming, I thought it would be nice to show you how this blog was built. After all, as developers, we love to know what’s under the hood!
The tech stack that powers this blog
🚀 Astro - The foundation
The heart of this blog is built with Astro.
Here’s why Astro was perfect for this project:
- Content-First architecture: Astro is specifically designed for content-heavy sites like blogs
- Zero JavaScript by default: Only the minimum JavaScript is sent to the client, making it incredibly fast
- Framework agnostic: I could use React, Vue, or any other framework if needed, but most of the site is pure HTML/CSS written in Astro components
- Excellent developer experience: Hot reloading, TypeScript support out of the box, and intuitive file-based routing
📚 Content Collections - Structured content management
One of Astro’s killer features is Content Collections, which I’m using to manage blog posts and more:
const posts = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/posts' }),
schema: PostContentSchema, // Zod schema for validating post frontmatter
});
This gives me:
- Type safety: Every post is validated against a Zod schema
- Automatic routing: Posts are automatically available at
/posts/[slug]
- Rich metadata: Frontmatter includes everything I need, like the post title, its summary, its reading time, etc,…
- MDX support: Full MDX capabilities when I need interactive components in posts
🗄️ SQLite + Drizzle ORM - Simple yet powerful data layer
For the database layer, I went with a SQLite database hosted on Turso, managed through Drizzle ORM:
Why SQLite?
- Perfect for a blog that doesn’t need complex relationships
- Zero configuration - it’s just a file
- Easy to backup and migrate
Why Drizzle ORM?
One word, TypeScript.
🎨 Styling philosophy
The visual design is built with:
- TailwindCSS v4: Utility-first CSS framework for rapid development
- Mobile-First Approach: Every component is designed mobile-first, then enhanced for larger screens
- Custom Color System: Carefully crafted color palette (= whatever colors I liked đź‘€) with CSS custom properties
- Astro scoped styles: Where I needed more complex styles, I used Astro’s scoped styles over Tailwind
Architecture decisions & patterns
File organization
The project follows a clean, scalable structure:
src/
├── assets/ # Static assets like images and fonts
├── components/ # Reusable UI components
├── content/ # Blog posts and topics
├── db/ # Database schemas and utilities
├── layouts/ # Page layouts
├── pages/ # Routes
├── types/ # TypeScript type definitions and Zod schemas
└── utils/ # Helper functions
SEO
Every page is optimized for SEO with:
- Meta tags
- Open Graph and Twitter Cards: Custom images and metadata for social sharing
- Structured Data: JSON-LD for rich search results
- Sitemap: Automatically generated sitemap for better indexing
- Robots.txt: Properly configured to allow search engines to index the site
Static pages have its metadata hardcoded, whereas dynamic pages (like blog posts) have their metadata defined in the frontmatter and processed at build time.
Content management workflow
Writing a new blog post is as simple as:
- Create a new
.mdx
file insrc/content/posts/
- Add the required frontmatter (validated by Zod schema)
- Write its content in Markdown syntax, using MDX for interactive components
- Save and commit the file, which is version controlled with Git with the rest of the repository
- Set the post’s status to
published
in the frontmatter to make it live whenever it’s ready - Merge to the main branch, which triggers a build and deploy process on Netlify.
- The post automatically appears on the blog with proper routing, SEO, and styling
Performance optimizations
- Static Site Generation: For now, the entire site is statically generated at build time, resulting in fast load times
- Image Optimization: Automatic image optimization with Astro’s built-in tools
- CSS Purging: Unused CSS is automatically removed in production
- Minimal JavaScript: Most components ship as static HTML, with JavaScript only for interactivity when needed (e.g. the sidemenu on small screens uses some JavaScript to toggle the menu visibility by swiping left or right)
What’s coming next
Now that the foundation is solid I can finally start blogging!
Here’s what you can expect from DuckyCoding:
- Quick guides: Short, focused tutorials on specific topics like Astro features, CSS tricks, TypeScript tips, web performance optimization, etc,…
- In-depth articles: Longer posts diving deep into web development concepts, architecture patterns, and best practices
- Project showcases: Behind-the-scenes looks at projects I’m working on, including code snippets and architecture decisions
- Community Q&A: Answering questions from readers, sharing solutions to common problems, and discussing new technologies
- Guest posts: Inviting other developers to share their experiences and insights
- Tech news and trends: My take on the latest developments in the web development world, including new tools, frameworks, and best practices
Join the journey
I’m excited to share this journey with you! Whether you’re a seasoned developer or just starting out, I hope you’ll find value in the content I’ll be sharing.
Feel free to reach out if you have questions about the technical setup, suggestions for future posts, or just want to connect. You can find me on GitHub or on any of my socials.
Here’s to building great things together! Quack! 🦆
This post marks the beginning of what I hope will be a long and valuable journey. Thank you for being here from the start, and welcome to DuckyCoding!