This is the source code to the ff4kb.aexoden.com web site, a knowledge base for Final Fantasy IV speedrunning. The site provides seed-specific step routes for numerous speedrun categories, guides for various techniques (e.g. seed manipulation, inventory warping), a game information database (monsters, formations, items, spells), and an interactive map viewer.
As long as I am maintaining the site myself, there is only limited utility to this code. Nonetheless, this provides a backup in case I stop maintaining the web site for any reason.
This project uses Devbox for its development environment. Install Devbox, then from the project root:
devbox shellThis will install uv and pre-commit, sync Python dependencies, and set up Git hooks automatically.
uv run manage.py migrate
uv run manage.py runserverThe site will be available at http://localhost:8000.
devbox run format # Check formatting (ruff)
devbox run lint # Lint and type check (ruff + mypy)Static game data lives in data/ as JSON files (items.json, monsters.json,
formations.json, spells.json, scripts.json). These are extracted from FF4
ROM files using scripts/dump_ff4_data.py. The ROM paths are listed in
scripts/roms.txt and would need to be adjusted for your environment. The
extracted JSON is committed to the repository, so ROMs are not needed to run the
site.
The data/routes/ directory contains the core content of the site: step-by-step
seed routes for each speedrun category. Each category (e.g. no64-excalbur,
no64-rosa) has a subdirectory with 256 text files (000.txt–255.txt), one
per seed. These files are generated by
rosa and include metadata (route version,
seed, variable configuration) followed by the step-by-step route instructions.
The cache/ directory contains pre-computed route metrics (aggregate statistics
across seeds for each route category). These are generated at build time by the
generate_metrics_cache management command and used on the route listing pages.
During development, they will be generated on demand if not already cached.
This site is currently deployed using a Coolify instance, and was historically deployed using dokku. However, the deployment is done using a standard Dockerfile, so in principle, it should be easy to deploy with other tools as well. There are certain environment variables that need to be set, either automatically by your PaaS solution or manually:
- DJANGO_ALLOWED_HOSTS: A comma separated list of domain names the app should
reply to. The default is
ff4kb.aexoden.combut this is almost certainly not what you want. - DJANGO_SECRET_KEY: Should be set to a random, unpredictable value. Generators are available on the web.
- ENVIRONMENT: Set to
Productionfor production. - PORT: The port to bind to. Set automatically by Dokku or Coolify. Defaults to 8000.
You will almost certainly need some sort of reverse proxy, either provided by Dokku, Coolify, etc. or manually configured.
One feature of this web site (using custom values for a route's variables)
requires a copy of rosa to be placed in the
rosa directory. The Dockerfile will take care of building and installing
this, but if you are doing some other form of installation, you will need to
handle the rosa installation yourself. Note that this feature currently has no
obvious public-facing interface, though if someone knew the correct parameters
to pass to the URL, they could access it.
This site's codebase was originally developed in late 2017. While it has evolved over time, parts of the design still reflect early choices that I now consider suboptimal or outdated. Though many improvements have been made, some aspects remain a product of their time. Specifically, the code still relies on too many nested dictionaries and contains many scattered magic numbers. A number of lints I would normally fix properly (mostly to do with magic numbers or complexity) are instead ignored. In addition, there is minimal testing architecture, leaving breakage all too easy to cause.
I do not currently have much interest in doing deep architectural improvements myself (and would be more tempted to rewrite everything in Rust), but well done pull requests are welcome.