Skip to content

hnlearndev/blog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

50 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Willian Nguyen's blog

Status

The final product is williannguyen.com.

Full personal reflection on this project can be found on this post.

Note:

There is a regular status service to check that the website should work. This is one of the feature can be seen in the source code. If it does not (mismatch with status), please dm me. Thank you for your helps.

ARCHITECTURE OVERVIEW

This application follows a full-stack Rust architecture using:

  • Frontend: Leptos with hydration for interactive client-side features
  • Backend: Axum web framework
  • Rendering: Server-side rendering (SSR) with client-side hydration
  • Content: Markdown-based blog posts with syntax highlighting
  • Build System: Custom build script for static content generation
  • Planned Database: SurrealDB

TECH STACK

Core Framework

Database (Planned)

  • SurrealDB - Multi-model database (planned for newsletter subscriber feature)

Content Processing

  • pulldown-cmark - Markdown parser
  • syntect - Syntax highlighting for code blocks
  • Static Content Generation - Build-time markdown processing

Development & Deployment

  • cargo-leptos - Leptos build tool
  • Hot Reload - Development server with live reloading
  • WASM Optimization - Size-optimized WebAssembly builds
  • End-to-End Testing - Playwright integration

PROJECT STRUCTURE

🌐 Frontend (Leptos)

Built with Leptos 0.8 using SSR + hydration pattern. The frontend follows a responsive component architecture with clear separation of desktop/mobile layouts.

src/
β”œβ”€β”€ client.rs              # Client-side hydration entry point
β”œβ”€β”€ lib.rs                 # Shared library code
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ mod.rs             # Root App component with header/footer
β”‚   β”œβ”€β”€ helpers.rs         # UI utility functions
β”‚   β”œβ”€β”€ components/        # Reusable UI components
β”‚   β”‚   β”œβ”€β”€ nav/           # Navigation (responsive desktop/mobile)
β”‚   β”‚   β”‚   β”œβ”€β”€ mod.rs     # Nav coordinator
β”‚   β”‚   β”‚   β”œβ”€β”€ desktop.rs # Desktop navigation (>768px)
β”‚   β”‚   β”‚   β”œβ”€β”€ mobile.rs  # Mobile navigation (≀768px)
β”‚   β”‚   β”‚   └── helpers.rs # Shared nav logic & parameterized components
β”‚   β”‚   β”œβ”€β”€ footer/        # Footer (responsive desktop/mobile)
β”‚   β”‚   β”‚   β”œβ”€β”€ mod.rs     # Footer coordinator
β”‚   β”‚   β”‚   β”œβ”€β”€ desktop.rs # Desktop footer layout
β”‚   β”‚   β”‚   β”œβ”€β”€ mobile.rs  # Mobile footer layout
β”‚   β”‚   β”‚   β”œβ”€β”€ helpers.rs # Copyright & NewsletterSection components
β”‚   β”‚   β”‚   └── subscribe_form.rs  # AutoForm-based newsletter form
β”‚   β”‚   β”œβ”€β”€ post_nav/      # Post navigation (prev/next links)
β”‚   β”‚   β”‚   β”œβ”€β”€ mod.rs     # PostNav coordinator
β”‚   β”‚   β”‚   β”œβ”€β”€ desktop.rs # Horizontal layout
β”‚   β”‚   β”‚   β”œβ”€β”€ mobile.rs  # Vertical stacked layout
β”‚   β”‚   β”‚   └── helpers.rs # BackToTop & PostLink components
β”‚   β”‚   β”œβ”€β”€ ui/            # rust-ui components (theme toggle, etc.)
β”‚   β”‚   β”œβ”€β”€ fast_a.rs      # Enhanced anchor component
β”‚   β”‚   β”œβ”€β”€ content_list.rs   # Dynamic post/poem list rendering
β”‚   β”‚   β”œβ”€β”€ icons.rs       # Icon mapping utilities
β”‚   β”‚   └── theme_toggle.rs   # Dark/light mode switcher
β”‚   β”œβ”€β”€ pages/             # Route-level page components
β”‚   β”‚   β”œβ”€β”€ mod.rs         # Page coordinator
β”‚   β”‚   β”œβ”€β”€ homepage.rs    # Landing page
β”‚   β”‚   β”œβ”€β”€ postpage.rs    # Blog post list & detail pages
β”‚   β”‚   └── poempage.rs    # Poetry list & detail pages
β”‚   └── hooks/             # Custom reactive hooks
β”‚       └── use_theme_mode.rs  # Theme state management with localStorage
β”œβ”€β”€ server/                # Backend (see Backend section)
└── shared/                # Shared DTOs between frontend/backend
    └── dto.rs

