Back to Projects
Django Backed Website

Django Backed Website

Full-stack Django portfolio with modular content-driven architecture, Docker containerization, and production deployment on AWS EC2

Project Philosophy

This portfolio website demonstrates practical full-stack development—from database design to production deployment. The core architecture is content-driven: every piece of content lives in the database rather than hardcoded templates. I can update the entire site through Django's admin interface without touching a single line of code.

Portfolio Homepage

The site you're looking at right now is the result of this project. Every section, skill, project description, and piece of content is managed through a custom Django admin interface. This means I can add new projects, update my skills, or modify any text without deploying new code—the database is the single source of truth.

Modular Django Architecture

The backend follows Django best practices with models designed for maximum flexibility. Rather than hardcoding content into templates, I built a comprehensive data model that represents every aspect of the portfolio.

Django Admin Interface

Data Models Include:
- Profile for personal information, bio, and site-wide settings
- SkillCategory and Skill for organized technology display with custom icons
- Experience for work history with linked skills and technologies
- Education for academic background
- Project with rich markdown descriptions and image galleries
- SocialLink for profile connections with custom or Font Awesome icons
- SiteSettings for global configuration like theme options

The Skill model is particularly flexible—it supports custom SVG icons, Font Awesome classes, configurable glow colors for hover effects, and links to external documentation. Projects reference skills through many-to-many relationships, automatically displaying appropriate icons and creating a cohesive visual language across the site.

Custom model methods handle computed properties like combining linked skills with custom technologies. Django admin customization includes inline editors, drag-and-drop ordering, and custom widgets that make content editing intuitive.

Frontend Development

The frontend uses semantic HTML5 with a custom CSS architecture built entirely on CSS custom properties (variables). No CSS framework—everything is hand-crafted for this specific design.

Theme Switching Demo

The theming system supports three modes: dark, light, and normal. Each theme defines its own set of CSS variables, and switching themes is as simple as changing a data attribute on the root element. Transitions are smooth, and the user's preference persists in localStorage.

Responsive design handles everything from 375px mobile screens to ultrawide desktop displays. The layout adapts using CSS Grid and Flexbox, with media queries at carefully chosen breakpoints that correspond to actual content needs rather than arbitrary device sizes.

Interactive Elements:
- Typing animation on the hero section with cursor that fades after completion
- Smooth scrolling navigation with active section highlighting
- Theme toggling with visual feedback tooltip
- Mobile hamburger menu with slide-out animation
- Scroll-triggered animations for content sections
- Skill tags with hover effects showing brand colors

Dependencies are minimal—no jQuery, no CSS frameworks like Bootstrap or Tailwind, just vanilla JavaScript and carefully architected CSS. The entire frontend weighs in at a fraction of what a framework-heavy site would require.

Docker Containerization

Docker provides consistency between development and production environments. The setup ensures that what works on my laptop works identically in production.

Docker Architecture

The multi-stage Dockerfile creates optimized production images:
1. Build stage installs dependencies and collects static files
2. Production stage copies only what's needed for a minimal footprint
3. Non-root user for security
4. Health checks for container orchestration

Docker Compose defines the complete application stack with volume mounts for persistent data (SQLite database, media uploads) and environment variables for configuration. Development and production compose files share a base configuration with environment-specific overrides.

Production Deployment

The production stack runs on AWS EC2 with Debian as the base OS:

  • Cloudflare handles DNS, provides CDN caching, and adds a security layer
  • Caddy reverse proxy manages automatic HTTPS with Let's Encrypt
  • Gunicorn serves the Django application with multiple workers
  • SQLite provides file-based persistence perfect for portfolio scale
  • WhiteNoise serves static files efficiently without a separate server

Deployment Architecture

Caddy was chosen specifically for its automatic certificate management—it handles Let's Encrypt issuance and renewal without any manual intervention, cron jobs, or certbot configuration. The Caddyfile is remarkably simple compared to equivalent Nginx configs.

Technical Challenges Solved

Theme System: CSS custom properties change based on a data-theme attribute, with JavaScript handling toggle and localStorage persistence. Colors needed to work across all themes while maintaining WCAG accessibility contrast ratios. The skill icons show their brand colors on hover, requiring careful CSS filter calculations.

Navigation Responsiveness: With seven navigation items plus a theme toggle, the horizontal nav overflowed on tablet-sized screens. The hamburger menu activates at 1100px with careful attention to slide-out animation, proper z-index stacking, and body scroll locking when the menu is open.

Markdown Rendering: Project descriptions support full markdown with syntax highlighting for code blocks. This required a custom template filter using Python-Markdown with extensions for fenced code blocks, tables, and table of contents. Comprehensive CSS ensures markdown content looks consistent with the site's design.

Section Ordering: The admin interface allows drag-and-drop reordering of homepage sections. This required a custom Django widget with JavaScript for the sortable interface and JSON field storage for the order configuration.

Lessons Learned

Planning data models before writing frontend code paid dividends throughout the project. The time invested in designing flexible models meant adding new sections or modifying content required no template changes—just database updates through the admin.

CSS architecture matters enormously. Starting with solid custom properties and consistent naming conventions made the responsive design and theming work much smoother than previous projects where I added styles ad-hoc. The BEM-ish naming pattern kept specificity manageable.

Choosing SQLite over PostgreSQL was the right call for this scale. No separate database server to manage, backups are just file copies, and performance is more than adequate for a portfolio site with low traffic.