- Ruby 42.8%
- HTML 35.3%
- CSS 20.7%
- JavaScript 0.7%
- Dockerfile 0.4%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
add evolutions feature, move to new database A bunch of stuff was done here! I added a new evolutions feature that shows the evolutions for each Pokémon, updated to the new database and did a few other things. The evolutions feature is still not 100% done but I think it works well enough that it can be released on the main branch. |
||
| .woodpecker | ||
| app | ||
| config | ||
| public | ||
| views | ||
| .dockerignore | ||
| .gitignore | ||
| .herb.yml | ||
| .rubocop.yml | ||
| .ruby-version | ||
| BENCHMARKS.md | ||
| config.ru | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.alpine | ||
| Dockerfile.dev | ||
| Dockerfile.old | ||
| Gemfile | ||
| Gemfile.lock | ||
| LICENSE | ||
| logo.png | ||
| Makefile | ||
| README.md | ||
| routes.md | ||
| screenshot.png | ||
| server.rb | ||
| theriodex.service | ||
| TODO.md | ||
Most established Pokédex sites are filled with ads and tracking and use a lot of bandwidth. Additionally, a lot of them can be somewhat hard to navigate as they contain a lot of information – which is great in general, but if you just want to quickly look up a Pokémon's moves in a particular generation or see its stats, it can be a bit of a hindrance and this is where Theriodex comes in.
Theriodex is designed to be fast and easily glancable with information clearly laid out and meant as a complementary tool for other, more detailed websites. Across a test of numerous Pokémon and move pages, Theriodex consistently requires much less data to fully load, even with adblock enabled on other sites:
| Site | Avg Weight (Baseline) | Avg Weight (EasyList) |
|---|---|---|
| Theriodex | 98 KB | 98 KB |
| Bulbapedia | 2148 KB | 893 KB |
| Serebii | 3712 KB | 2487 KB |
| PokémonDB | 757 KB | 219 KB |
Note: Tests were conducted in July 2026 from a German IP address using a headless Chromium setup and hitting the official https://theriodex.net installation. The pages tested were: Gligar, Pikachu, Charizard, Mewtwo, Bulbasaur's moves in Gen IX and Poison Sting move info. Each page was tested five times with and five times without EasyList blocking.
Try it out at theriodex.net and see for yourself!
Info: The name Theriodex comes from
therio-(Ancient Greek for "animal" or "beast") and-dex(reference to the Pokédex).
Table of Contents
Features
Core Pokédex Information and Features
- All 1000+ Pokémon through Generation IX, including regional variants, mega evolutions and other special forms
- A quick overview of type damage, taking dual-types into account, so you can see at a glance what a Pokémon is weak or resistant to
- Full move learnsets (level-up, TM/HM, egg, tutor) with STAB highlighting
- Ability descriptions, plus which Pokémon can actually have them
- Base stats and full evolution overviews
- Plenty of sprites for all Pokémon from various generations
- A random Pokémon on the homepage if you just want to go and explore (there are so many Pokémon…)
- An evolution tree with information about when a Pokémon evolves into another and what requirements there are for its evolving
Browsing
- Filter by type, generation, and more
- A full item database with descriptions and effects
- Fast, fuzzy search across both Pokémon and moves
- Interface localisation via a lang parameter (still a work in progress, see below)
Game
- A "Who's That Pokémon?"-type guessing game, with blurred sprites, adjustable difficulty, and a daily challenge
- Filter by generation if you want to practise, say, only Gen 3
- A global leaderboard backed by Redis
Customisation
- A handful of pixel fonts to pick from
- Various themes, some of which you'll have to unlock by playing the game
- Custom CSS cursor packs
- Cards or table view, whichever you prefer for browsing
Quick Start
Prerequisites:
- Docker and Docker Compose installed on a supported operating system – mostly Linux or macOS (Windows might be supported but no guarantees!).
- Approximately 512 MB of available RAM (you should be fine with less, but this number is a safe one)
- Two CPU cores
Note: Should you have less cores or RAM available to you, please read the sections below on how to disable Puma workers; this will allow you to run Theriodex (at the expense of much worse concurrent user performance) on lower-end hardware.
First, create a new folder with a docker-compose.yml file and edit it to include the following text. You may also use the docker-compose.yml file from this repository.
services:
theriodex:
image: codeberg.org/hexaitos/theriodex:latest
platform: linux/amd64
ports:
- "5678:5678"
environment:
- REDIS_HOST=redis
depends_on:
- redis
volumes:
- ./privacy.md:/usr/src/app/views/privacy.md
- ./public/sprites:/usr/src/app/public/sprites
- ./public/cries:/usr/src/app/public/cries
restart: unless-stopped
redis:
image: valkey/valkey:latest
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
redis_data:
Afterwards, create another file titled privacy.md in the same folder and copy your privacy policy into that file. You may also leave it empty if you do not wish to have one at all, but you must change the privacy policy, you may not use the one included in this repository.
Additionally, should you wish to have sprites and sounds, you will be required to download those separately. See the section further below on how to acquire these.
You can then start Theriodex with the following command:
(sudo) docker compose up -d
Theriodex will be available at http://localhost:5678 after the images have been downloaded. The -d flag makes it start as a daemon so that it all runs in the background and so that it autostarts when you start your computer / server. To make it available on the public Internet, please follow the instructions in the Reverse Proxy section.
Podman notes: The above-mentioned
docker-compose.ymlfile works without any problems under Podman as well! Simply install podman and podman-compose (or docker-compose) and runpodman compose up -dinstead.
Installation (advanced)
For most folk, the Quick Start should be sufficient to get started. If you want to run it without Docker or have different requirements (like using a different operating systems like OpenBSD), this section is for you.
Docker
Pre-built Image (Recommended)
(sudo) docker run \
--name theriodex \
-e REDIS_HOST=REDIS_HOST_HERE \
-p 5678:5678 \
-d \
codeberg.org/hexaitos/theriodex:latest
The container is linux/amd64 only.
Building from Dockerfile
Clone the repository and build using the provided Dockerfile (follow standard Docker build procedures). This is a required step if you wish to run Docker but need to adjust the amount of Puma workers or if you wish to disable workers entirely.
From Source
Requirements: Ruby (tested with 4.0.5) and Bundler.
- Clone the repository
- Run
bundle installto install gems - Place the
spritesfolder in/public/(see Sprites and Sounds) - Start the server:
puma -C config/puma.rb
Production Mode
# Production mode with Puma (recommended for multi-worker):
REDIS_HOST="localhost" puma -C config/puma.rb
# Production mode (single process, no Puma config):
REDIS_HOST="localhost" ruby server.rb -e production
Important: Redis is required by default and needs to be used when using Puma workers. If you do not need a multi-worker setup, please read the Session Storage section on how to disable
Rack::Session::Redisand switch toRack::Session::Pool. Redis is still required for the leaderboard functionality, but otherwise, Theriodex will run well without Redis otherwise if you follow the steps outlined.
Puma workers
Because the SQLite database that Theriodex uses is read-only, multi-threading with Puma can easily be used and is enabled by default in the Docker image. The Docker sets a somewhat safe default of two workers, this should run comfortably even on lower-end systems.
If you wish to adjust the values for your own use case, please edit the config/puma.rb and adjust the workers and threads values accordingly.
Please note that each new worker will almost double the required amount of RAM used by Theriodex. One instance of Theriodex uses approximately 190 MB of memory. A two-worker installation already can require 300+ MB of memory; the reason for this is that each worker will need to spawn its own instance of Theriodex.
This brings us to yet another important point. As each worker spawns its own session, sessions need to be stored in a central location; thus, the default, multi-worker Puma setup requires Rack::Session::Redis for session storage.
I would highly recommend at least two Puma workers to be used. On a stress test / performance test conducted with Locust and 100 users (starting at one user and increasing by one user every second for 2 minutes and 20 seconds), we saw a performance increase from a median of 1,456ms with the default Puma configuration to a median of 430ms with the two-worker configuration.
YJIT
We recommend using YJIT in production installation, especially those that expect a large traffic volume.
What is YJIT?
This is especially helpful if you are trying to run Theriodex in an environment where you expect a lot of requests and a lot of traffic. YJIT (Yet Another Ruby JIT) is a just-in-time compiler for Ruby. Essentially, what it does is it observes the program and notices when certain things get executed a bunch of times over and over again (especially when they use the same types, such as always integers or always strings). It then compiles it to regular bytecode that the CPU can execute directly without needing to go through the Ruby interpreter.
This can save considerable time in the execution of your program – because the interpreter is much slower than bytecode directly executed by the CPU –, but this compiled bytecode has to be stored somewhere, namely in memory. This means that you can expect a performance increase but also an increase in memory usage. The observed increase in performance is around 10-20% depending on workload with an increase in memory usage of about the same amount.
How to use YJIT
If you use the official docker container, YJIT will already be enabled. If you are running Theriodex on bare hardware, you will need several things:
- Ruby compiled with Rust support. For this, your system will need the
rustccompiler. Please check how to install this for your operating system! - Setting the
ENV RUBY_YJIT_ENABLE=1environment variable in your environment
If you use a Ruby version management tool such as rbenv and rbenv install (which I, personally, use), then – once you have the rustc compiler installed – you can simply run rbenv install 4.0.5 (or whichever version is current at the time of your reading this) and enable it locally in Theriodex by running rbenv enable 4.0.5.
You can check whether the installation was successful by running RUBY_YJIT_ENABLE=1 ruby -e "puts RubyVM::YJIT.enabled?". This command should simply output true if Ruby has been compiled with YJIT support. Start the server as follows:
# Production mode with Puma (recommended for multi-worker):
RUBY_YJIT_ENABLE=1 REDIS_HOST="localhost" puma -C config/puma.rb
# Production mode (single process, no Puma config):
RUBY_YJIT_ENABLE=1 REDIS_HOST="localhost" ruby server.rb -e production
jemalloc
We urge you use jemalloc if you are using Puma workers, but it is recommended in either case to avoid high memory usage.
Why use jemalloc
We have found that GLib's malloc seems to cause some issues, especially when using multi-worker setups with Puma causing the memory usage to baloon way above what is reasonable without properly being able to free memory again. After having run Theriodex for about 15 hours on a VPS and having done a few traffic tests, memory had balooned to over 1.6 GB with heavy swapping – on a VPS that only has 2 GB of physical memory and 1 GB of zram.
The Theriodex Docker container reported around 800 MB of memory usage while using about the same amount again in swap. Having found out about that, we ended up switching over to jemalloc which has reduced the memory footprint dramatically. After further tests, memory now plateaus at around 500-600 MB with two workers in total rather than more than 1.6 GB.
How to install jemalloc
The installation of jemalloc differs from system to system. These instructions are for installations on Linux or macOS, specifically! Firstly, you will need to install jemalloc on your system using your system's package manager:
# macOS
brew install jemalloc
# Ubuntu, Debian and derivatives
sudo apt install libjemalloc-dev
# Fedora
sudo dnf install jemalloc-devel
# Arch and derivatives
sudo pacman -S jemalloc
Afterwards, you have several options of using jemalloc with your Ruby installation. First, check if your Ruby version is, perhaps, already compiled with jemalloc. Run ruby -r rbconfig -e 'puts RbConfig::CONFIG["configure_args"]' in your terminal. If the output includes --with-jemalloc, then your Ruby version is already using it. If not, follow the steps below to install it.
Scenario 1 – Compiling Ruby with jemalloc support
If you are able to compile your Ruby version yourself, you can compile it with the --with-jemalloc flag. If you use rbenv, you can do so as follows: RUBY_CONFIGURE_OPTS="--with-jemalloc" rbenv install 4.0.5
Scenario 2 – Using LD_PRELOAD (if you cannot change your Ruby installation)
If you are unable to change your Ruby installation, you can still use jemalloc with the caveat of your needing yet another environment variable, name LD_PRELOAD. First, figure out where your jemalloc library is located by running find /usr/lib /usr/local/lib -name "libjemalloc.so*". You should receive a list of various library files such as this:
/usr/lib/libjemalloc.so
/usr/lib/libjemalloc.so.2
Copy and remember the path of the libjemalloc.so.2 file and then start Ruby with the LD_PRELOAD=/path/to/jemalloc.so.2 environment variable. For example, on my system (where it is located at /usr/lib/libjemalloc.so.2), it would look as follows:
# Production mode with Puma (recommended for multi-worker):
LD_PRELOAD=/usr/lib/libjemalloc.so.2 RUBY_YJIT_ENABLE=1 REDIS_HOST="localhost" puma -C config/puma.rb
# Production mode (single process, no Puma config):
LD_PRELOAD=/usr/lib/libjemalloc.so.2 RUBY_YJIT_ENABLE=1 REDIS_HOST="localhost" ruby server.rb -e production
Redis/Valkey
Redis (or Valkey) is used for two things:
- Leaderboard: Stores highscores for the "Who's That Pokémon?" guessing game
- Session storage: Stores session data such as UI customisation as well as game data as it is being played.
Configuration:
Set the REDIS_HOST environment variable:
REDIS_HOST="localhost" ruby server.rb -e production
Session storage
By default, Theriodex uses Rack::Session::Redis to store session data in Redis. This is required for multi-worker Puma, since in-memory sessions (Rack::Session::Pool) are not shared between workers.
If you are running a single process (no Puma workers), you can switch back to Rack::Session::Pool:
# In server.rb, comment out or remove the Redis session line:
# use Rack::Session::Redis, key: 'rack.session', expire_after: 86_400, url: "redis://#{ENV['REDIS_HOST']}:6379/0"
# And uncomment or add this line instead:
use Rack::Session::Pool, key: 'rack.session', expire_after: 86_400
Note:
Rack::Session::Cookieis unfortunately not really viable because the game session data (especially in longer sessions) may exceed the 4 KB cookie size limit.
Configuration
Sprites and Sounds
Sprites and cries are served from local storage, not GitHub.
- Sprites: Download from PokeAPI/sprites (~1.5 GB) and place the
spritesfolder in/public/ - Cries: Download from PokeAPI/cries (~30 MB) and place the
criesfolder in/public/
Note: Theriodex should work without sprites but then, of course, it will not display any of the images.
Database
The SQLite database (db.sqlite3) is derived from PokeAPI and Veekun's Pokédex. You can rebuild it yourself using PokeAPI's instructions and replace the included database. No modifications have been made yet, though migrations may be required in the future.
Leaderboard (Redis)
The guessing game uses Redis/Valkey for score tracking. Entries are stored in a sorted set score with format: USERNAME-YYYYMMDDHHMMSS>RANDOM_HASH.
Configuration:
Set the REDIS_HOST environment variable:
REDIS_HOST="localhost" ruby server.rb -e production
Reverse Proxy
To make your version of Theriodex publicly accessible, you will most likely want to put it behind a reverse proxy. My preferred method of doing so is by using Caddy, as it makes the whole process rather simple!
Let us assume that you have a server or other device which has a public IP and which is currently not hosting anything else – ports 80 and 443 are available and open to the public; let us also assume that you own the domain theriodex.net and have entered your servers public IP addresses into your domain registrar so that theriodex.net points to the public IP address(es) of your server.
You can, then, simply install Caddy and use the following configuration assuming that you use the default port of 5678:
theriodex.net {
@assets path *.css *.js
@images path *.png *.jpg *.jpeg *.gif *.svg *.webp *.ico
@fonts path *.woff2 *.ttf
header @assets Cache-Control "public, max-age=3600"
header @images Cache-Control "public, max-age=2592000"
header @fonts Cache-Control "public, max-age=2592000"
reverse_proxy localhost:5678 {
header_down -Cache-Control
}
encode zstd gzip
}
Caddy will automatically obtain an SSL certificate for you and in just a few moments, your website should be available under theriodex.net and have HTTPS enabled! It also enables (hopefully) decent caching defaults.
Privacy Policy
This repo includes the privacy policy for my own hosted instance of Theriodex. This will obviously not apply to you, so if you wish to host it yourself, change the privacy policy under /views/privacy.md accordingly.
With Docker, mount your own policy:
docker run \
-e REDIS_HOST="redis_host" \
-p 5678:5678 \
-v /path/to/your/privacy.md:/usr/src/app/views/privacy.md \
theriodex
Development & Deployment
Auto-restart with rerun
The rerun gem auto-restarts the server when files change, useful for development or auto-updating deployments:
rerun -- ruby server.rb -e production
Caching
Theriodex uses rack-cache for disk caching. Configuration is in /app/helpers/vars.rb:
CACHE_DIR = "/tmp/cache/rack"
Cache is cleared on server start via this line in server.rb:
FileUtils.remove_dir(CACHE_DIR) if Dir.exist?(CACHE_DIR)
Disabling Caching
Use the no_rack_cache environment:
ruby server.rb -e no_rack_cache
Or manually remove all rack/cache references, cache_control lines, and the FileUtils.remove_dir call from server.rb.
Memory Caching
Change the cache stores to heap (not recommended for production due to unbounded growth):
use Rack::Cache,
:metastore => 'heap:/',
:entitystore => 'heap:/',
:verbose => true
See rack-cache documentation for details.
Platform Notes (OpenBSD)
Tested on OpenBSD 7.6 and 7.7 with Ruby 3.3.5/3.4.2.
Nokogiri Issues
You should be able to install bundler itself without any problems, but when running bundle install, you may run into problems with installing nokogiri. To solve this, running the following commands should make it work:
pkg_add libxml libxslt libiconv
bundle config build.nokogiri --use-system-libraries
bundle install
Permission Errors (Non-root)
You may also have trouble installing the gems in the repository by running bundle install and will get permission errors, as Bundler is unable to write to the directories it wants to write to. A possible fix for this problem is changing the directory that Bundler installs its gems into to something that the current user can access, such as ~/.gem. To do so, add the following to your ~/.profile:
Add to ~/.profile:
export GEM_HOME=$HOME/.gem
Or run:
echo 'export GEM_HOME=$HOME/.gem' >> $HOME/.profile
Acknowledgements
A special and immense thanks also to all my partners – who are way better at programming and database queries than I am – for helping me out a lot and answering my questions and giving helpful tips. I definitely would not have been able to get as far with this project if it hadn’t been for them. Thank you, I love you all 💛
Data sources:
Fonts:
Icons: Iconoir
- Logo: The fantastic logo was made by my partner Coyote 💛
Support the original creators! Please consider donating to / buying the fonts and icons used in Theriodex if you are a frequent vistor of theriodex.net or if you wish to host it yourself.
Copyright
Pokémon and Pokémon character names are trademarks of Nintendo, Game Freak, and Creatures Inc. Theriodex is not affiliated with, authorized, or endorsed by The Pokémon Company, Game Freak, Creatures, or Nintendo.
The project is licensed under the 3-Clause BSD License.
