# Contributing to GuliMon

Adding a Gilguli to the public GuliDex is a single click: fill in the form on
[submit.html](submit.html) and hit Submit. No GitHub account, no fork, no
manual pull request — a Cloudflare Pages Function does all of that for you
in the background.

## How submission works

1. Go to [submit.html](submit.html) and fill in the form: a name, an
   optional description, an optional uploader name (just a display credit,
   not verified), and an image.
2. The page resizes/compresses your image client-side, then POSTs it to
   `/api/submit`.
3. That function (the only server-side code in this whole project) creates a
   branch in this repo, commits `submissions/<id>.png` and
   `submissions/<id>.json`, and opens a pull request — automatically, using
   its own GitHub credentials. You never touch GitHub directly.
4. Your submission is saved to this browser's local storage the moment the
   function responds, so it shows up under "Pending review" on the
   [GuliDex](index.html) immediately. Use "Check status" there to see when
   it's gone public (this checks the public `data/dex.json`, not the GitHub
   API, to stay within GitHub's unauthenticated rate limit).

## What happens after the PR is opened

**Moderation here is automated, not human-curated.** The same pipeline this
project always used still runs, whether the PR was opened by hand (old flow)
or by the function (current flow):

1. `validate-submission.yml` checks that the PR only *adds* files under
   `submissions/`, that the JSON matches the schema below, that the image
   file matches what the JSON references, and that the image is under the
   size/dimension caps. It fails its check run on any violation.
2. If validation passes, `automerge-submission.yml` merges the PR
   automatically — squashed, via the repo's own bot token — and deletes the
   submission branch. No one reviews the image content before it goes live.
3. `build-dex.yml` then regenerates `data/dex.json` from all
   `submissions/*.json` files and commits it back to `main`, which
   redeploys the site.

If validation fails, the PR is left open and unmerged with a failing check —
there's no way to retry from the site itself yet; open an issue if that
happens to you.

### Why no human review, and why no login gate?

This is an explicit, accepted tradeoff for keeping moderation fully
automated: `validate-submission.yml` can check shape, size, and schema, but
it cannot judge whether an image is appropriate, and the submit endpoint
doesn't require any account or CAPTCHA today, so it can be spammed by a
script. If either becomes a real problem in practice, the fixes are a
takedown workflow (revert the commit, block the id) and adding bot
protection (e.g. Cloudflare Turnstile) to `/api/submit` — neither is built
yet.

## Submission schema — `submissions/<id>.json`

```json
{
  "id": "string, required — slug + short random suffix, e.g. pyro-fox-x7k2",
  "name": "string, required, max 40 chars",
  "description": "string, optional, max 300 chars",
  "uploaderName": "string, optional, max 40 chars — free-text display credit, not a verified identity",
  "image": "string, required — must equal '<id>.png'",
  "createdAt": "string, required — ISO 8601, set by the submit function at creation time"
}
```

- `id` is generated server-side (in `functions/api/submit.js`, via
  `js/id.js`): `slugify(name) + '-' + <4-char random base36>`. It's the join
  key between the `.json` file and its matching image — both share the same
  basename.
- Don't hand-edit `data/dex.json` — it's regenerated by `build-dex.yml` on
  every push to `main` and any manual edits will be overwritten.
- Editing or deleting a Gilguli after merge isn't supported yet — it would
  need a second PR against the same id's files.

## Running the submit function yourself

See the "Deployment" section in [README.md](README.md) for how to deploy
`functions/api/submit.js` on Cloudflare Pages and configure its one secret.
