diff --git a/.gitignore b/.gitignore index 6fea084..4d1da90 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ node_modules/ # WebAssembly generated files pkg/ +dist/ # IDE files .vscode/ diff --git a/CNAME b/CNAME deleted file mode 100644 index d3e171d..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -www.atomicincrement.com \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 9c3d7dc..1c2d19e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ leptos_meta = { version = "0.6", features = ["csr"] } leptos_router = { version = "0.6", features = ["csr"] } wasm-bindgen = "0.2" console_error_panic_hook = "0.1" +pulldown-cmark = "0.11" +serde = { version = "1.0", features = ["derive"] } +chrono = { version = "0.4", features = ["serde"] } [dependencies.web-sys] version = "0.3" diff --git a/README.md b/README.md index 36001ed..5e2cd84 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,288 @@ # AtomicIncrement Landing Page -A modern landing page built with Rust and Leptos featuring a responsive design inspired by the Fledgio website. +[![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/gaveesh89/landing-page_GJ) +[![Rust](https://img.shields.io/badge/rust-1.70+-orange.svg)](https://www.rust-lang.org) +[![Leptos](https://img.shields.io/badge/leptos-0.6+-blue.svg)](https://leptos.dev) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -## Features +A modern, high-performance landing page and blog system built with Rust and Leptos, featuring a complete case studies section, responsive design, and professional styling. -- **Modern Navigation**: Responsive menu bar with mobile support -- **Hero Section**: Engaging introduction with call-to-action buttons -- **Features Grid**: Highlighting key differentiators and capabilities +## ๐Ÿš€ Live Demo + +- **Website**: [http://127.0.0.1:8080](http://127.0.0.1:8080) (development) +- **Blog**: [http://127.0.0.1:8080/blog](http://127.0.0.1:8080/blog) +- **About Page**: [http://127.0.0.1:8080/about](http://127.0.0.1:8080/about) +- **Engagement Form**: [http://127.0.0.1:8080/engagement](http://127.0.0.1:8080/engagement) + +## โœจ Features + +### ๐ŸŒ **Landing Page** +- **Modern Navigation**: Responsive menu bar with mobile hamburger menu +- **Hero Section**: Engaging introduction with technical visualization +- **Features Grid**: Highlighting key differentiators and capabilities with unified CTAs +- **Core Capabilities**: Technical expertise showcase with visual indicators - **Testimonials**: Customer feedback and success stories -- **Contact Section**: Multiple ways to get in touch -- **Responsive Design**: Works perfectly on desktop and mobile devices +- **Recent Projects**: Horizontal scrolling project showcase +- **About Founder**: Dedicated about page with professional information +- **Contact Section**: Professional contact form and information +- **Engagement Form**: Comprehensive project initiation with architectural review process +- **Unified CTA Flow**: All service inquiries funnel to professional engagement form +- **Responsive Design**: Optimized for desktop, tablet, and mobile devices -## Technology Stack +### ๐ŸŽฏ **Professional Engagement System** +- **Project Parameters**: Comprehensive form for technical requirements +- **Budget & Timeline**: Structured ranges for project planning +- **Technical Assessment**: Current stack and infrastructure evaluation +- **Success Metrics**: KPI definition and measurement criteria +- **Architectural Review**: 48-hour professional project assessment +- **Clear Process**: Transparent next steps and consultation workflow -- **Rust**: System programming language for performance and safety -- **Leptos**: Modern reactive web framework for Rust -- **Tailwind CSS**: Utility-first CSS framework for styling -- **WebAssembly**: For running Rust code in the browser +### ๐ŸŽฏ **Call-to-Action Flow** +- **Hero Banner**: "Start Your Project" โ†’ `/engagement` +- **Header**: "Get Started" โ†’ `/engagement` +- **Areas of Expertise**: All 3 CTAs ("Learn More", "Get Consulting", "Start Project") โ†’ `/engagement` +- **Founder Story**: "Learn Our Story" โ†’ `/about` +- **Footer**: "Start a Project" โ†’ `#contact` -## Development Setup +### ๐Ÿงญ **Navigation Structure** +- **Home**: Main landing page with all sections +- **Services**: Scrolls to "Areas of Expertise" section on homepage +- **About**: Dedicated founder and company information page +- **Blog**: Internal blog system with technical posts and tutorials +- **Contact**: Direct link to contact section +- **Engagement**: Professional project initiation form with architectural review -### Prerequisites +### ๐Ÿ“ **Blog System** +- **Markdown Support**: Full markdown parsing with frontmatter +- **Professional Styling**: Dark theme with purple accents and hover effects +- **Technical Content**: 4 comprehensive case studies and tutorials +- **SEO Optimized**: Proper meta tags, excerpts, and structured content +- **Responsive Reading**: Optimized typography and spacing for readability +- **Code Highlighting**: Syntax highlighting for code blocks +- **Navigation Integration**: Seamless integration with main site navigation -1. Install Rust: https://rustup.rs/ -2. Install `wasm-pack`: - ```bash - cargo install wasm-pack - ``` -3. Install a local development server (like `basic-http-server`): +### ๐ŸŽจ **Design & Performance** +- **Dark Theme**: Professional dark design with gradient backgrounds +- **Smooth Animations**: Hover effects, transitions, and micro-interactions +- **Performance Optimized**: WebAssembly for near-native performance +- **Accessibility**: WCAG compliant with proper ARIA labels and keyboard navigation +- **Mobile First**: Responsive design that works perfectly on all devices + +## ๐Ÿ› ๏ธ Technology Stack + +- **[Rust](https://www.rust-lang.org/)**: Systems programming language for performance and safety +- **[Leptos](https://leptos.dev/)**: Modern reactive web framework for Rust +- **[Trunk](https://trunkrs.dev/)**: Rust web application bundler +- **[Tailwind CSS](https://tailwindcss.com/)**: Utility-first CSS framework +- **[WebAssembly](https://webassembly.org/)**: For running Rust code in the browser +- **[pulldown-cmark](https://github.com/raphlinus/pulldown-cmark)**: Markdown parser for blog content +- **[serde](https://serde.rs/)**: Serialization framework for data handling +- **[chrono](https://github.com/chronotope/chrono)**: Date and time library + +## ๐Ÿ“‹ Prerequisites + +- **Rust**: Install from [rustup.rs](https://rustup.rs/) +- **Trunk**: Web application bundler for Rust + ```bash + cargo install trunk + ``` +- **wasm32 target**: WebAssembly compilation target + ```bash + rustup target add wasm32-unknown-unknown + ``` + +## ๐Ÿš€ Quick Start + +1. **Clone the repository**: ```bash - cargo install basic-http-server + git clone https://github.com/gaveesh89/landing-page_GJ.git + cd landing-page_GJ ``` -### Build and Run - -1. Build the WebAssembly package: +2. **Install dependencies and build**: ```bash - wasm-pack build --target web --out-dir pkg + cargo build ``` -2. Start a local development server: +3. **Start development server**: ```bash - basic-http-server . + trunk serve ``` -3. Open your browser and navigate to `http://localhost:4000` +4. **Open in browser**: Navigate to [http://localhost:8080](http://localhost:8080) -## Project Structure +## ๐Ÿ“ Project Structure ``` -โ”œโ”€โ”€ src/ -โ”‚ โ”œโ”€โ”€ lib.rs # Main application entry point -โ”‚ โ””โ”€โ”€ components/ -โ”‚ โ”œโ”€โ”€ mod.rs # Component module exports -โ”‚ โ”œโ”€โ”€ header.rs # Navigation header component -โ”‚ โ”œโ”€โ”€ hero.rs # Hero section component -โ”‚ โ”œโ”€โ”€ features.rs # Features grid component -โ”‚ โ”œโ”€โ”€ testimonials.rs # Testimonials section component -โ”‚ โ”œโ”€โ”€ contact.rs # Contact section component -โ”‚ โ””โ”€โ”€ footer.rs # Footer component -โ”œโ”€โ”€ index.html # Main HTML file -โ”œโ”€โ”€ Cargo.toml # Rust project configuration -โ””โ”€โ”€ README.md # This file +landing-page_GJ/ +โ”œโ”€โ”€ ๐Ÿ“ src/ +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ lib.rs # Main application entry point +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ blog.rs # Blog system with markdown parsing +โ”‚ โ”œโ”€โ”€ ๐Ÿ“ components/ # Reusable UI components +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ mod.rs # Component module exports +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ header.rs # Navigation header with blog navigation +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ hero.rs # Hero section with engagement CTA +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ features.rs # Areas of expertise grid +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ testimonials.rs # Customer testimonials +โ”‚ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ contact.rs # Professional contact form +โ”‚ โ”‚ โ””โ”€โ”€ ๐Ÿ“„ footer.rs # Footer with social links +โ”‚ โ””โ”€โ”€ ๐Ÿ“ pages/ # Page components +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ mod.rs # Page module exports +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ about.rs # About founder page +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ engagement.rs # Professional engagement form +โ”‚ โ””โ”€โ”€ ๐Ÿ“„ blog.rs # Blog list and post pages +โ”œโ”€โ”€ ๐Ÿ“ content/ +โ”‚ โ””โ”€โ”€ ๐Ÿ“ posts/ # Blog post markdown files +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ hello-world.md # Welcome post +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ getting-started.md # Systems programming guide +โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ rust-tips.md # Performance optimization tips +โ”‚ โ””โ”€โ”€ ๐Ÿ“„ What is an atomic increment.md # Company story +โ”œโ”€โ”€ ๐Ÿ“„ index.html # Main HTML with blog CSS styling +โ”œโ”€โ”€ ๐Ÿ“„ Cargo.toml # Rust dependencies and configuration +โ”œโ”€โ”€ ๐Ÿ“„ README.md # This documentation +โ””โ”€โ”€ ๐Ÿ“ dist/ # Built WebAssembly and assets ``` -## Customization +## ๐Ÿ“ Blog Content Management + +### Adding New Blog Posts + +1. **Create a new markdown file** in `content/posts/`: + ```markdown + --- + title: "Your Post Title" + date: "2024-11-08" + excerpt: "Brief description of your post" + --- + + # Your Post Content + + Write your content here using markdown... + ``` + +2. **Update `src/blog.rs`** to include the new post: + ```rust + // Add to get_all_posts() function + let your_post_content = include_str!("../content/posts/your-post.md"); + posts.push(parse_post("your-post-slug", your_post_content)); + ``` + +3. **The post will be available** at `/blog/your-post-slug` -The landing page is designed to be easily customizable: +### Blog Features +- **Frontmatter Support**: YAML frontmatter for metadata +- **Markdown Parsing**: Full CommonMark support with code highlighting +- **Automatic Sorting**: Posts sorted by date (newest first) +- **SEO Friendly**: Proper excerpts and meta information +- **Responsive Design**: Optimized reading experience -1. **Company Information**: Update company name, logo, and contact details in the components -2. **Content**: Modify text content in each component file -3. **Styling**: Adjust Tailwind CSS classes for different colors, layouts, or animations -4. **Features**: Add or remove feature cards in the features section -5. **Testimonials**: Update customer testimonials with real feedback +## ๐Ÿงช Testing -## Deployment +Run the test suite: +```bash +cargo test +``` -For production deployment: +Key test coverage: +- โœ… Blog post parsing and frontmatter extraction +- โœ… Markdown to HTML conversion +- โœ… Post retrieval by slug +- โœ… All posts loading (currently 4 posts) -1. Build the optimized WebAssembly package: +## ๐Ÿ—๏ธ Building for Production + +1. **Optimize build**: ```bash - wasm-pack build --target web --out-dir pkg --release + trunk build --release ``` -2. Deploy the generated files (index.html, pkg/ directory) to your web server +2. **Deploy the `dist/` folder** to your web server + +3. **Environment variables** (optional): + ```bash + export RUSTFLAGS="-C target-cpu=native" + ``` + +## ๐ŸŽจ Customization Guide + +### **Styling** +- **Colors**: Modify CSS variables in `index.html` +- **Layout**: Adjust Tailwind classes in components +- **Blog Styling**: Update blog-specific CSS classes + +### **Content** +- **Company Info**: Update in `src/components/` +- **Blog Posts**: Add new markdown files in `content/posts/` +- **Navigation**: Modify links in `header.rs` and `footer.rs` + +### **Features** +- **Add Components**: Create new components in `src/components/` +- **Routing**: Add new routes in `src/lib.rs` +- **Pages**: Create new pages in `src/pages/` + +## ๐ŸŒ Deployment Options + +### **Static Hosting** +- GitHub Pages +- Netlify +- Vercel +- AWS S3 + CloudFront + +### **Server Deployment** +- Any static file server (nginx, Apache) +- CDN for optimal performance + +## ๐Ÿค Contributing + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/amazing-feature` +3. Commit your changes: `git commit -m 'Add amazing feature'` +4. Push to the branch: `git push origin feature/amazing-feature` +5. Open a Pull Request + +## ๐Ÿ“‹ Recent Updates + +### **v1.2.1** - November 8, 2025 +- โœ… **Unified CTA Flow**: All Areas of Expertise CTAs now lead to engagement form +- โœ… **Professional Funnel**: "Learn More", "Get Consulting", "Start Project" โ†’ `/engagement` +- โœ… **Founder Story Fix**: "Learn Our Story" now correctly links to `/about` page +- โœ… **Consistent Experience**: Single entry point for all service inquiries +- โœ… **Documentation**: Updated README with comprehensive CTA flow mapping + +### **v1.2.0** - November 8, 2025 +- โœ… **Engagement Form**: Professional project initiation form with comprehensive parameters +- โœ… **Enhanced CTA**: Hero banner and header buttons now lead to engagement form +- โœ… **Services Navigation**: Updated to scroll directly to "Areas of Expertise" section +- โœ… **Blog Terminology**: Consistent "Blog" terminology across header and footer +- โœ… **Footer Cleanup**: Removed external blog link, streamlined navigation +- โœ… **Professional Workflow**: Clear engagement process with architectural review + +### **v1.1.0** - November 8, 2025 +- โœ… **Navigation Simplified**: Removed external "Blog" link from header navigation +- โœ… **Case Studies Focus**: "Case Studies" tab now exclusively points to internal blog system +- โœ… **Mobile Navigation**: Updated mobile menu to match desktop navigation changes +- โœ… **Documentation**: Updated README with current navigation structure +- โœ… **Performance**: Cleaner navigation reduces external dependencies + +### **v1.0.0** - November 8, 2025 +- โœ… **Complete Blog System**: Full markdown parsing with frontmatter support +- โœ… **Professional Styling**: Dark theme with responsive design +- โœ… **4 Technical Posts**: Comprehensive case studies and tutorials +- โœ… **Routing System**: Integrated blog routes with main application +- โœ… **SEO Optimization**: Proper meta tags and structured content + +## ๏ฟฝ๐Ÿ“„ License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## ๐Ÿ”— Links + +- **Company**: [Atomic Increment Ltd](https://atomicincrement.com) +- **Blog**: [Technical Blog](https://atomicincrement.github.io/) +- **LinkedIn**: [Company Page](https://www.linkedin.com/company/atomic-increment-limited/) +- **GitHub**: [@atomicincrement](https://github.com/atomicincrement) +- **Twitter/X**: [@quaternioso](https://x.com/quaternioso) -## License +--- -This project is open source and available under the MIT License. \ No newline at end of file +Built with โค๏ธ using Rust and Leptos by [Atomic Increment](https://atomicincrement.com) \ No newline at end of file diff --git a/content/posts/What is an atomic increment.md b/content/posts/What is an atomic increment.md new file mode 100644 index 0000000..f2867a7 --- /dev/null +++ b/content/posts/What is an atomic increment.md @@ -0,0 +1,53 @@ +--- +title: "What is an atomic increment?" +date: "2021-11-17" +excerpt: "Understanding why we call ourselves Atomic Increment and how atomic operations solve race conditions in multithreaded code for improved performance." +--- + +# What is an atomic increment? + +Why do we call ourselves Atomic Increment? One of the myriad ways of improving code performance is to use multithreaded code to lower latency. Every modern computer has many cores which can run one or more threads at the same time. + +The "atomic increment" operation allows us to safely share a counter between two threads. Why is this necessary? This is because two CPUs running the same code increment a counter using these three operations: + +- load from memory +- increment +- store back to memory + +If two threads are running, then we may get these following sequences: + +## The good one: + +``` + Processor 1 Processor 2 + |------------------------|------------------------| + | load from memory | | + | increment | | + | store back to memory | | + | | load from memory | + | | increment | + | | store back to memory | + |------------------------|------------------------| +``` + +This adds 2 to the memory. + +## And the bad one: + +``` + Processor 1 Processor 2 + |------------------------|------------------------| + | load from memory | | + | | load from memory | + | increment | | + | | increment | + | | store back to memory | + | store back to memory | | + |------------------------|------------------------| +``` + +The second sequence is bad because we only add 1 to the memory not 2! This is because Processor 1 overwrites the result of Processor 2 - a situation known as a "Race Condition". + +To solve this we use special instructions that allow the CPUs to "lock" the memory while the increment occurs. How this is implemented depends on the CPU. + +For more information about concurrent programming, get in touch with us. \ No newline at end of file diff --git a/content/posts/getting-started.md b/content/posts/getting-started.md new file mode 100644 index 0000000..f3f5a35 --- /dev/null +++ b/content/posts/getting-started.md @@ -0,0 +1,249 @@ +--- +title: "Getting Started with Systems Programming in Rust" +date: "2024-11-08" +excerpt: "Discover why Rust has emerged as the premier language for systems programming, offering memory safety without sacrificing performance. Learn core concepts and build your first systems program." +--- + +# Getting Started with Systems Programming in Rust + +Systems programming is the art of building software that directly interacts with computer hardware and operating systems. **Rust** has emerged as the premier language for this domain, offering memory safety without sacrificing performance. + +## Why Rust for Systems Programming? + +### Memory Safety Without Garbage Collection + +Traditional systems languages like C and C++ give you direct control over memory but leave room for dangerous bugs: + +```c +// C code - potential memory leak and use-after-free +char* create_buffer() { + char* buffer = malloc(1024); + // Oops! Forgot to free + return buffer; +} + +void use_buffer() { + char* data = create_buffer(); + free(data); + printf("%s", data); // Use after free - undefined behavior! +} +``` + +Rust prevents these issues at compile time: + +```rust +// Rust code - memory safety guaranteed +fn create_buffer() -> Vec { + Vec::with_capacity(1024) // Memory automatically managed +} + +fn use_buffer() { + let data = create_buffer(); + // data is automatically freed when it goes out of scope + // Compiler prevents use-after-free +} +``` + +## Core Concepts for Beginners + +### 1. Ownership System + +Rust's ownership system is the foundation of its memory safety guarantees: + +```rust +fn main() { + let s1 = String::from("Hello"); + let s2 = s1; // s1 is moved to s2 + + // println!("{}", s1); // This would cause a compile error + println!("{}", s2); // This works fine +} +``` + +### 2. Borrowing and References + +Borrowing allows you to use values without taking ownership: + +```rust +fn calculate_length(s: &String) -> usize { + s.len() // We can read s but not modify it +} // s goes out of scope but nothing happens (we don't own it) + +fn main() { + let hello = String::from("Hello, world!"); + let len = calculate_length(&hello); // We borrow hello + println!("Length of '{}' is {}", hello, len); // hello is still valid +} +``` + +### 3. Mutability Control + +Rust makes mutability explicit and controlled: + +```rust +fn main() { + let mut counter = 0; + + // Only one mutable reference at a time + let r1 = &mut counter; + *r1 += 1; + + // let r2 = &mut counter; // This would fail to compile + println!("Counter: {}", counter); +} +``` + +## Building Your First Systems Program + +Let's create a simple file reader that demonstrates systems programming concepts: + +```rust +use std::fs::File; +use std::io::{self, Read, BufReader}; +use std::path::Path; + +struct FileAnalyzer { + filename: String, + size: u64, + lines: usize, +} + +impl FileAnalyzer { + fn new(path: &Path) -> io::Result { + let file = File::open(path)?; + let metadata = file.metadata()?; + + let mut reader = BufReader::new(file); + let mut contents = String::new(); + reader.read_to_string(&mut contents)?; + + let lines = contents.lines().count(); + + Ok(FileAnalyzer { + filename: path.file_name() + .unwrap() + .to_string_lossy() + .to_string(), + size: metadata.len(), + lines, + }) + } + + fn report(&self) { + println!("๐Ÿ“„ File Analysis Report"); + println!(" Name: {}", self.filename); + println!(" Size: {} bytes", self.size); + println!(" Lines: {}", self.lines); + println!(" Avg bytes/line: {:.2}", + self.size as f64 / self.lines as f64); + } +} + +fn main() -> io::Result<()> { + let analyzer = FileAnalyzer::new(Path::new("Cargo.toml"))?; + analyzer.report(); + Ok(()) +} +``` + +## Performance Considerations + +### Zero-Cost Abstractions + +Rust's abstractions compile down to the same assembly as hand-optimized C: + +```rust +// High-level iterator code +let sum: i32 = (0..1_000_000) + .filter(|x| x % 2 == 0) + .map(|x| x * x) + .sum(); + +// Compiles to equivalent of: +// for (int i = 0; i < 1000000; i += 2) { +// sum += i * i; +// } +``` + +### SIMD and Vectorization + +Rust makes it easy to use SIMD instructions for performance: + +```rust +use std::arch::x86_64::*; + +unsafe fn vectorized_add(a: &[f32], b: &[f32]) -> Vec { + assert_eq!(a.len(), b.len()); + let mut result = Vec::with_capacity(a.len()); + + for i in (0..a.len()).step_by(8) { + let va = _mm256_loadu_ps(&a[i]); + let vb = _mm256_loadu_ps(&b[i]); + let vr = _mm256_add_ps(va, vb); + + let mut temp = [0.0f32; 8]; + _mm256_storeu_ps(temp.as_mut_ptr(), vr); + result.extend_from_slice(&temp); + } + + result +} +``` + +## Essential Tools and Ecosystem + +### Development Environment + +1. **Rustup**: Rust toolchain installer +2. **Cargo**: Package manager and build system +3. **Clippy**: Linting tool for better code +4. **Rustfmt**: Code formatter + +### Key Libraries for Systems Programming + +```toml +[dependencies] +tokio = "1.0" # Async runtime +serde = "1.0" # Serialization +clap = "4.0" # Command-line parsing +log = "0.4" # Logging +anyhow = "1.0" # Error handling +``` + +## Next Steps + +1. **Practice ownership patterns** with small programs +2. **Learn async programming** with Tokio +3. **Explore unsafe Rust** for performance-critical code +4. **Study real projects** like Redis modules or Linux drivers +5. **Join the community** on Discord and forums + +## Common Pitfalls for Beginners + +### Fighting the Borrow Checker + +```rust +// Don't do this +fn bad_example() { + let mut vec = vec![1, 2, 3]; + let first = &vec[0]; + vec.push(4); // Error: can't modify while borrowed + println!("{}", first); +} + +// Do this instead +fn good_example() { + let mut vec = vec![1, 2, 3]; + let first = vec[0]; // Copy the value + vec.push(4); // Now modification is allowed + println!("{}", first); +} +``` + +Remember: **Rust teaches you to write better code**, even if it feels restrictive at first. The compiler is your friend, not your enemy! + +## Conclusion + +Systems programming with Rust opens up a world of possibilities where you can write high-performance, memory-safe code. Start with simple projects, understand the ownership model deeply, and gradually tackle more complex systems. + +The journey from beginner to systems programming expert is challenging but incredibly rewarding. Welcome to the Rust community! ๐Ÿฆ€ \ No newline at end of file diff --git a/content/posts/hello-world.md b/content/posts/hello-world.md new file mode 100644 index 0000000..06891b2 --- /dev/null +++ b/content/posts/hello-world.md @@ -0,0 +1,83 @@ +--- +title: "Hello World: Welcome to Atomic Increment's Technical Blog" +date: "2024-11-08" +excerpt: "Welcome to the official blog of Atomic Increment, where we share insights, experiences, and deep dives into systems programming, Rust development, and cutting-edge technology solutions." +--- + +# Welcome to Our Technical Journey + +Welcome to the official blog of **Atomic Increment**, where we share our insights, experiences, and deep dives into the world of systems programming, Rust development, and cutting-edge technology solutions. + +## What You'll Find Here + +Our blog is your gateway to understanding the intricate world of high-performance systems programming. Here's what we'll be covering: + +### ๐Ÿฆ€ Rust Programming +- Advanced Rust patterns and best practices +- Memory safety without garbage collection +- Zero-cost abstractions in action +- Performance optimization techniques + +### โšก Systems Programming +- Low-level programming concepts +- Operating system interactions +- Hardware optimization strategies +- Real-time system design + +### ๐Ÿ—๏ธ Architecture & Design +- Scalable system architectures +- Distributed systems patterns +- Performance-critical design decisions +- Security-first development approaches + +## Our Mission + +At Atomic Increment, we believe in **pushing the boundaries** of what's possible in systems programming. Through this blog, we aim to: + +1. **Share knowledge** gained from real-world projects +2. **Educate developers** on advanced programming concepts +3. **Showcase innovations** in performance-critical applications +4. **Build community** around high-quality software engineering + +## A Code Example to Get Started + +Here's a simple Rust example that demonstrates memory safety and performance: + +```rust +use std::collections::HashMap; + +fn main() { + let mut performance_metrics: HashMap = HashMap::new(); + + // Safe memory management without garbage collection + performance_metrics.insert("latency_ms".to_string(), 0.001); + performance_metrics.insert("throughput_ops_sec".to_string(), 1_000_000.0); + performance_metrics.insert("memory_usage_mb".to_string(), 45.2); + + for (metric, value) in &performance_metrics { + println!("๐Ÿ“Š {}: {:.3}", metric, value); + } + + // Memory automatically deallocated when going out of scope +} +``` + +## What's Next? + +Stay tuned for our upcoming posts where we'll dive deep into: + +- **Performance optimization techniques** used in our trading engine project +- **Blockchain consensus algorithms** and their Rust implementations +- **Game engine architecture** for real-time graphics rendering +- **Compiler optimization passes** for domain-specific languages + +## Connect With Us + +We'd love to hear from you! Share your thoughts, questions, or suggestions: + +- **Email**: andy@atomicincrement.com +- **LinkedIn**: [Atomic Increment Limited](https://www.linkedin.com/company/atomic-increment-limited/) +- **GitHub**: [atomicincrement](https://github.com/atomicincrement) +- **Twitter/X**: [@quaternioso](https://x.com/quaternioso) + +Welcome to the journey of **atomic increments** in software excellence! ๐Ÿš€ \ No newline at end of file diff --git a/content/posts/rust-tips.md b/content/posts/rust-tips.md new file mode 100644 index 0000000..0c1cc37 --- /dev/null +++ b/content/posts/rust-tips.md @@ -0,0 +1,447 @@ +--- +title: "Advanced Rust Tips: Performance Secrets from Production Systems" +date: "2024-11-08" +excerpt: "Battle-tested Rust techniques for exceptional performance. Learn memory layout optimizations, zero-allocation patterns, SIMD vectorization, and lock-free programming from production systems." +--- + +# Advanced Rust Tips: Performance Secrets from Production Systems + +After building high-performance systems for over a decade, we've learned that **the difference between good and exceptional performance** often lies in the details. Here are battle-tested Rust techniques that have delivered measurable improvements in our production systems. + +## Memory Layout Optimizations + +### Struct Field Ordering Matters + +The order of fields in a struct affects memory usage due to alignment requirements: + +```rust +// โŒ Poor memory layout (24 bytes on 64-bit systems) +struct BadLayout { + flag: bool, // 1 byte + 7 bytes padding + id: u64, // 8 bytes + count: u32, // 4 bytes + 4 bytes padding +} + +// โœ… Optimized memory layout (16 bytes) +struct GoodLayout { + id: u64, // 8 bytes + count: u32, // 4 bytes + flag: bool, // 1 byte + 3 bytes padding (but efficient) +} + +// ๐Ÿš€ Best layout with explicit packing +#[repr(C, packed)] +struct PackedLayout { + id: u64, // 8 bytes + count: u32, // 4 bytes + flag: bool, // 1 byte = 13 bytes total +} +``` + +### Cache-Friendly Data Structures + +Design data structures that work with CPU cache lines (typically 64 bytes): + +```rust +use std::mem; + +// Cache-aligned structure for hot data +#[repr(align(64))] +struct CacheAligned { + hot_data: [u64; 8], // Exactly one cache line +} + +// Separate hot and cold data +struct OptimizedStruct { + // Hot data: accessed frequently + counter: u64, + timestamp: u64, + + // Cold data: accessed rarely + metadata: String, + config: HashMap, +} + +fn demonstrate_cache_efficiency() { + println!("CacheAligned size: {} bytes", mem::size_of::()); + println!("Alignment: {} bytes", mem::align_of::()); +} +``` + +## Zero-Allocation Patterns + +### Stack-Based Collections + +Use arrays and stack allocation when possible: + +```rust +use arrayvec::ArrayVec; + +// โŒ Heap allocation for small collections +fn heap_based_processing(items: &[i32]) -> Vec { + let mut results = Vec::new(); + for &item in items { + if item > 0 { + results.push(item * 2); + } + } + results +} + +// โœ… Stack-based processing for bounded data +fn stack_based_processing(items: &[i32]) -> ArrayVec { + let mut results = ArrayVec::new(); + for &item in items { + if item > 0 { + if results.try_push(item * 2).is_err() { + break; // Handle overflow gracefully + } + } + } + results +} +``` + +### Custom Allocators for Hot Paths + +```rust +use bumpalo::Bump; + +struct Arena<'a> { + bump: &'a Bump, +} + +impl<'a> Arena<'a> { + fn new(bump: &'a Bump) -> Self { + Self { bump } + } + + // Fast allocation from pre-allocated arena + fn allocate_slice(&self, len: usize) -> &'a mut [T] + where + T: Default + Copy, + { + self.bump.alloc_slice_fill_default(len) + } +} + +fn fast_computation() { + let arena = Bump::new(); + let allocator = Arena::new(&arena); + + // All allocations happen in the arena + let buffer = allocator.allocate_slice::(1000); + + // Perform computation... + for i in 0..buffer.len() { + buffer[i] = (i as f64).sin(); + } + + // Arena is automatically freed when it goes out of scope +} +``` + +## SIMD and Vectorization + +### Manual SIMD for Critical Paths + +```rust +use std::arch::x86_64::*; + +// High-performance vector operations +pub unsafe fn simd_dot_product(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + assert!(a.len() % 8 == 0, "Length must be multiple of 8"); + + let mut sum = _mm256_setzero_ps(); + + for i in (0..a.len()).step_by(8) { + let va = _mm256_loadu_ps(a.as_ptr().add(i)); + let vb = _mm256_loadu_ps(b.as_ptr().add(i)); + let product = _mm256_mul_ps(va, vb); + sum = _mm256_add_ps(sum, product); + } + + // Horizontal sum of 8 floats + let high = _mm256_extractf128_ps(sum, 1); + let low = _mm256_castps256_ps128(sum); + let sum128 = _mm_add_ps(high, low); + + let shuf = _mm_movehdup_ps(sum128); + let sums = _mm_add_ps(sum128, shuf); + let shuf2 = _mm_movehl_ps(sums, sums); + let result = _mm_add_ss(sums, shuf2); + + _mm_cvtss_f32(result) +} + +// Portable SIMD using std::simd (nightly) +#[cfg(feature = "portable_simd")] +fn portable_simd_example(data: &mut [f32]) { + use std::simd::*; + + for chunk in data.chunks_exact_mut(8) { + let vec = f32x8::from_slice(chunk); + let result = vec * f32x8::splat(2.0) + f32x8::splat(1.0); + *chunk = result.to_array(); + } +} +``` + +## Advanced Async Patterns + +### Custom Runtime Optimizations + +```rust +use tokio::task; +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +// High-performance task spawning for hot paths +struct LocalSpawner { + local_set: tokio::task::LocalSet, +} + +impl LocalSpawner { + fn new() -> Self { + Self { + local_set: tokio::task::LocalSet::new(), + } + } + + fn spawn_local(&self, future: F) -> tokio::task::JoinHandle + where + F: Future + 'static, + F::Output: 'static, + { + self.local_set.spawn_local(future) + } +} + +// Zero-cost async state machine +struct CustomFuture { + state: State, +} + +enum State { + Initial, + WaitingForData(Pin>>>), + Processing(Vec), + Done(String), +} + +impl Future for CustomFuture { + type Output = String; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + loop { + match &mut self.state { + State::Initial => { + let future = Box::pin(async { vec![1, 2, 3, 4] }); + self.state = State::WaitingForData(future); + } + State::WaitingForData(future) => { + match future.as_mut().poll(cx) { + Poll::Ready(data) => { + self.state = State::Processing(data); + } + Poll::Pending => return Poll::Pending, + } + } + State::Processing(data) => { + let result = format!("Processed {} bytes", data.len()); + self.state = State::Done(result); + } + State::Done(_) => { + if let State::Done(result) = std::mem::replace(&mut self.state, State::Initial) { + return Poll::Ready(result); + } + } + } + } + } +} +``` + +## Lock-Free Programming + +### Atomic Operations for High Concurrency + +```rust +use std::sync::atomic::{AtomicU64, AtomicPtr, Ordering}; +use std::ptr; + +// Lock-free counter with memory ordering optimization +struct HighPerfCounter { + value: AtomicU64, +} + +impl HighPerfCounter { + fn new() -> Self { + Self { + value: AtomicU64::new(0), + } + } + + // Fast increment for hot paths + fn increment(&self) -> u64 { + self.value.fetch_add(1, Ordering::Relaxed) + } + + // Precise read when exact value needed + fn load_precise(&self) -> u64 { + self.value.load(Ordering::Acquire) + } +} + +// Lock-free stack implementation +struct LockFreeStack { + head: AtomicPtr>, +} + +struct Node { + data: T, + next: *mut Node, +} + +impl LockFreeStack { + fn new() -> Self { + Self { + head: AtomicPtr::new(ptr::null_mut()), + } + } + + fn push(&self, data: T) { + let new_node = Box::into_raw(Box::new(Node { + data, + next: ptr::null_mut(), + })); + + loop { + let head = self.head.load(Ordering::Acquire); + unsafe { + (*new_node).next = head; + } + + match self.head.compare_exchange_weak( + head, + new_node, + Ordering::Release, + Ordering::Relaxed, + ) { + Ok(_) => break, + Err(_) => continue, + } + } + } +} +``` + +## Compilation and Optimization Tricks + +### Profile-Guided Optimization Setup + +```toml +# Cargo.toml configuration for maximum performance +[profile.release] +lto = "fat" # Link-time optimization +codegen-units = 1 # Single codegen unit for better optimization +panic = "abort" # Smaller binary, faster code +opt-level = 3 # Maximum optimization + +[profile.release-with-debug] +inherits = "release" +debug = true # Keep debug info for profiling + +# CPU-specific optimizations +[env] +RUSTFLAGS = "-C target-cpu=native -C target-feature=+avx2,+fma" +``` + +### Conditional Compilation for Hot Paths + +```rust +// Feature-gated optimizations +#[cfg(target_arch = "x86_64")] +unsafe fn optimized_x86_64_path(data: &[u8]) -> u32 { + // SIMD implementation + simd_checksum(data) +} + +#[cfg(not(target_arch = "x86_64"))] +fn generic_path(data: &[u8]) -> u32 { + // Portable implementation + data.iter().fold(0, |acc, &b| acc.wrapping_add(b as u32)) +} + +// Compile-time function selection +pub fn compute_checksum(data: &[u8]) -> u32 { + #[cfg(target_arch = "x86_64")] + unsafe { + optimized_x86_64_path(data) + } + + #[cfg(not(target_arch = "x86_64"))] + generic_path(data) +} +``` + +## Profiling and Measurement + +### Built-in Benchmarking + +```rust +use std::hint::black_box; +use std::time::Instant; + +// Prevent compiler optimizations from eliminating code +fn benchmark_function(name: &str, mut f: F) -> T +where + F: FnMut() -> T, +{ + let start = Instant::now(); + let result = black_box(f()); + let duration = start.elapsed(); + + println!("{}: {:?}", name, duration); + result +} + +// Example usage +fn performance_comparison() { + let data: Vec = (0..1_000_000).collect(); + + benchmark_function("Iterator chain", || { + black_box( + data.iter() + .filter(|&&x| x % 2 == 0) + .map(|&x| x * 2) + .sum::() + ) + }); + + benchmark_function("Manual loop", || { + let mut sum = 0; + for &x in &data { + if x % 2 == 0 { + sum += x * 2; + } + } + black_box(sum) + }); +} +``` + +## Key Takeaways + +1. **Profile before optimizing** - measure actual bottlenecks +2. **Memory layout matters** - align hot data structures +3. **Avoid allocations** in critical paths when possible +4. **Use SIMD** for data-parallel operations +5. **Choose the right atomic ordering** for your use case +6. **Leverage compile-time optimizations** with proper flags + +Remember: **Premature optimization is the root of all evil**, but when performance matters, these techniques can provide significant improvements. Always measure the impact of your optimizations! + +Happy optimizing! โšก๐Ÿฆ€ \ No newline at end of file diff --git a/index.html b/index.html index 4f794e4..b5ac54c 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -17,16 +17,452 @@ } + -
- \ No newline at end of file + diff --git a/src/blog.rs b/src/blog.rs new file mode 100644 index 0000000..f60396d --- /dev/null +++ b/src/blog.rs @@ -0,0 +1,181 @@ +use serde::Deserialize; +use pulldown_cmark::{Parser, html}; + +#[derive(Clone, Debug, Deserialize, PartialEq)] +pub struct Post { + pub slug: String, + pub title: String, + pub date: String, + pub excerpt: String, + pub content: String, +} + +/// Parse frontmatter from markdown content +/// Returns (title, date, excerpt, body) tuple +pub fn parse_frontmatter(content: &str) -> (String, String, String, String) { + let parts: Vec<&str> = content.splitn(3, "---").collect(); + + if parts.len() < 3 { + // No frontmatter found, return empty metadata + return ("Untitled".to_string(), "".to_string(), "".to_string(), content.to_string()); + } + + let frontmatter = parts[1].trim(); + let body = parts[2].trim(); + + let mut title = "Untitled".to_string(); + let mut date = "".to_string(); + let mut excerpt = "".to_string(); + + // Parse YAML-like frontmatter + for line in frontmatter.lines() { + let line = line.trim(); + if line.starts_with("title:") { + if let Some(title_value) = line.strip_prefix("title:") { + title = title_value.trim().trim_matches('"').to_string(); + } + } else if line.starts_with("date:") { + if let Some(date_value) = line.strip_prefix("date:") { + date = date_value.trim().trim_matches('"').to_string(); + } + } else if line.starts_with("excerpt:") { + if let Some(excerpt_value) = line.strip_prefix("excerpt:") { + excerpt = excerpt_value.trim().trim_matches('"').to_string(); + } + } + } + + (title, date, excerpt, body.to_string()) +} + +/// Convert markdown content to HTML +pub fn markdown_to_html(markdown: &str) -> String { + let parser = Parser::new(markdown); + let mut html_output = String::new(); + html::push_html(&mut html_output, parser); + html_output +} + +/// Parse a single post from slug and raw markdown content +pub fn parse_post(slug: &str, raw_content: &str) -> Post { + let (title, date, excerpt, markdown_body) = parse_frontmatter(raw_content); + let content = markdown_to_html(&markdown_body); + + Post { + slug: slug.to_string(), + title, + date, + excerpt, + content, + } +} + +/// Get all blog posts, sorted by date descending +pub fn get_all_posts() -> Vec { + let mut posts = Vec::new(); + + // Load all markdown files using include_str! + let hello_world_content = include_str!("../content/posts/hello-world.md"); + let getting_started_content = include_str!("../content/posts/getting-started.md"); + let rust_tips_content = include_str!("../content/posts/rust-tips.md"); + let my_new_topic_content = include_str!("../content/posts/What is an atomic increment.md"); + + // Parse each post + posts.push(parse_post("hello-world", hello_world_content)); + posts.push(parse_post("getting-started", getting_started_content)); + posts.push(parse_post("rust-tips", rust_tips_content)); + posts.push(parse_post("my-new-topic", my_new_topic_content)); + + // Sort by date descending (newest first) + posts.sort_by(|a, b| { + // Parse dates for comparison + let date_a = chrono::NaiveDate::parse_from_str(&a.date, "%Y-%m-%d") + .unwrap_or_else(|_| chrono::NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()); + let date_b = chrono::NaiveDate::parse_from_str(&b.date, "%Y-%m-%d") + .unwrap_or_else(|_| chrono::NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()); + + date_b.cmp(&date_a) // Descending order (newest first) + }); + + posts +} + +/// Find a specific post by slug +pub fn get_post_by_slug(slug: &str) -> Option { + get_all_posts().into_iter().find(|post| post.slug == slug) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_frontmatter() { + let content = r#"--- +title: "Test Post" +date: "2024-11-08" +excerpt: "This is a test excerpt" +--- + +# Hello World + +This is a test post."#; + + let (title, date, excerpt, body) = parse_frontmatter(content); + assert_eq!(title, "Test Post"); + assert_eq!(date, "2024-11-08"); + assert_eq!(excerpt, "This is a test excerpt"); + assert!(body.contains("# Hello World")); + } + + #[test] + fn test_markdown_to_html() { + let markdown = "# Hello\n\nThis is **bold** text."; + let html = markdown_to_html(markdown); + assert!(html.contains("

