/lunalux.io

The code running my personal website. 🌐🏠

Primary LanguagePythonMIT LicenseMIT

Hi 👋, I'm Luna!

The code that runs my personal website, lunalux.io. Feel free to inspect, use, or be inspired by the code, but keep in mind, it was made to fit my needs and may not be suitable for your use case.

ToC

Overview

The website is based on Wagtail CMS, and is primarily structured as a blog.

Each page is an instance of the Page model, and the content is created in the admin interface using predefined components that I have created in home/templates/blocks, but some special pages are defined as django view functions primarily located in home/views.py.

The main content pages are HomePage, and Article which are located in home/models/page_models.py. HomePage is meant to be flexible enough to create a wide range of layouts whereas Article is constrained to be in a blog-post format. However, since most pages are Article instances, I have developed more components for that. The most notable use of HomePage is the index page.

For a more thorough documentation of the features and changelog of the website, you can read the colophon page.

Dynamic Feeds

The Feed class is able to generate different dynamic RSS feeds based on the parameters submitted. Combined with the user interface, it is easy for visitors to generate a personal feed with the content types, tags, and content maturity they're interested in.

Bidirectional linking

Whenever an Article is saved, the body is scanned for internal links (see _add_interpage_links_from_html_field on AbstractPage) to other articles. If an internal link is found, a InterPageLink is created between the two articles. This is used to create a "Continue Reading" section at the bottom of each article.

Hover Preview

When hovering over internal links in the body of Article instances, a preview will show.

Trending pages

Whenever a page is rendered, we save a PageHit object to the database. We use these to find the trending pages on the site by counting the number of hits in the last 7 days (see AbstractPage.get_trending_articles). This is used to create the "Trending" section on the index page.

Interactive widgets

In some articles, I include interactive widgets such as in Gradient Descent. These are one-off components located in home/templates/oneoff_blocks.

HTMX

I use HTMX to improve the user experience several places on the site. I use it for search to automatically load search results as you type. I use it to lazy load fragments of articles (see get_template method on Article), and to avoid full page reloads when navigating between links within the article using hx-boost.

Installation

Make sure that you have one of the following Python versions 3.11, 3.12, if not, I recommend using pyenv to manage your Python versions.

1: Create a virtual environment and install the dependencies:

python3 -m virtualenv venv
source venv/bin/activate
pip install -r requirements.txt

Note if running in production mode, you should install requirements_production.txt in addition to requirements.txt.

2: Apply migrations:

python3 manage.py migrate

3: Create superuser

python3 manage.py createsuperuser

4: Run the development server:

python3 manage.py runserver

If you go to localhost:8000 in your browser, you should see Welcome to your new Wagtail site! and be able to log in to the admin interface at localhost:8000/admin/ with your username and passwords.

You can now start to set up your website using my components. You can use the Wagtail documentation to learn more about how to use Wagtail.

Deployment

To deploy to production, you can load the application in wsgi_production.py which loads the production settings.

I use gunicorn to run the application and nginx as a reverse proxy.

Note: You will have to change the settings to be suitable for your production environment, primarily the hostname.