← all builds

From-Scratch Build · Academic Web

Academic Personal Website

A self-hosted personal site for a researcher — publications, projects, talks and courses — where every word is editable from an admin panel instead of hand-coded HTML. Rebuilt from scratch to understand how a database-backed Django site is actually wired together.

Django 5htmxSQLite MarkdownDocker

What it is

A CV that edits itself

Most academic homepages are static HTML that goes stale the moment you give a new talk or publish a new paper. This is the opposite: a content-managed personal site where publications, projects, research lines, talks and courses all live in a database, and the owner edits them through a private admin instead of touching code.

I built it to learn the full server-rendered web model — not a single-page app, but classic Django: a request comes in, a view queries the database, a template renders HTML, and the browser gets a finished page. The only sprinkle of interactivity comes from htmx, which lets sections of a page update without a full reload.

The core idea I wanted to learn: the content and the presentation should be separate. The same template renders whether there are three publications or three hundred — the page is a view of a database, not a hand-written document.

The stack

Tools under the hood

The point of this rebuild was the toolchain. Here is what each piece actually does in the system.

framework

Django 5

The Python web framework that does the heavy lifting — URL routing, the ORM, templating, and a generated admin site for editing content.

data

Models & ORM

Each content type — Publication, Project, Talk, Course, ResearchLine — is a Python class. Django turns it into a table and into admin forms automatically.

interactivity

htmx

Adds AJAX to plain HTML via attributes. Filtering a publication list swaps in just the new rows instead of reloading the whole page.

content

Markdown

Long-form text (bios, project write-ups) is authored in Markdown and rendered to HTML, so the admin doesn't have to write tags by hand.

storage

SQLite + Pillow

A single-file database for content, with Pillow handling uploaded images — banners, project shots and profile photos.

packaging

Docker Compose

The whole app — Python, dependencies, the database file — ships in one container, so it runs identically on a laptop or a server.

Architecture

How a page gets built

Every page follows the same server-rendered path. Tracing it once made the whole framework click.

  1. URL routing live

    A path like /publications/ is matched against a URL map and handed to the matching view function.

  2. View + ORM query live

    The view asks the database for the records it needs — all talks, this year's papers — through Django's ORM, no raw SQL.

  3. Template render live

    The data is poured into an HTML template that extends a shared base.html layout.

  4. htmx partials live

    Filtered lists render a small partial template and htmx swaps it into the page — no full reload.

  5. Admin editing live

    The site owner logs into Django's admin to add a paper or edit a bio; the public pages update instantly.

  6. SEO & sitemap live

    A generated sitemap and per-page metadata so search engines can index the researcher's work.

How it runs

One command to a full site

The build is designed so a non-technical owner never sees the code. The workflow is:

In my rebuild I focused on getting the model layer right first — because in Django, once the models are sound, the admin, the views and the templates all fall out of them.

Reflection

What rebuilding it taught me