# Teletype Games

Monorepo for the Teletype Games portal: a Vue 3 frontend, a Rails 8 API host app,
and the reusable **WarpEngine** software-catalog engine.

## Project structure

```
apps/
  frontend/            # Vue 3 + Vite + TypeScript + Tailwind SPA
  api/                 # Rails 8 host app: TTG-specific API + ActiveAdmin shell
libs/
  ruby/warp_engine/    # WarpEngine: mountable Rails engine (catalog, updater, admin resources)
```

The API is split in two layers:

- **WarpEngine** (`libs/ruby/warp_engine`) owns the software catalog: models
  (softwares, releases, release assets, images, platform links, download stats),
  the CI-callable `/update` endpoint, the public read-only JSON API
  (`/api/software*`, `/api/builds*`, `/api/image`, `/api/download`, `/file/*`)
  and the catalog ActiveAdmin resources. See its [README](libs/ruby/warp_engine/README.md).
- **The host app** (`apps/api`) owns everything TTG-specific: members, events,
  wiki proxy, RSS feeds, Devise/ActiveAdmin authentication, theming and assets.
  It consumes WarpEngine as a path gem and mounts it at `/`.

## Development environment

```bash
docker compose up -d
```

| Service | URL |
|---|---|
| Frontend | `http://${WEBAPP_DOMAIN}` |
| API | `http://${WEBAPP_DOMAIN}/api` |
| Admin | `http://${WEBAPP_DOMAIN}/admin` |
| API docs | `http://${WEBAPP_DOMAIN}/api/swagger` |

The api image is built from the repo root (so the `libs/` path gems are visible
during `bundle install`) and mounts `./libs` at runtime. After changing the
compose file or the Gemfile, rebuild with `docker compose up -d --build api`.

## Testing

```bash
make api-test
```

Runs the host suite (`apps/api`, `softwares_test` DB), the WarpEngine suite
(dummy app, `warp_engine_test` DB) and a production-mode `zeitwerk:check`.
Individually:

```bash
docker exec -e RAILS_ENV=test api bundle exec rspec                                # host
docker exec -w /libs/ruby/warp_engine -e RAILS_ENV=test api bundle exec rspec     # engine
```

JSON contract baselines for `/api/software` and `/api/builds` live in
`apps/api/spec/snapshots/` — diff against them after refactors.

## Linting

### Backend (RuboCop)

```bash
docker compose run --rm --no-deps api bundle exec rubocop        # check
docker compose run --rm --no-deps api bundle exec rubocop -A     # autofix
```

Config: `apps/api/.rubocop.yml` (rubocop-rails-omakase preset)

### Frontend (ESLint)

```bash
docker compose run --rm --no-deps frontend npm run lint          # check
docker compose run --rm --no-deps frontend npm run lint:fix      # autofix
```

Config: `apps/frontend/eslint.config.js` (ESLint 9 flat config, Vue + TypeScript)
