docs
/
AppEngine API

Sites

The site record — the home page, hosts and domains, logo and favicon, tracking and SEO — and the two fields whose shape is not what you would expect.

A site record is the container for everything that is true of a website rather than of one page: which page is the home page, what domain serves it, the logo, the favicon, analytics, and the site-wide SEO switches.

There is normally one per site, and an organization can have several.

s, d = req("GET", "/repository/find/site?perPage=10", token=t)
for r in d["data"]:
    dd = r["data"]
    print(dd["name"], dd.get("domain"), dd.get("hostName"))

The fields

{
  "name": "businessmade",
  "title": "BusinessMade",
  "description": "…",
  "keywords": "…",
  "homePage": "index",
  "hostName": "businessmade-businessmade.site.appmint.app",
  "domain": "businessmade.io",
  "logo": { "path": "…", "url": "https://…" },
  "favicon": "https://…/favicon.png?…",
  "faviconAssets": { "ico": "…", "png": "…" },
  "hideSiteHeader": false,
  "hideSiteFooter": false,
  "tracking": { "googleSiteVerification": "…", "bingSiteVerification": "…" },
  "seo": { "noIndex": false }
}

homePage — name, slug or id

"homePage": "index"

A page is found by its name, its slug (both case-insensitive) or its id — the same lookup every page address uses. If nothing matches, the site serves its fallback at / rather than an error.

When the site sets publishedPagesOnly, pages are served from their published copies: an edit shows only after the page is published again (POST /repository/publish/page/:id).

s, d = req("GET", "/repository/find/page?perPage=100", token=t)
for r in d["data"]:
    print(r["name"], "|", r["data"].get("slug"))   # homePage may match either

favicon is a string. logo is an object.

They are not symmetrical, and the asymmetry is silent.

"logo":    { "path": "org/brand/logo.png", "url": "https://…" },   // object
"favicon": "https://…/favicon.png?…"                                // string

The renderer normalises the logo — typeof rawLogo === 'string' ? rawLogo : rawLogo?.url — so either shape works there. The favicon is passed straight into the framework's icons field with no unwrapping.

Store the favicon as an object and no icon link is emitted at all. The site keeps the platform default, the record reads back looking correctly set, and nothing reports a problem.

Keep the detail under a key of your own:

{ "data.favicon": "https://…/favicon.png?…",
  "data.faviconAssets": { "ico": "…", "png": "…", "path": "org/favicon.ico" } }

Verify on the rendered page, never on the record:

curl -s "https://your-site/?cb=$RANDOM" | grep -oE '<link rel="icon" href="[^"]{0,80}'

Seeing href="/favicon.ico" means your value was ignored.

Page-level <link rel="icon"> tags in data.html are deliberately stripped by the renderer, so a page cannot set its own favicon. The site record is the only mechanism.

Generating the files: Set a logo and favicon.

Hosts and domains

FieldWhat it is
hostNameThe platform host — <site>-<org>.site.appmint.app
domainYour custom domain

Both serve the site. The platform host always works and updates immediately; the custom domain sits behind a cache.

Verify a deploy on hostName first. Custom domains lag by a cache cycle. If the platform host shows your change and the custom domain does not, that is a cache, not a failed deploy — and redeploying will not help.

Tracking and SEO

"tracking": {
  "googleSiteVerification": "…",
  "bingSiteVerification": "…"
}

These come from the site record rather than a build-time variable, because one deployment serves many tenants and each claims its own property.

"seo": { "noIndex": true }

seo.noIndex is the site-wide kill switch and outranks any per-page value. It is the same flag robots.txt reads, so the two cannot disagree.

Chrome switches

hideSiteHeader and hideSiteFooter suppress the platform's own header and footer. Set both if your pages carry their own — otherwise you get two headers, which usually reads as a CSS bug.

Writing to the record

s, rec = req("GET", f"/repository/get/site/{sk}", token=t)

req("POST", f"/repository/update-partial/site/{sk}", {
    "sk": sk,
    "version": rec["version"],
    "data.title": "New title",
}, token=t)

Dot-paths only. {"data": {...}} replaces the entire object — domain, logo, tracking and everything else you did not include.

Read the record before overwriting data.logo. A site may already have a designed logo, in which case you only want to set the favicon.