")); + assert!(html.contains("")); + } + + #[test] + fn test_parse_post() { + let content = r#"--- +title: "Test Post" +date: "2024-11-08" +--- + +# Hello World"#; + + let post = parse_post("test-slug", content); + assert_eq!(post.slug, "test-slug"); + assert_eq!(post.title, "Test Post"); + assert_eq!(post.date, "2024-11-08"); + assert!(post.content.contains("

")); + } + + #[test] + fn test_get_all_posts() { + let posts = get_all_posts(); + assert_eq!(posts.len(), 4); + + // Check that posts are loaded + let slugs: Vec<&str> = posts.iter().map(|p| p.slug.as_str()).collect(); + assert!(slugs.contains(&"hello-world")); + assert!(slugs.contains(&"getting-started")); + assert!(slugs.contains(&"rust-tips")); + assert!(slugs.contains(&"my-new-topic")); + } + + #[test] + fn test_get_post_by_slug() { + let post = get_post_by_slug("hello-world"); + assert!(post.is_some()); + + let post = post.unwrap(); + assert_eq!(post.slug, "hello-world"); + assert!(post.title.contains("Hello World")); + + // Test non-existent post + let missing_post = get_post_by_slug("nonexistent"); + assert!(missing_post.is_none()); + } +} \ No newline at end of file diff --git a/src/components/about_founder.rs b/src/components/about_founder.rs new file mode 100644 index 0000000..92ae0ce --- /dev/null +++ b/src/components/about_founder.rs @@ -0,0 +1,134 @@ +use leptos::*; + +#[component] +pub fn AboutFounderSection() -> impl IntoView { + view! { +
+ {/* Background Elements */} +
+
+
+ +
+
+ {/* Content Column */} +
+
+ + "Founder Story" + +
+ +

