The Forge app standard, version 1
date: 2026-10-28 · for: outside developers and Forge's own apps
A Forge app is one folder and one file that describes it. Forge finds apps by that file; nothing else in Forge is edited to add one. This page is the whole contract. sdk/template/ is a working app that follows it, and python3 sdk/forge_kit.py check <folder> tells you what is missing.
1. The folder
myapp/
forge_app.json the description (section 2). Required.
web_app.py the backend: a FastAPI app named `app`. Required for
a backend app (kind "uvicorn").
static/ the page: index.html, its JS and CSS. Required.
requirements.txt the Python packages the backend needs, nothing else.
tests/ pytest tests. Expected; a review asks for them.
screenshots/ PNG pictures for the store page (16:10, 1600x1000 best).
README.md what it does, how to run it, what it keeps.
LICENSE an open-source licence. Required to publish.
- The backend listens on
127.0.0.1only, on the port Forge hands it. - An app with no backend is fine: set
"kind": "static"and"web_dir": "static", and Forge serves that folder by itself. A static app can also be a live demo on the website. - Everything an app saves goes in its own data folder: the path in the
FORGE_APP_DATAenvironment variable (Forge sets it for every app the Store installs), otherwise~/.local/share/forge/<name>/. Never write into the app folder itself (it is replaced on update) or anywhere you did not declare.
2. forge_app.json
{
"standard": 1,
"name": "myapp",
"label": "My App",
"version": "1.0.0",
"tagline": "What it does, in one short line",
"icon": "🧪",
"accent": "#7cc4a4",
"kind": "uvicorn",
"module": "web_app:app",
"src_dir": ".",
"port": 8600,
"touches": {
"files": "own",
"network": "none",
"jan": "no",
"models": [],
"gpu": false,
"runs_programs": false,
"accounts": false
},
"listing": {
"category": "life",
"about": "Two or three sentences for the store page.",
"author": "Your name",
"license": "MIT",
"source": "https://github.com/you/myapp",
"screenshots": ["screenshots/home.png"],
"video": "",
"live_demo": false
}
}
| field | required | meaning |
|---|---|---|
standard | yes | Which version of this page the app follows. Now 1. |
name | yes | The id: 2 to 32 lowercase letters, digits and hyphens, starting with a letter and not ending in a hyphen. Not a name Forge already uses (its own apps, store, forge, sdk ...). Never changes after the first release. |
label, tagline | yes | Shown on the tile and the store page. Tagline: 80 characters at most. |
version | yes | MAJOR.MINOR.PATCH (section 4). |
icon | yes | One emoji, or a path inside the folder to a square PNG or SVG. |
accent | yes | The app's colour, #rrggbb. |
kind | no | uvicorn (default: a FastAPI backend) or static (a page only, served from web_dir). |
module, src_dir | for uvicorn | How Forge starts it: python -m uvicorn <module> inside src_dir. |
port | no | A suggested port, a whole number from 1024 to 65535. Forge may give the app another free one. |
touches | yes | What the app reaches outside itself (section 3). |
listing | to publish | The store page: category (a Forge section: play, create, life, research, watch, system or assistants), about, author, license (an open-source SPDX id: MIT, Apache-2.0, BSD-3-Clause, MPL-2.0, GPL-3.0-or-later and the other common ones), source (where its code is), screenshots (paths in the folder), video (a path or an https link, optional), live_demo (true only for a static app that works in a browser). |
Forge's own apps carry more fields (sidebar section, help sheet, services); they are listed in Forge's README.md, section 3, and are all optional.
3. What an app touches
Every app says, in touches, what it reaches outside its own folder and data folder. The store page shows this to the person before they download, and a review checks the code does no more than it says.
| key | values | meaning |
|---|---|---|
files | own, picked, home | own: only its data folder. picked: also files the person chooses in the page. home: reads folders in the home folder by itself (say which in about). |
network | none, local, internet | none: never leaves the computer. local: talks to other programs on this computer (such as Jan). internet: fetches from the internet; list the hosts in hosts. |
hosts | list | With internet: every host name it contacts, such as ["api.example.org"]: plain names, no *, no links. |
jan | no, optional, required | Whether it uses Jan, the local AI app, and whether it still works without it. |
models | list | The local AI models it downloads or asks Jan for, by name, with their size in the about text. |
gpu | true or false | Whether it uses the graphics chip (heavy work the person should know about). |
runs_programs | true or false | Whether it starts other programs or commands. |
accounts | true or false | Whether it handles logins, passwords, money or messages. |
4. Versions
versionisMAJOR.MINOR.PATCH. Raise PATCH for a fix, MINOR for a new feature, MAJOR when saved data or settings change in a way an older version cannot read.- An app must read the data an older version of itself saved. A MAJOR bump converts it once, on start, after keeping a copy.
- Each release is one file,
<name>-<version>.zip, with its sha256 next to it. A version number is never reused: a fixed release gets a new number. - Raising
standardis Forge's job. An app keeps working on the version it names; Forge reads every older one.
5. Making and publishing
python3 sdk/forge_kit.py new myapp --label "My App" # copies the template
python3 sdk/forge_kit.py check myapp # this page, as a check
python3 sdk/forge_kit.py package myapp # zip, sha256, store entry
python3 sdk/forge_kit.py publish myapp --repo you/myapp # shows what it would do
python3 sdk/forge_kit.py publish myapp --repo you/myapp --yes # uploads
package leaves out .venv, caches, and the data/ and dist/ folders at the top of the app folder, and stops if a file forge_app.json names would be left out. publish uploads the zip as a GitHub Release of a public repo you already have (downloads there are free, and the Store downloads without signing in). It never creates a repo or an account.
6. Apps from other people
Running someone else's code is the main risk, so outside apps go through a review before they are listed, and version 1 keeps them to a small reach:
filesisownorpicked;networkisnoneorlocal, orinternetwith every host listed;runs_programsandaccountsare false. An app that needs more stays a Forge app made by Forge.- Python packages are pinned with their hashes (
--generate-hashes); the store installs exactly those and nothing else. - The reviewed release is pinned by its sha256. A new version is a new review.
Open submissions are not running yet. The steps are on the website's "Submit an app" page.
The starter template is sdk/template/ and the tool is sdk/forge_kit.py in Forge's source.