# COG Factory partner onboarding

Give this file to your coding agent. It describes how to prepare, preview and maintain your own listings in COG Factory's Jedi Knight experiment library.

COG Factory is opening its AI experiment index to a handful of fellow JK creators. You keep your own files in your own FTP folder. The site indexes your JSON and links directly to your images and downloads. There is no partner account dashboard or Edit form on COG Factory.

## Before the agent starts

SM Sith Lord supplies these details separately for each invited partner. Do not guess them or copy another partner's settings.

| Setting | Supplied by the owner |
| --- | --- |
| Author ID and display name | For example `jezz` / Jezz, or `gnarl` / Gnarl; these identify the real creators, not characters |
| FTP host, port and connection type | Use exactly the provided protocol, including encryption when supported |
| FTP username and password | Store privately in your local tool or credential store, never in uploaded JSON or this public guide |
| Remote root | The account's assigned folder; it may already be the FTP login's `/` |
| Public asset URL prefix | The HTTPS URL that corresponds to that remote root |
| Storage quota | The account's size cap, including old files and temporary uploads |
| Library URL | Normally `https://smsithlord.com/openjkdf2libretro/cogfactory/gen2/library/`; use the owner's preview URL before launch |

The owner must register your author ID and actual folder on the site before it can index you. Your agent cannot register an author by uploading JSON. Work only within your assigned FTP root. Never change the site's PHP, cache, other authors' folders or server configuration. Ask for missing connection details before attempting an upload.

## What your agent should build for you

Build a small **local** tool appropriate to your workflow. A simple local web page, desktop script or command-line helper is fine; there is no required language or framework. The minimum useful workflow is:

1. Open the local copy of your index and project entries. Let you manually edit title, description, features, category, compatibility, credits, AI disclosure, dates, download and screenshot metadata.
2. Add/reorder screenshots, show thumbnails, read actual image dimensions, generate the thumbnails described below, and validate required fields and local asset paths. Keep other projects in the index intact.
3. Let you choose **Draft** or **Published** explicitly. Default new entries to Draft. Show the unlisted/public distinction clearly.
4. Show a local approximation if useful, and offer **Open site preview** using the URL below. The site's own preview is the final check of the actual card and details.
5. Show which files will upload and their total size; preserve credentials privately. Upload only changed files within your folder. Publishing or removing a listing should be an explicit action by you.
6. Save a local backup before overwriting existing JSON. Read existing remote data before the first edit on a new machine. Handle failed uploads and server errors without claiming success.

You do not need to upload the tool itself. COG Factory consumes JSON and media/download files, not executable submission scripts. Do not build against an imaginary COG Factory edit API: there isn't one. Prefer the fewest dependencies that give your creator a usable tool.

## Folder layout

Paths below are **relative to your assigned FTP root**, not a new `jezz` folder inside it:

```text
index.json
projects/
  underwater-base/
    entry.json
    downloads/
      underwater-base-v1.zip
    screenshots/
      entrance.jpg
      passage.jpg
      outpost.jpg
      thumbs/
        entrance.webp
        passage.webp
        outpost.webp
```

Your `index.json` lists the projects that should be indexed, including drafts:

```json
{"projects": ["underwater-base"]}
```

Each ID must match its project folder: lowercase letters and numbers separated by single hyphens, up to 64 characters. Keep IDs stable when changing a title. The index supports up to 200 projects per partner. Each JSON file must be valid UTF-8, at most 512 KiB, with no comments or trailing commas.

All listing data for a project lives in its `entry.json`. There is no per-project JavaScript file. Example:

```json
{
  "status": "draft",
  "title": "Underwater Base",
  "description": "Explore a flooded outpost with friends.",
  "category": "mod",
  "compatibility": "vanilla",
  "features": [
    "Explore three flooded rooms.",
    "Find an underwater route.",
    "Play with friends."
  ],
  "genres": ["exploration"],
  "released": "2026-10-12",
  "updated": "2026-10-12",
  "version": "Build 1",
  "requirements": "Jedi Knight: Dark Forces II with the thing and adjoin limit removers.",
  "ai": "AI-assisted COG scripting; describe any generated art or audio here.",
  "credits": [],
  "download": "downloads/underwater-base-v1.zip",
  "screenshots": [
    {"url": "screenshots/entrance.jpg", "size": "1280x720", "thumbnail": {"url": "screenshots/thumbs/entrance.webp", "size": "640x360"}, "caption": "The flooded entrance.", "kind": "gameplay"},
    {"url": "screenshots/passage.jpg", "size": "1280x720", "thumbnail": {"url": "screenshots/thumbs/passage.webp", "size": "640x360"}, "caption": "The underwater passage.", "kind": "gameplay"},
    {"url": "screenshots/outpost.jpg", "size": "1280x720", "thumbnail": {"url": "screenshots/thumbs/outpost.webp", "size": "640x360"}, "caption": "Inside the outpost.", "kind": "gameplay"}
  ]
}
```

Replace the example claims, dates and file names with your actual work. Do not claim multiplayer support or testing you have not performed.