+ "Built by a Systems Programming " + + "Pioneer" + +

+ +
+

+ "Atomic Increment was founded by Andy Thomason, a systems programming expert with over 30 years of experience architecting game engines, compilers, and blockchain infrastructure. What started as a passion for teaching Rust at Oxford has grown into a consultancy trusted by enterprises to build high-performance, memory-safe solutions that scale." +

+ +

+ "From leading the UK's first Skillset-accredited MSc Games Development program to pioneering blockchain node development, Andy brings rare depth: someone who built production systems before Rust existedโ€”and now teaches the world why Rust solves problems they didn't know they had." +

+
+ + {/* Key Achievements */} +
+
+
+ "30+ Years Systems Programming" +
+
+
+ "Oxford University Instructor" +
+
+
+ "MSc Games Development Pioneer" +
+
+
+ "Blockchain Infrastructure Expert" +
+
+ + {/* CTA */} + +
+ + {/* Visual Column */} +
+
+ {/* Main Profile Card */} +
+ {/* Profile Header */} +
+
+ "AT" +
+

"Andy Thomason"

+

"Founder & Principal Engineer"

+
+ + {/* Stats Grid */} +
+
+
"30+"
+
"Years Experience"
+
+
+
"1000+"
+
"Students Taught"
+
+
+ + {/* Expertise Tags */} +
+ + "Game Engines" + + + "Compilers" + + + "Blockchain" + + + "Systems Programming" + +
+
+ + {/* Floating Elements */} +
+ + + +
+ +
+ + + +
+
+
+
+
+
+ } +} \ No newline at end of file diff --git a/src/components/contact.rs b/src/components/contact.rs index d533ddc..c35ecbb 100644 --- a/src/components/contact.rs +++ b/src/components/contact.rs @@ -1,83 +1,154 @@ use leptos::*; +use leptos::ev::SubmitEvent; #[component] pub fn ContactSection() -> impl IntoView { + let (submitted, set_submitted) = create_signal(false); + let (_entity_name, set_entity_name) = create_signal(String::new()); + let (_role_title, set_role_title) = create_signal(String::new()); + let (_contact_email, set_contact_email) = create_signal(String::new()); + let (_project_scope, set_project_scope) = create_signal(String::new()); + let (_budget_allocation, set_budget_allocation) = create_signal(String::new()); + let (_timeline, set_timeline) = create_signal(String::new()); + + let on_submit = move |ev: SubmitEvent| { + ev.prevent_default(); + set_submitted.set(true); + }; + view! {
-
-
-

