ยฏ\_(ใƒ„)_/ยฏ Building My Rust Blog Platform: A Developer's Journey ๐Ÿš€


Building My Rust Blog Platform: A Developer's Journey ๐Ÿš€

Greetings, fellow Rustaceans, and curious devs! ๐Ÿ‘‹ I recently built and deployed a blog platform using Rust and wanted to share my experience. This isn't your typical WordPress setup - It's a from-scratch Rust application with some pretty cool features.

๐Ÿค” Why Rust for a Blog?

I chose Rust for this project because I wanted something performant and secure, and I just enjoy coding in Rust. The ecosystem has matured enough that web development is actually pleasant now (a sentence I couldn't have written a few years ago!).

๐Ÿ› ๏ธ The Tech Stack

Here's what powers this blog:

  • Rust (2021 edition) as the language โค๏ธ
  • Axum (v0.8.x) for the web framework ๐Ÿ”„
  • SQLx (v0.7.x) with SQLite for database operations ๐Ÿ’พ
  • Tera (v1.x) for HTML templating ๐Ÿ“
  • Tokio for the async runtime โšก

โœจ Cool Features That Make This Blog Special

I wanted to go beyond basic CRUD operations, so I built in some features that make the blog more enjoyable:

  • Tezos Wallet Authentication ๐Ÿ” - I'm using decentralized auth via Tezos wallet signatures for admin login, which is pretty neat if you're into Web3
  • Markdown & HTML Sanitization ๐Ÿงน - Write in Markdown but don't worry about XSS attacks
  • Enhanced Code Blocks ๐Ÿ’ป - Syntax highlighting plus a one-click "Copy Code" button
  • Interactive SVG ๐Ÿ‘จโ€๐Ÿ’ป - Drop in [ HACKER_SVG ] in your post to get an animated, matrix-style graphic
  • Dark/Light Mode ๐ŸŒ“ - Complete with OS preference detection and local storage saving
  • USER-Aware View Counting ๐Ÿ“Š - So refreshing the page doesn't inflate your numbers

The dynamic theming was particularly fun to implement. It detects your OS preference and remembers your manual local storage selection.

โš™๏ธ Axum: The Web Framework Backbone

Axum (v0.8.x) is the core web framework for this blog, orchestrating how requests are handled and responses are generated. Its ergonomic design and tight integration with the Tokio ecosystem made it a natural choice.

Key ways Axum is utilized in this project:

  • ย  Routing: Defining clear routes for different parts of the blog, such as displaying individual posts, listing all posts, handling admin functionalities (like the Tezos wallet authentication), and serving static assets.
  • ย  State Management: Axum's state management capabilities are used to share application-wide resources like the SQLx database connection pool and application configuration with route handlers.
  • ย  Request Handling: Processing incoming HTTP requests, extracting parameters (like post slugs or query parameters), and validating inputs.
  • ย  Response Generation: Working in tandem with Tera to render HTML templates or return JSON responses for specific API-like endpoints (e.g., for user-aware view counting).
  • ย  Middleware: Leveraging Axum's middleware system for tasks such as logging, error handling, and managing the session state crucial for features like Tezos wallet authentication.

The framework's focus on type safety and composability helped build a robust and maintainable web application layer.

๐ŸŽจ Templating with Tera

For rendering HTML, I opted for Tera, a powerful templating engine inspired by Jinja2 and Django templates. This made it easy to create dynamic web pages.

Setting it up with Axum was quite straightforward. I defined a base template with common elements like the header, footer, and navigation, and then child templates for specific pages would extend this base. Tera's syntax is intuitive, allowing for loops, conditionals, and template inheritance, which keeps the front-end code clean and maintainable.

For example, displaying a list of blog posts might look something like this in a Tera template:

{% for post in posts %}
ย  <article>
ย  ย  <h2>{{ post.title }}</h2>
ย  ย  <p>{{ post.summary }}</p>
ย  </article>
{% endfor %}

This approach effectively separated the presentation logic from the application's core Rust code.

๐Ÿšข Deploying to Fly.io: Easier Than Expected

Getting this running on Fly.io was surprisingly straightforward. I needed to create a few key files:

  1. A Dockerfile that builds the Rust app ๐Ÿณ
  2. A proper .dockerignore to keep build context small ๐Ÿ—‘๏ธ
  3. The fly.toml config file โš™๏ธ

The trickiest part was handling the SQLite database. Since Fly.io instances can restart anywhere, I needed to set up a persistent volume:

fly volumes create personal_blog_data --size 1

Then in my fly.toml, I configured the mount:

[[mounts]]
 source = "personal_blog_data"
 destination = "/app/data"

And made sure my DATABASE_URL points to that location:

DATABASE_URL=sqlite:/app/data/rust_blog_app.db

๐Ÿง™โ€โ™‚๏ธ The SQLx Offline Mode Lifesaver

One thing that tripped me up initially was SQLx's compile-time query checking. In Docker builds you don't have a database connection during compile time! The solution was to use offline mode:

  1. Locally run: cargo sqlx prepare โœจ
  2. Commit the generated sqlx-data.json file ๐Ÿ“„
  3. Set SQLX_OFFLINE=true in the Dockerfile ๐Ÿ—๏ธ

This lets SQLx validate queries without an actual DB connection during builds.

๐Ÿ‘‘ Setting Up Admin Access

Since I'm using Tezos wallet authentication, I needed to configure my admin wallet:

fly secrets set ADMIN_TEZOS_ADDRESSES=my_tezos_wallet_address
fly secrets set SESSION_SECRET_KEY=a_very_long_random_string

Let me know if you're curious about the implementation details or want to check out the code! I'm happy to share more about specific components.

~ The GitHub link will be posted soon!

๐ŸŽ‰ Conclusion

Building a blog in Rust was definitely more work than setting up a WordPress site, but the performance, security, and satisfaction of crafting something from scratch made it worthwhile. Plus, now I can tell people that my blog runs on Rust and watch their impressed nods (or confused stares, depending on the crowd). ๐Ÿ˜Ž