# osgameclones: a YAML database rendered into a static site, a Makefile whose ci target tests nothing, and a docker build that prints its environment

> opengaming/osgameclones is the source of osgameclones.com, a list of open source game reimplementations kept as YAML files and validated against two schemas. Everything else about it is a small static site pipeline: poetry, a renderer, an nginx image. The parts worth reading are the Makefile targets that do not match their names and the build stage that echoes its own environment.

**opengaming/osgameclones** — Open Source Clones of Popular Games

- Repository: https://github.com/opengaming/osgameclones
- Website: https://osgameclones.com/
- Stars: 3,144 · Forks: 452
- Language: Python
- License: NOASSERTION
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/opengaming-osgameclones

## The database is YAML in the repository, validated by two schemas

The site is generated from files that live in the repository. All the games and their references to the original games are stored as YAML under games/ and originals/, and the readme's only guidance on their contents is that all information is inside and that reading them should make the structure clear.

Two schemas do the real work. Every game is validated against the rules in schema/games.yaml, and every original-game entry against schema/originals.yaml. The second schema matters because the database is relational in practice: all games listed need an original game they reimplement or clone, and if no entry exists in originals/ for it, a contributor creates one following the stated format.

Contribution has two routes, and the second is the one the project prefers. You can fill in a game form served when you open a new issue, or edit the YAML files directly and submit a pull request. Both forms live on the deployed site, at its add_game.html and add_original.html pages.

One presentation decision is stated outright: sorting is alphabetical, with the single exception of ScummVM, because it is that many games at once.

## The readme says make builds the site, and make runs the renderer

The contributing section promises a one command build:

```
make
```

There is no default target in the Makefile. The first target is run, and its recipe is the renderer itself, poetry run python render.py. So the command the readme describes as building the project into the _build directory does build it, but by way of the same recipe the ci target uses, rather than through a target named build or all.

The rest of the file names things more precisely than the readme does. There is min, which minifies the built index, poetry, which installs poetry itself through pipx, and poetry-install, which runs poetry install with the --no-root flag, a small difference from the bare poetry install the readme gives for setup. The prod target chains them, poetry, poetry-install, run, min, so the full local pipeline is four steps behind a single name.

One declaration is empty. The phony line is written as .PHONY: with nothing after the colon, rather than listing the targets it is meant to cover, so run, prod, docker-build and docker-run are never actually marked phony.

## The target named ci installs and renders, and nothing else

The Makefile has a target called ci, and it is two commands long:

```
poetry run python render.py
```

preceded in the recipe by poetry-install, which installs dependencies without the root package. So ci means install dependencies and build the site. It runs no test command, and there is no test target in the file and no test directory in the root of the repository.

Correctness for this project is enforced somewhere else entirely: by the two schema files that every game and every original entry is validated against, plus a yamllint configuration file in the root. A malformed record is caught by validating a record, not by asserting behaviour.

That is a reasonable design for a static catalogue, but it does mean the name ci covers none of the work the word usually implies, so anyone wiring this into a pipeline should read the recipe before trusting the label.

## The docker builder echoes its own environment into the build log

The image is built in two stages, and the first one is where the surprises are.

The builder starts from alpine, creates /src and /app, copies the repository into /src, and copies a file called CHECKS into /app. It installs curl, make, gcc, musl-dev, libffi-dev, python3 and python3-dev with apk, and then installs poetry by piping a remote installer script straight into the interpreter:

```
curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 -
```

Between the package install and that line sits a standalone RUN env. It is a debugging leftover, and its effect is that every environment variable present at build time is written into the image build log, which is where build arguments and any injected values end up visible to anyone with access to the registry or the CI log.

The second stage is nginx:1.27.4-alpine. It copies the built site from the builder into the web root, installs a vhost.conf as the default server configuration, copies CHECKS in again, and exposes port 80. So CHECKS travels into the final image, where a static file server has no use for it.

## The container publishes port 80 by default and deletes the previous one first

Two make targets cover the container path, and the readme walks through both:

```
make docker-build
```

builds an image tagged opengaming/osgameclones, matching the repository's own namespace. Running it is the second target, which first removes any previous container and then starts a new one:

```
-docker rm -f osgameclones-site
docker run -d -p${PORT}:80 --name osgameclones-site opengaming/osgameclones
```