- "Ready to Get Started?" +
+
+

+ "ENGAGEMENT INITIATION."

-

- "Let's discuss how we can help accelerate your project" +

+ "SUBMIT PROJECT PARAMETERS FOR ARCHITECTURAL REVIEW."

-
-
- - // - // -
-
- -
- - "Get In Touch" - +
+ {move || if submitted.get() { + view! { +
+

+ "PARAMETERS RECEIVED. ARCHITECTURAL REVIEW INITIATED." +

+
+ }.into_view() + } else { + view! { +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+ +
+ + +
+
+ +
+ +
+
+ }.into_view() + }}

} -} - -#[component] -fn ContactCard( - icon: &'static str, - title: &'static str, - description: &'static str, - action: &'static str, - link: &'static str, -) -> impl IntoView { - let is_link = !link.is_empty(); - - view! { -
-
{icon}
-

{title}

-

{description}

-
- {if is_link { - view! { - - {action} - - }.into_view() - } else { - view! { - {action} - }.into_view() - }} -
-
- } } \ No newline at end of file diff --git a/src/components/core_capabilities.rs b/src/components/core_capabilities.rs new file mode 100644 index 0000000..c200772 --- /dev/null +++ b/src/components/core_capabilities.rs @@ -0,0 +1,108 @@ +use leptos::*; + +#[component] +pub fn CoreCapabilitiesSection() -> impl IntoView { + view! { +
+
+
+