## Drafts, publishing and site previews

- `"status": "draft"` keeps the entry out of normal browsing. **Omitting `status` also means Draft.**
- `"status": "published"` includes it in the normal Library. These are the only two accepted values.
- Open `LIBRARY_URL?drafts=1` to include drafts. With existing query parameters, append `&drafts=1` instead.
- To open your own entry directly, use `LIBRARY_URL?drafts=1&item=cogfactory.guest-AUTHOR_ID--PROJECT_ID`. Example: `library/?drafts=1&item=cogfactory.guest-jezz--underwater-base`.
- The preview includes other partners' drafts too. It labels draft cards/details and keeps normal category and compatibility filters working. Use All / Any game if a filter hides your entry.
- Once published, its ordinary detail link is `LIBRARY_URL?item=cogfactory.guest-AUTHOR_ID--PROJECT_ID`.

**Draft means unlisted, not private.** The URL parameter is not authentication. Anyone can add it, share the preview URL, or access JSON, screenshots and downloads if they know their URLs. Do not upload secrets or material that must remain private. Turning a published entry back into Draft does not erase previously shared files or cached copies.

Drafts need the same valid metadata and media links as published entries so the site can render them. They are not a place for partially uploaded or invalid JSON. Use your local tool for incomplete work, then upload a complete draft for site preview.

## Metadata and media requirements

| Field | Rules |
| --- | --- |
| `title` | Required, 1–120 characters |
| `description` | Required, 1–1200 characters; plain text, not HTML |
| `category` | `level`, `mod`, `tc` or `tool`; defaults to `mod` |
| `compatibility` | `retail`, `vanilla` or `libretro`; defaults to `vanilla` for game content. `enhanced` is accepted as an older alias for Libretro. Tools have no game compatibility |
| `features` | Required: 3–8 useful short statements, each up to 100 characters |
| `genres` | Optional list of 1–8 descriptive genres, each up to 40 characters. Do not use Mod/Level/TC/Tool as genres; category is separate |
| `released`, `updated` | Required release date in `YYYY-MM-DD`; updated is optional and defaults to released. Change updated for a meaningful content update |
| `version` | Optional, up to 40 characters, such as Build 1 |
| `requirements` | Optional, up to 300 characters; state the actual runtime needs. A category-appropriate default is provided |
| `ai` | Required key: describe generated/assisted content in up to 800 characters, or use JSON `null` if none |
| `credits` | Optional list, at most 40 items, each with `role` (up to 40 characters) and `name` (up to 200). Credit borrowed assets separately from submission authorship |
| `notice` | Optional IP/attribution notice, up to 800 characters; the site supplies a fan-content notice by default |
| `download` | Required link to the actual package/file or download destination |
| `screenshots` | Required: 3–24 images. Each needs `url`, a caption up to 80 characters and true `WIDTHxHEIGHT` dimensions, and a `thumbnail` object with its own `url` and actual `size`; `kind` is `gameplay`, `menu` or `clean`, defaulting to gameplay |
| `platforms` | For tools: optional platform names, up to 8, each up to 40 characters |

Game content defaults to **Jedi Knight: Dark Forces II**. Mysteries of the Sith is a future concern; coordinate with the owner before targeting a different game. Retail means stock JK limits. Vanilla means stock JK with thing/adjoin limit removers. Libretro means OpenJKDF2Libretro-specific features. Choose the tier from the actual requirements and tests, not how the graphics look.

Use actual in-game screenshots or accurate tool screenshots. Prefer 1280×720 or higher (1920×1080 ideal) when practical; correctly labelled lower-resolution JK captures are accepted. Do not stretch an image or invent dimensions to satisfy that preference. Use sensible JPEG/PNG/WebP compression and meaningful captions. The first screenshot is the fallback card/hero image, so choose a useful overview. This submission format currently supports screenshots, not an uploaded video field or a mandatory extra capsule/logo package.

### Create and upload thumbnails

Your agent must generate a separate thumbnail for **every screenshot**, including drafts.
For `screenshots/entrance.jpg`, use `screenshots/thumbs/entrance.webp`: same base name in a
`thumbs/` subfolder. Prefer WebP at about quality 80; JPEG is also fine if the tool cannot
write WebP (use `.jpg` and record that exact URL). Keep names lowercase with hyphens.

- Fit within **640 × 640 pixels**, keeping the original aspect ratio. Do not crop, stretch
  or upscale. A 1280×720 original becomes 640×360; 640×480 stays 640×480 but gets its own
  compressed file; 320×240 stays 320×240. Aim for roughly 100 KB or less when practical.
- Keep the full image untouched. A thumbnail must have a different URL from its full image.
- In each screenshot, include `"thumbnail": {"url": "screenshots/thumbs/entrance.webp", "size": "640x360"}`.
  Record actual output dimensions. The site reads this explicit URL; it does not guess a
  filename, resize partner files, or send them to Cloudinary.
- Cards and list rows use the **first screenshot's thumbnail**. Gallery thumbnail controls
  use each screenshot's thumbnail; the main detail image and full viewer use the original.
  Share metadata also keeps the full image. Reordering screenshots changes the card image.