The leading dash on the remove line tells make to ignore its failure, so the target works on a first run where no container exists. The port variable defaults to 80 in the Makefile, which means the default mapping publishes the container's port 80 straight onto host port 80, and the readme's alternative form, make docker-run PORT=3000, moves it to 3000. Either way the site is served over plain http from nginx with no certificate in the picture, which matters because this is a public catalogue rather than a local-only build.

## Three generated-looking files sit at the root next to the templates directory

The root listing mixes inputs with things that look like outputs. index.html, game.html and feed.xml sit at the top level, beside a templates/ directory and a static/ directory, and the renderer's job is to write into _build, which does not appear in the root at all.

Which of those root files are sources and which are leftovers is not stated anywhere in the readme, and that matters when you are about to edit a page: changing the wrong one of a pair costs a rebuild to discover.

Two other root files deserve a mention. _ext.py is a Python module sitting beside render.py, and nothing in the readme says what it extends or who imports it. CHECKS, the file copied into both docker stages, is likewise never explained; it is the only file in the repository that the readme does not mention at all, apart from the fact that it is copied into a running image.

## Version 1.0.0 with no releases, and a licence declared twice

The manifest is small and worth reading in full, because it tells you what the site depends on.

The project is named osgameclones at version 1.0.0, and it requires Python 3.12 or newer but below 4.0. Six runtime dependencies do the work: natsort for natural ordering, pykwalify and pykwalify-webform for schema validation and the web forms that back the issue templates, Unidecode and python-slugify for turning titles into URL slugs, and htmlmin for the minification step.

The development group is a different story, with pandas, mistletoe, feedparser, httpx, pygithub, tenacity, yamllint, beautifulsoup4 and thefuzz, which reads like tooling for fetching and checking upstream material rather than for rendering a static site.

Two inconsistencies sit at the edges. The version has been 1.0.0 since the start and the repository has no GitHub releases, so there is nothing to install a version from. And the licence is declared as MIT in the manifest with a LICENSE file in the root, while the project's own metadata field is left unasserted rather than naming a licence.

## Conclusion

Use it if you want to contribute a reimplementation to an existing catalogue, and follow the documented route: open an issue to get the form, or edit the YAML under games/ and submit a pull request, keeping both schemas satisfied. Two things to know before touching the build. The target named ci installs and renders rather than testing anything, so correctness rests entirely on schema validation. And the docker builder echoes its full environment into the build log, which is worth removing before anyone builds this with secrets in build arguments.

## FAQ

### What is osgameclones?

It is a catalogue of open source clones and remakes of games, and the repository is the source of the site osgameclones.com. The games and the original games they reference are stored as YAML under games/ and originals/, rendered into a _build directory and, in the container path, served by nginx on port 80.

### How do I add a game to osgameclones?

Either fill in the game form served when you open a new issue, or edit the YAML files in the games directory directly and submit a pull request, which the readme prefers. Every game is validated against schema/games.yaml, and each one must reference an entry in originals, which is validated against schema/originals.yaml.

### How do I run osgameclones locally?

Install poetry, which is the only stated prerequisite, then run poetry install inside the cloned directory and run make, which builds the project into the _build directory. For containers the readme gives make docker-build followed by make docker-run, with the host port chosen through the PORT variable, for example make docker-run PORT=3000.

### Is cloning a game legal?

The repository takes no position on that question. It collects open source reimplementations, records which original game each one reimplements or clones in a separate entry, and invites additions by pull request or issue. Whether any given reimplementation is permitted depends on its own licence, which nothing here assesses.

### What is osgameclones built with?

Python, declared as requiring version 3.12 or newer and below 4.0. Runtime dependencies are natsort, pykwalify, pykwalify-webform, Unidecode, htmlmin, and python-slugify. The development group adds beautifulsoup4, httpx, mistletoe, pandas, feedparser, tenacity, yamllint, pygithub, and thefuzz.

## Sources

- [Issues](https://github.com/opengaming/osgameclones/issues)
- [opengaming/osgameclones on GitHub](https://github.com/opengaming/osgameclones)
- [Project website](https://osgameclones.com/)
- [README](https://github.com/opengaming/osgameclones/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/opengaming-osgameclones