+ "Core Capabilities" +

+

+ "Advanced technical expertise delivering robust, high-performance solutions" +

+
+ +
+ + + + + + +
+
+
+ } +} + +#[component] +fn CapabilityCard( + title: &'static str, + description: &'static str, + icon_type: &'static str, +) -> impl IntoView { + view! { +
+
+ {/* Icon */} +
+ {match icon_type { + "performance" => view! { + + + + }.into_view(), + "security" => view! { + + + + }.into_view(), + "optimization" => view! { + + + + }.into_view(), + "expertise" => view! { + + + + }.into_view(), + "architecture" => view! { + + + + }.into_view(), + "data" => view! { + + + + }.into_view(), + _ => view! { +
+ }.into_view(), + }} +
+ + {/* Content */} +

{title}

+

{description}

+
+
+ } +} \ No newline at end of file diff --git a/src/components/features.rs b/src/components/features.rs index 9f829a3..58018cb 100644 --- a/src/components/features.rs +++ b/src/components/features.rs @@ -3,50 +3,39 @@ use leptos::*; #[component] pub fn FeaturesSection() -> impl IntoView { view! { -
+
-
-

- "What Makes Us Different" +
+

+ "Areas of Expertise"

-

- "Our expertise spans across modern technologies and proven methodologies" +