Frontend Architecture Patterns

  • Responsive Module Pattern: Each complex component (nav/, footer/, post_nav/) uses a directory structure with mod.rs (coordinator), desktop.rs, mobile.rs, and helpers.rs (shared logic)
  • Parameterized Components: Shared UI elements (e.g., SocialLinks, NavLinks) accept class prefixes for layout variants without duplication
  • Theme Management: Reactive theme state persisted to localStorage, with SSR-compatible hydration
  • Static Content: Markdown posts/poems processed at build time, rendered as static HTML with syntax highlighting
  • rust-ui Integration: Uses rust-ui ecosystem for form generation (autoform), icons (icons crate with Leptos feature), and UI primitives
  • CSS Strategy: PicoCSS base + Tailwind CSS v4 + custom semantic stylesheets in public/style/

βš™οΈ Backend (Axum) Architecture

The backend structure seen below is over-engineered for the purpose of personal blog with only public newsletter subcriber feature.

However, the industry-graded architecture is purposely used to study fullstack technology with Rust. The architecture is learnt from the book FullStack Rust with Axum from Martin Fabio

β”œβ”€β”€ main.rs                 # Application entry point
β”œβ”€β”€ server.rs               # Server orchestration & middleware stack
└── server/                 # Modular backend architecture
    β”œβ”€β”€ db.rs               # Database module coordinator
    β”œβ”€β”€ db/
    β”‚   β”œβ”€β”€ config.rs       # Database URL & connection config
    β”‚   β”œβ”€β”€ pool.rs         # PgPool initialization & management
    β”‚   β”œβ”€β”€ state.rs        # AppState with shared resources
    β”‚   └── error.rs        # Database-specific error handling
    β”œβ”€β”€ middleware.rs       # Middleware module coordinator
    β”œβ”€β”€ middleware/
    β”‚   β”œβ”€β”€ cache.rs        # HTTP caching strategies
    β”‚   β”œβ”€β”€ governor.rs     # Rate limiting (IP-based)
    β”‚   β”œβ”€β”€ csrf.rs         # CSRF token protection
    β”‚   β”œβ”€β”€ throttle.rs     # Request throttling
    β”‚   β”œβ”€β”€ global_layer.rs # Middleware layer coordinator
    β”‚   └── global_layer/
    β”‚       β”œβ”€β”€ cors.rs                 # Cross-Origin Resource Sharing
    β”‚       └── security_headers.rs     # Security headers middleware
    β”œβ”€β”€ models.rs           # Data model coordinator
    β”œβ”€β”€ models/
    β”‚   β”œβ”€β”€ subscriber.rs   # Newsletter subscriber model
    β”‚   └── status.rs       # Status badge model (for shields.io)
    β”œβ”€β”€ repositories.rs     # Data access coordinator
    β”œβ”€β”€ repositories/
    β”‚   β”œβ”€β”€ subscriber.rs   # Database queries & data access
    β”‚   └── status.rs       # Status badge logic (checks and aggregates status)
    β”œβ”€β”€ services.rs         # Business logic coordinator
    β”œβ”€β”€ services/
    β”‚   β”œβ”€β”€ subscriber.rs   # Newsletter business logic
    β”‚   └── status.rs       # Status badge update logic (periodic background updater)
    β”œβ”€β”€ handlers.rs         # Request handler coordinator
    β”œβ”€β”€ handlers/
    β”‚   β”œβ”€β”€ subscriber.rs   # HTTP request/response handling
    β”‚   └── status.rs       # Status badge API handler (serves cached status)
    β”œβ”€β”€ routes.rs           # API route coordinator
    └── routes/
        β”œβ”€β”€ subscriber.rs   # Newsletter API endpoints
        └── status.rs       # Status badge AP endpoint (`/status-badge` for shields.io)

🏘️ Backend Layer Relationships

