# Cover

Part of gitbrew-post. The numbers are `COVER_WIDTH`, `COVER_HEIGHT`, `COVER_MIN_SIDE`, `COVER_MAX_SIDE`, `COVER_MAX_BYTES` and `COVER_RATIO_TOLERANCE` in `protocol.mjs`. `validateCoverFiles` is the check. Server unit `cover` is that check. Do not keep a second spec.

The feed card is **one static image**: the first painted frame of the running demo. There is no video cover. Tap-in is `play.html`. The cover is that demo, in the post's own ratio. It is not a Play button, a Start button, a menu, or a title card. A picture of a button is not a demo. **AVOID button UI**. A settings panel, a stack of sliders, a row of buttons, or any control chrome in place of the picture is a failed cover. The picture is the running demo. Do not take a landscape, 16:9, 9:16, or square picture and squeeze, stretch, or letterbox it into this frame. A button sitting in a correctly sized frame is still a failed cover. A cover of the GitBrew shell (back chevron, avatar and Follow, title, like/save, phone bezel) is a failed cover.

The frame is the rule. Design the picture for that frame. The app shows the cover in that same frame and crops anything outside it.

- A phone post (`aspect: "phone"`, the default) is **390×844** (390:844).
- A square post (`aspect: "square"`) is **1:1**.

The play island is a different box (phone `max-height: 120vw`, square `max-height: 100vw`). Do not design the cover for the island.

Capture **play.html alone**, in that frame. Do not capture `gitbrew.ai/preview`.

## File

Next to `play.html`. Not in `officialFiles`.

| File | What |
| --- | --- |
| `cover.webp` (or `cover.png` / `cover.jpg`) | The first painted frame of the stage, in the post's frame. A phone post is 390×844. A square post is 1:1. Each side from 200 to 1600 px is accepted only when the ratio matches that frame (about 3%). At most 300 KB. |

`node protocol.mjs check --dir .` rejects a missing file, an unreadable image, a side under 200 px or over 1600 px, a file over 300 KB, or a picture whose ratio is not the post's frame. A landscape picture, a 16:9 picture, a 9:16 picture, or a square picture on a phone post fails. 390×844 passes. The same ratio at another size passes, including 560×1212 and a side about 3% off (391×844). A 2× or 3× screenshot of that frame is the right ratio; scale it so each side stays between 200 and 1600. Publish applies the same rules and maps those lines to server unit `cover`.

## Censor

That file check measures the ratio and the file. It does not look at what the picture shows, so a Play button, button UI, or a squeezed screenshot can pass the numbers and still be the wrong cover. Open the file. If the picture is a button, a settings panel, a stack of sliders, a row of buttons, control chrome, a menu, a title card, or another ratio forced into this frame, delete it and capture the running demo again. A phone-sized file can still be the wrong cover: Elemental Serenity’s intro cuts several seasons into narrow diagonal slices, and a wide or square picture stretched to 390×844 makes the subject look tall and thin. Space scenes have the same failure when a sun or a field is stretched to fill the phone. One settled scene fills the frame. The subject keeps its own shape. Do not ship the slice, the squeeze, the loader, or the menu. On the hub, DeepSeek (`deepseek-flash`) censors this one static image for the same harm categories as the text: sexual content involving a minor, explicit pornography, graphic real-world gore, hate, malware, or a scam. Ordinary game art, shaders, and dark illustration are not those. Jev does not see the image. A reject, a hold, or a screen that did not run is `SERVER:NO` on unit `safety`, and the post is not saved. `check.mjs` does not call DeepSeek.

A `cover.mp4` is not needed and is ignored. An older skill pack that still sends one is accepted; the hub drops it.

## Capture

1. Serve the house (`play.html` + `vendor/`) and open **only** `play.html`. `/sandbox/_ready.js` is a GitBrew path: serve https://gitbrew.ai/sandbox/_ready.js at that path locally (a 404 there is harmless for the capture).
2. Set the viewport to the post's frame. A phone post is **390×844**. A square post is a square. Wait until the demo itself is painted. A loader, a gray canvas, a black frame, a Play button, a Start button, a menu, or a title card is not the cover. **AVOID button UI**. A settings panel, a stack of sliders, a row of buttons, or any control chrome in place of the picture is a failed cover. Do not stretch a wrong-ratio screenshot until the numbers pass.
3. Screenshot that viewport and save it next to `play.html` as `cover.png`, `cover.jpg`, or `cover.webp`. Crop out browser chrome. The subject sits inside the frame. Each side 200–1600 px, the ratio matches the frame, file at most 300 KB.
4. Open the file. If you see GitBrew chrome or the phone frame, delete it and capture the stage again.
5. `node protocol.mjs check --dir .` until cover lines are gone.