+ "Comprehensive Rust solutions tailored to accelerate your development cycle and optimize system performance"

-
-
- - - - - - -
+
+ + +

@@ -54,17 +43,70 @@ pub fn FeaturesSection() -> impl IntoView { } #[component] -fn FeatureCard( - icon: &'static str, +fn ExpertiseCard( title: &'static str, description: &'static str, + cta_text: &'static str, + cta_link: &'static str, + icon_color: &'static str, ) -> impl IntoView { + let icon_classes = match icon_color { + "blue" => "bg-blue-100 text-blue-600", + "purple" => "bg-purple-100 text-purple-600", + "emerald" => "bg-emerald-100 text-emerald-600", + _ => "bg-gray-100 text-gray-600", + }; + + let cta_classes = match icon_color { + "blue" => "text-blue-600 hover:text-blue-700 border-blue-200 hover:border-blue-300 hover:bg-blue-50", + "purple" => "text-purple-600 hover:text-purple-700 border-purple-200 hover:border-purple-300 hover:bg-purple-50", + "emerald" => "text-emerald-600 hover:text-emerald-700 border-emerald-200 hover:border-emerald-300 hover:bg-emerald-50", + _ => "text-gray-600 hover:text-gray-700 border-gray-200 hover:border-gray-300 hover:bg-gray-50", + }; + view! {
-
-
{icon}
-

{title}

-

{description}

+
+ {/* Icon */} +
+ {match icon_color { + "blue" => view! { + + + + }.into_view(), + "purple" => view! { + + + + }.into_view(), + "emerald" => view! { + + + + }.into_view(), + _ => view! { +
+ }.into_view(), + }} +
+ + {/* Content */} +

{title}

+

{description}

+ + {/* CTA */} +
} diff --git a/src/components/footer.rs b/src/components/footer.rs index eeb6e02..cc1f346 100644 --- a/src/components/footer.rs +++ b/src/components/footer.rs @@ -3,75 +3,221 @@ use leptos::*; #[component] pub fn Footer() -> impl IntoView { view! { -