Building a Website Framework with Django
How an analytics engineer accidentally built a multi‑site Django ecosystem by treating websites like data models.
Building a Django Framework That Powers All My Sites¶
How an analytics engineer accidentally built a multi‑site Django ecosystem by treating websites like data models.
For years, I kept rebuilding my personal site — not because I love redesigning, but because nothing ever fit the way my brain works. I’m an analytics engineer. I live in data models, relationships, transformations, and Python. I think in schemas. I think in reusable structures. I think in systems.
Most web tools don’t think that way.
I tried everything: ASP.NET WebForms back in the day, a half‑finished Razor Pages rewrite, a brief fling with Hugo, and a handful of “this time for real” prototypes that never made it past the honeymoon phase. Every attempt got me close, but never to something that felt natural.
This year, I finally stopped trying to rebuild a website and instead built the framework I should have made years ago — a Django‑based system that now powers three websites (and counting).
whitneyontheweb.com is just one tenant in the whole thing.
Why Django clicked for me¶
The real reason I chose Django is simple:
it matches how I think.
As an analytics engineer, I’m used to:
- defining models
- shaping data
- building transformations
- creating reusable logic
- and working in Python all day
Django lets me approach websites the same way. A page isn’t just HTML — it’s a model. A component isn’t just markup — it’s a reusable object. A site isn’t a pile of files — it’s a structured system with relationships and constraints.
Static site generators never gave me that. They’re great for content, but the moment I wanted structure, logic, or reuse, everything felt like a workaround.
Django felt like home.
From “a site” to “a framework”¶
Once I realized I wasn’t building a website — I was building a platform — everything changed.
I built a shared Django project with:
- a unified content model
- reusable templates and components
- a theming layer for per‑site branding
- shared utilities and helpers
- a consistent design system
- and a deployment pipeline that works across all sites
Now when I spin up a new site, I’m not reinventing anything. I’m just creating a new tenant in the system.
The modern stack that makes it fun¶
This isn’t old‑school Django. This is Django paired with a front‑end stack that feels lightweight and expressive:
- Tailwind CSS for styling without the CSS rabbit hole
- daisyUI for prebuilt components that don’t look like Bootstrap’s cousin
- Alpine.js for interactive sprinkles without a full SPA
- d3.js for the data‑viz playground I’ve always wanted
- Django Cotton for cleaner, more expressive templates
Individually, these tools are great. Together, they feel like a custom framework built around how I think — structured, reusable, Python‑first.
Why not a static site generator?¶
Because I don’t think in Markdown files.
I think in models.
Static site generators are fantastic when your site is mostly text. But the moment you want dynamic content, shared components, or anything that resembles an application, you start bolting on scripts and plugins until you’ve basically built a framework out of duct tape.
I wanted something that could grow with me — not something I’d outgrow again in six months.
The best part: everything is reusable now¶
Every improvement benefits every site:
- Add a new layout → all sites get it
- Fix a bug → fixed everywhere
- Build a new component → drop it into any project
- Want a new site → it’s basically “instantiate a new model”
It’s the first time my personal site hasn’t felt like a dead end. It’s part of a system — one that reflects how I actually think and work.
What I learned¶
- Your tools should match your brain, not the other way around.
- Frameworks aren’t “too heavy” if they remove friction.
- Reusability beats reinvention every time.
- Finishing something feels better than chasing the perfect stack.
And honestly? It feels good to finally have a setup that reflects how I actually build things — structured, reusable, Python‑first, and ready to grow.