- Upload both versions before the entry JSON. Regenerate the thumbnail whenever its source
  changes; use matching versioned names for both if replacing a released image. Include both
  versions in your quota check, and verify both public links after uploading.

Missing thumbnail metadata, dimensions above 640×640, upscaled dimensions, or the same URL
as the original makes an entry invalid. Your local tool must also verify the actual image
files and dimensions: PHP validates JSON, not image bytes or remote file existence.

Relative media and download paths resolve inside `projects/PROJECT_ID/` under your public URL prefix. Use literal file paths, preferably lowercase with hyphens; the site URL-encodes relative segments. Full HTTPS links and same-site root paths also work. The site hotlinks files; it does not import them into Cloudinary or a media library, resize them, or verify that a remote file actually exists. Your local tool should check local files and public links.

Downloads do not require a GOB filename in the JSON. A Level can contain a level GOB; a Mod can contain a mod GOB; a TC may contain both. A Tool or other generic package can simply be a downloadable file. For multi-file releases, provide a ZIP with clear installation instructions, requirements, version and credits. Explain `episode/` versus `mods/` placement where applicable. Don't distribute the retail game's data. Respect your assigned quota and preserve any licenses/attributions that apply to your assets.

The site supplies your author identity from its roster. Do not put an `author`, `id`, `url` or `page` override in the entry. Partner entries open their details in the Library and have downloads, but no **Its page** link or separate generated project page.

## Recommended contents of your published ZIP

We recommend following COG Factory's own download convention: put the release files, a `readme.txt` and a representative `screenshot.jpg` together inside the actual ZIP you publish. Include these even when the listing already has a description and screenshots, so the download remains understandable when shared on its own.

For a simple one-GOB release, use one clearly named top-level folder:

```text
underwater-base-v1/
  underwater-base.gob
  readme.txt
  screenshot.jpg
```

Adapt the contents to the release. A TC or other package may contain multiple GOBs; include every GOB needed for that release. A tool or other non-GOB package should contain its relevant files instead, with the README and an accurate tool screenshot or other useful preview. No GOB is required for those packages.

When files need different installation locations, preserve that structure inside the top-level folder. For example, put level GOBs in `episode/`, mod GOBs in `mods/`, and external music in `MUSIC/` where applicable. Keep the README and preview easy to find at the top level and explain exactly where each folder goes. Include required redistributable supporting files and license notices; exclude retail game data, personal profiles, credentials and local build/test clutter.

The `readme.txt` should cover:

- The title, version/build, author and a short description of what the package does.
- Requirements and compatibility, including required patches, engines or dependencies.
- Installation and launch steps, identifying each GOB/file's purpose and destination; explain any files that would be overwritten.
- Controls and usage, or tool instructions for non-game packages.
- Known limitations and what was actually tested.
- Credits, asset licenses/attributions, AI assistance where applicable, and a notice that Jedi Knight fan content is not made or distributed by LucasArts.

Before publishing, open the ZIP itself and check that the release files, README, preview and any required supporting files are present and match the advertised version.

## Upload and update procedure

1. Validate the entry locally, including screenshot dimensions and matching file names/case. Ensure the total upload fits your quota with room for temporary files.
2. Upload the full images, generated thumbnails and download first. Prefer new versioned asset file names for replacements so browser caches cannot show an old image/package under the same URL.
3. Upload `entry.json` under a temporary name in that same project folder, then rename it into place once complete, if your FTP server supports replacement by rename. Keep a backup; don't delete the previous entry first just to make an upload succeed.
4. For a new project, add its ID to `index.json` **last**, using the same temporary-upload/rename approach. Preserve all existing IDs, including drafts. An existing project's edits need no index edit or revision number.
5. Reload the draft-preview URL after the cache interval. The server normally checks on the first request after 60 seconds have elapsed; it is not an instant push or a scheduled job.
6. Check author, Draft label, category, compatibility, captions, download and the package's contents on the actual site. Once your creator chooses to list it, change `status` to `published` and upload the entry again. Confirm it appears without `drafts=1` after refresh.

To unlist, change status to Draft. To remove the listing from both views, remove its ID from your index. Deleting just `entry.json` does **not** reliably remove a listing: the cache retains last-good data for broken or missing uploads. A valid empty `{"projects":[]}` removes all your listings. Asset deletion is separate and should be an explicit action, since it breaks shared links.

If a valid listing still looks old, allow a cache interval, reload, check filters and draft state, then verify the public file contents and ask SM Sith Lord to inspect the server log. Invalid new entries are omitted; invalid updates retain the last valid entry, including its previous publication state. A malformed index retains that author's previous listings while other partners can still update. There is no private submission-status API or server-side editing form.

## Agent handover checklist

Leave your creator with their local tool and a short explanation of how to edit, validate, upload, preview, publish and unlist; private connection configuration; backups; and working Library/detail links. Keep credentials out of logs and Git. Record what was actually uploaded and tested. Do not report a submission published until it is visible in the normal Library view.
