My portfolio website, built with rust-fel, Rust WASM, and React.
This is a hybrid portfolio site that combines multiple technologies:
- Main Site: Built with Rust using rust-fel framework, compiled to WebAssembly
- Posts/Projects Pages: React SPA built with Vite and styled with Tailwind CSS
- Blog Engine: Markdown-to-HTML conversion pipeline using Showdown
- Theme System: Dynamic light/dark theme switcher
- Deployment: GitHub Pages with client-side routing
The site uses a dual-runtime approach:
- Rust WASM Layer: Renders the main site structure (home, navigation, theme)
- React SPA Layer: Handles interactive pages (/posts, /projects) injected into the DOM
- Both communicate through shared DOM nodes and localStorage
- Rust - Main application logic compiled to WASM
- rust-fel - Rust framework for functional UI
- wasm-pack - Rust to WebAssembly compiler
- wee_alloc - Minimal memory allocator for WASM
- React 18 - Posts and projects interactive UI
- Vite - Fast build tool and dev server
- TypeScript - Type-safe JavaScript
- Tailwind CSS - Utility-first styling
- PostCSS - CSS processing with autoprefixer
- wouter - Lightweight client-side router
- Lucide React - Icon library
- Showdown - Markdown to HTML converter
- ESLint - Code linting
- Cypress - E2E testing framework
- http-server - Local development server
- Rust & Cargo
- Node.js & npm
wasm-pack- Install with:cargo install wasm-pack
-
Install dependencies in all directories:
npm install cd injected-app && npm install && cd .. cd converter && npm install && cd ..
-
Build and run the development server:
npm run build
This single command:
- Compiles Rust code to WASM using wasm-pack (
build.sh) - Converts markdown posts to HTML (
converter/index.js) - Builds the React SPA with Vite (
injected-app/vite.config.ts) - Copies generated assets to root-level
assets/directory - Starts a local http-server on port 8000
npm run start- Watch TypeScript files for changesnpm run build- Full production build (same as described above)npm run build-ts- Compile TypeScript onlynpm run build-injected- Build React app in isolationnpm run convert- Convert markdown posts to HTMLnpm run node-server- Start local server on port 8000
- Create a markdown file in
converter/posts/md/(e.g.,post.3.md) - Run
npm run convertto generate HTML - The React component will detect and display the new post
The site includes a dynamic theme switcher (src/theme_switcher.rs) that toggles between light and dark modes and persists to localStorage.
The React app uses Tailwind CSS with custom components in injected-app/src/ui/. ESLint enforces code quality.
Cypress configuration exists in cypress.json for E2E testing.
The 404.html file is a duplicate of index.html to enable client-side routing on GitHub Pages. When a user navigates to a non-existent path, GitHub Pages serves 404.html, which contains the full SPA routing logic.
- Generated WASM files are in
pkg/directory - Built React assets are copied to
assets/in the bundle step - CSS and JS are optimized for production in the Vite build
- wee_alloc: Minimal WASM memory footprint
- Release build: Rust compiled with LTO (Link-Time Optimization) and opt-level 3
- Code splitting: Separate WASM runtime and React bundle
- Asset bundling: Vite's rollup configuration bundles React app into single JS file