Duke Apartments
A modern, performant web application for Duke Street Apartments in Vermillion, South Dakota. This full-stack project showcases apartment listings with an elegant UI, advanced image optimization, and progressive web app capabilities.
A modern, performant web application for Duke Street Apartments in Vermillion, South Dakota. This full-stack project showcases apartment listings with an elegant UI, advanced image optimization, and progressive web app capabilities.
Duke Apartments is a marketing website designed to provide prospective tenants with property information, an interactive photo gallery, and easy contact options. Built with a modern tech stack emphasizing performance and user experience, the site achieves fast load times through static site generation, responsive image delivery, and intelligent caching strategies.
The project follows a monorepo architecture with separate packages for the public-facing client and an admin dashboard, backed by Firebase serverless infrastructure.
Challenge: Serving optimized images across varying device sizes and connection speeds without manual asset management.
Solution: Implemented vite-imagetools to automatically generate multiple image formats (AVIF, WebP, PNG) and responsive srcsets during the build process. The browser selects the optimal format and size, reducing bandwidth by up to 70% on modern browsers.
Challenge: Creating a gallery that supports keyboard navigation, touch gestures, mouse interactions, and accessibility—all without external dependencies.
Solution: Built a custom event handling system with gesture tracking, event delegation, and proper focus management. The gallery responds to arrow keys, swipe gestures, and click/tap events while maintaining accessibility standards.
Challenge: Implementing robust form validation without adding heavy dependencies to a performance-focused static site.
Solution: Created a reusable Svelte action (use:formValidation) that provides event-driven validation, real-time error messaging, and form state management in minimal code.
Challenge: Adding analytics tracking to a pre-rendered static site without compromising build-time rendering or causing hydration issues.
Solution: Implemented conditional browser environment checks with lazy Firebase initialization, enabling full analytics functionality while maintaining zero server costs and fast initial page loads.
Challenge: Managing cache versions across deployments to ensure users receive updated content while still benefiting from caching.
Solution: Implemented versioned cache names with automatic cleanup of stale caches during service worker activation, ensuring smooth updates without manual cache invalidation.
| Technology | Purpose |
|---|---|
| SvelteKit | Full-stack framework with SSG capabilities |
| Svelte | Reactive, compiler-driven UI components |
| TypeScript | Type-safe development |
| Tailwind CSS | Utility-first styling |
| vite-imagetools | Build-time image optimization |
| Technology | Purpose |
|---|---|
| Firebase Hosting | Static site hosting with CDN |
| Firebase Analytics | User tracking and insights |
| Firestore | NoSQL database |
| Cloud Functions | Serverless backend |
| Technology | Purpose |
|---|---|
| Vite | Next-generation build tooling |
| pnpm Workspaces | Monorepo package management |
| GitHub Actions | CI/CD pipeline |
| Vitest | Unit testing framework |
| ESLint + Prettier | Code quality and formatting |
Image optimization is crucial: Implementing vite-imagetools reduced image payloads significantly while automating what would otherwise be tedious manual work.
Svelte actions are powerful: Custom actions like use:formValidation enable reusable behavior patterns that keep components clean and focused.
Service workers require careful versioning: Without proper cache management, users can get stuck on old versions. Versioned cache names solved this elegantly.
Monorepos simplify multi-site projects: pnpm workspaces allow shared configuration while maintaining independent build processes for each site.
Static sites can still be dynamic: Firebase Analytics and client-side interactivity prove that static generation doesn't mean sacrificing functionality.