graph TD
  Middleware["🧩 Middleware Stack<br/>(server.rs & routes/)"]
  Middleware -->|Applied globally and per route| Routes["πŸ›£οΈ Routes"]
  Routes -->|Use| Handlers["πŸ‘ Handlers"]
  Handlers -->|Use| Services["πŸ›ŽοΈ Services"]
  Services -->|Use| Repositories["πŸ“¦ Repositories"]
  Repositories -->|Use| Models["πŸ“„ Models"]
  Repositories -->|Use| DB["πŸ—„οΈ DB"]

Middleware & Security Features

  • Global
    • Compression: Brotli compression for responses
    • Request Timeout: Configurable request timeouts
    • Security Headers: Comprehensive HTTP security headers
  • Route specific
    • Rate Limiting: Per-IP request throttling using Governor
    • CORS: Cross-Origin Resource Sharing configuration
    • CSRF Protection: Token-based CSRF mitigation

Layer Responsibilities

  • Routes: HTTP endpoints + middleware application, delegate to handlers
  • Handlers: HTTP request/response processing, input validation
  • Services: Business logic, orchestration, transaction management
  • Repositories: Data access queries, DB operations using models
  • Models: Data structures, serialization, validation rules
  • DB: Connection pooling, configuration, state management

BUILD SYSTEM

The project uses a custom build script (build.rs) that:

  1. Processes Markdown Files: Reads blog posts from contents/posts/
  2. Syntax Highlighting: Applies code highlighting using Syntect
  3. Static Generation: Converts markdown to HTML at build time
  4. Optimized Output: Generates Rust code with static post data

PERFORMANCE FEATURES

  • Server-Side Rendering (SSR): Fast initial page loads
  • Hydration: Interactive client-side features without full SPA overhead
  • Static Content: Build-time markdown processing reduces runtime overhead
  • Compression: Brotli compression for smaller payload sizes
  • Connection Pooling: Efficient database connection management
  • Request Timeout: Prevents long-running requests from blocking resources
  • HTTP Caching Strategy: Multi-tier caching system for optimal performance
  • WASM Optimization: Aggressive size optimization for client-side bundles

WASM BUNDLE OPTIMIZATION

The WebAssembly build process includes several standard optimization techniques to minimize bundle size:

Optimization Techniques

  • Size-focused compilation (opt-level = 'z')
  • Link-time optimization (LTO)
  • Strip debug symbols (strip = true)
  • Abort on panic (panic = "abort")
  • Single codegen unit
  • Use wee_alloc for smaller WASM allocator

Benchmark Results

Below information is obtained from the actual implementation on the project and get benchmark to show the efficency of these technuques.

Metric Before Optimization After Optimization Improvement
Bundle Size 8.5MB 1.5MB 82.4% smaller
Gzipped Size ~2.1MB ~400-600KB ~75% smaller
Load Time Impact Baseline Significantly improved 5.6x smaller

Impact

  • Faster page loads: 82% smaller WASM bundles load much faster
  • Reduced bandwidth: Significant savings in data transfer
  • Better mobile experience: Smaller bundles improve performance on slower connections
  • Production ready: Size is now within reasonable limits for web deployment

CACHING

Deploy standard industry practices

  • Static Assets:
    • Uses Cache-Control: public, max-age=31536000 for 1-year caching.
    • Assets are versioned for cache busting, ensuring users get updates when files change.
  • API Responses:
    • Uses Cache-Control: public, max-age=60 for short-term caching (1 minute).
    • Improves performance for read-only endpoints and reduces database load.
  • Sensitive/Dynamic Endpoints:
    • Uses Cache-Control: no-store to prevent caching of user actions and sensitive data.

Future Features

  • Centralized Error Handling (Status: Planned)

To add a middleware layer to catch errors, log them, and provide consistent user-friendly responses. Implementation is postponed until the app grows in complexity.

  • Modulized global layer (Status: Planned)

This was planned out at the begginning with tower crate 's ServiceBuilder as a global layer which is then called into server.rs. However, refactoring this seperated out from server.rs run is more troublesome than expected. Until the project expands further, it is placed directly in server.rs.

Reference

About

Personal blog written in Rust Leptos and Axum

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Packages

 
 
 

Contributors