Project Overview
This repository is the full implementation of my personal portfolio website. I built it as a central place to present my background, projects, hobbies, resume, and contact workflow while keeping content updates lightweight and maintainable.
Architecturally, the site uses a Flask app factory with blueprint-based routing, shared base templates/partials, and markdown-driven long-form content loaded from the static text directory. The goal was to keep page logic simple, make content easy to edit without touching Python code, and preserve a consistent visual system across all sections.
Implementation Highlights
- App factory + blueprints for clear route organization
- Reusable partials for top nav and footer
- Markdown content rendering from `app/static/text`
- Interactive gallery filtering and lazy-loaded images
- Resume page with embedded PDF and fallback handling
Key Features
- Content-First Markdown Pipeline: All long-form copy (about, projects, hobbies) lives in markdown files, not templates—enabling fast updates without code changes or redeployment.
- Modular Design System: Shared base templates and composable CSS modules (cards, banners, galleries) ensure visual consistency while allowing flexible page layouts.
- Persistent Theme Persistence: Dark/light mode toggle with localStorage support, maintaining user preference across sessions and routes.
- Rich Gallery Experience: Category-filtered photography gallery with Medium Zoom support, lazy loading, and incremental batching—optimized for image-heavy portfolios.
- Intelligent Resume Handling: Auto-detects static PDF resume files, embeds inline preview for modern browsers, and provides download fallback for compatibility.
- Fully Integrated Contact Workflow: End-to-end visitor contact pipeline with async email dispatch, validation, thank-you responses, and internal notifications—production-ready out of the box.
- Responsive & Accessible Navigation: Dynamic top-nav reveal behavior, active-link highlighting, and mobile-optimized menus ensure smooth navigation across all devices.
System Architecture
Design Philosophy: Separation of concerns to minimize maintenance burden. Content lives independently from code, templates are reusable and composable, and each layer has a single responsibility.
Core Layers:
- Application Bootstrap: Flask app factory in `app/__init__.py` centralizes configuration (paths, blueprints, middleware) and injects context helpers for templates.
- Routing & Views: Blueprint-based routing in `app/routes.py` organizes handlers into logical groups (`site_bp` for main pages, `hobbies_bp` for hobby subsections). Each route is a thin wrapper that loads content and renders.
- Content Management: Markdown files in `app/static/text` serve as the canonical source of truth. A `get_text_md()` helper converts markdown to HTML on-demand and caches results, eliminating the need for a database.
- Presentation Layer: Shared templates (`base.html`, `topnav.html`, `footer.html`) and modular CSS provide a consistent visual system. Page-specific templates compose these partials to minimize duplication.
- Email Integration: Markdown email templates in `app/utils/email` support both visitor thank-you and internal notification flows with full async dispatch and error handling.
Why This Matters: By decoupling content from code, non-technical contributors can update copy without touching Python. Markdown is version-controllable, diff-friendly, and search-engine friendly. Cached HTML rendering keeps page loads fast while eliminating database overhead. Modular CSS and reusable templates make it painless to add new pages or hobby sections.
Technologies Used
Backend: Python, Flask 3 (app factory pattern + blueprints), Gunicorn runtime support.
Frontend: Jinja templates, modular CSS, responsive media queries, vanilla JavaScript interactions.
Content: Markdown-based copy pipeline using `python-markdown` and static content organization.
Media & UI: Font Awesome icons, Medium Zoom integration, curated static image/video assets.
Email: `easy-email-builder` + markdown email templates for thank-you and notification flows.
Environment: `python-dotenv` for local config and sensitive credential management.
Challenges & Learnings
The biggest challenge was balancing content flexibility with maintainability. I wanted rich pages (projects, hobbies, resume, galleries) without hardcoding long blocks directly in templates. Moving long-form text into markdown files and building route-level helpers for content loading made updates significantly easier.
Another major lesson came from responsive UX consistency. As sections evolved independently, shared CSS needed stronger global conventions for spacing, banner overlays, nav behavior, and mobile formatting. Consolidating these concerns into common stylesheets improved both development speed and visual consistency.
Finally, implementing contact emails and resume preview functionality reinforced how useful clear fallback behavior is: if credentials are missing or embedded PDF preview fails, users still get a graceful, understandable path forward.