Settings and links
Admin > General and Appearance share one loaded settings state. Admin > Header links manages a separate global destination list. Both save server state before Publish/build updates generated reader pages; neither is a remote-host deployment or account-permission editor.
General fields
| Field | Maximum |
|---|---|
| Site title | 120 characters, nonblank |
| Header title | 80 characters, nonblank |
| Subtitle | 300 characters |
| Default description | 300 characters |
| Site URL | 2000 characters |
Inputs are text and trimmed on validation; length is checked on supplied string before trimming. Site URL is blank or full HTTP/HTTPS without credentials, query or fragment. It is normalized and one trailing slash removed. A path can be present, but siteUrl is not the same setting as baseUrl, and entering it does not configure DNS/host deployment.
Use fictional Field Guide branding for examples, not a real person’s private identity. A public reading URL and private editor URL have different audiences. Verify intended reader origin/path before saving; do not put access tokens or account credentials in addresses.
Appearance and unavailable controls
| Item | Current behavior |
|---|---|
| Show home hero | Boolean runtime override, save then build |
| Raw HTML status | Read-only actual server-file setting |
| Default theme | No Admin override field |
| Footer text/links | No active current-template control |
| baseUrl | Operator file configuration |
| Per-user branding | Not implemented |
Hero visibility changes homepage presentation, not whether content is built. Runtime settings only own the exposed validated fields; unknown/server-only keys are omitted. Raw HTML displayed here is server preview policy, not a browser switch that rewrites reader build policy automatically.
Shared drafts, save and discard
- Load intended server’s General values and Appearance state.
- Make the reviewed branding/hero change.
- Save once from either area and wait for final result.
- Recheck loaded saved values, then Publish/build and inspect reader.
- If hosting is separate, release and verify actual deployed pages.
| State/action | Result |
|---|---|
| General edit or hero toggle | Shared unsaved settings flag |
| Save in either area | Sends all General fields plus hero |
| Save active | Inputs/buttons disabled, leaving gated |
| Success | Saved values/revision reload, draft clears |
| Failure | “Not saved”; intended values remain |
| Discard in either area | All loaded settings restored |
| Leave/sign out | Unsaved discard decision |
General and Appearance are not independent save transactions. Saving hero can also save an unsaved General field. Review the whole shared change, especially public titles/site URL. Discard is loaded-state restoration, not a rollback of already saved values or another administrator’s disk changes.
The runtime file revision is SHA-256 of current bytes, or missing before first save. A stale expected revision produces 409 and instructs reload. Preserve edits, fetch current state and reapply deliberately. Server temporary-write/rename protects file replacement, not a multi-operator semantic merge.
Runtime versus siteconfig
| Layer | Meaning |
|---|---|
| Defaults | Used when no valid supplied value |
siteconfig.json |
Base operator configuration |
site-settings.json |
Selected runtime overrides |
| Generated output | Baked-in last build values |
| Remote host/cache | Actual served artifact may be older |
Applicable runtime overrides win over base file values. If base omits headerTitle, its siteTitle supplies header fallback before runtime merge. A separate runtime siteTitle override does not necessarily make another stored/header value match. Inspect effective values rather than guessing inheritance.
Settings JSON stores validated exposed fields only, with private group-readable 0640 creation mode. Reader branding is public when rendered even though configuration lives outside content. Malformed stored overrides throw rather than quietly becoming an empty successful settings set; inspect/restore protected file instead of repeatedly submitting blind changes.
Build/editor must use intended runtime paths. Build --data selects build configuration/link data; editor data lives beside selected users file. Different paths can produce apparently ignored changes. Site settings owns complete file/runtime precedence and build-time fields.
Global header links
| Value | Contract |
|---|---|
| Count | Up to 30 stored entries, including hidden |
| Title | Nonblank, whitespace collapsed, max 40 |
| Address | Full HTTP/HTTPS, max 2000, no credentials |
| Show on site | Hidden when exactly false |
| Order | Stored list order |
| ID | Valid generated 12-hex identity |
Unlike Site URL, header URLs may contain query/fragment and nonstandard ports. Do not embed secrets just because a URL validates. Link acceptance and safe server-side icon fetching have different rules: an accepted internal/nonstandard-port destination may still fail icon fetch and use generic.
These are header destinations, not chapter links, writer permissions or automatic remote repository access. Reader overflow moves links into More when there is not enough room. Test longest titles and menu at phone/desktop widths. A hidden destination does not remove content files or protect target site.
Header actions save immediately
| Action | Result |
|---|---|
| Add/Edit form Save | Validates whole next list; waits for icon work |
| Cancel form | Drops form edits, no list save |
| Show checkbox | Saves whole list immediately |
| Up/Down | Saves reordered list immediately |
| Remove | Confirmation then saves list without entry |
| Refresh icon | Edit checkbox; request occurs on Save |
There is no general Save/Discard footer for all header rows. The list is sent in full for each action and has no settings-style revision token. Two administrators with old lists can overwrite each other’s changes; reload/reconcile before editing shared destinations. Do not describe it as conflict-safe concurrent merge.
UI’s busy flag serializes its send function, but does not make every possible click a queued change. Wait for result and inspect saved list. On form failure, error stays visible; on show failure, list re-renders loaded state. A lost response needs current list inspection before repeating Add/Remove.
Favicon request boundary
Saving a new address, changed address or explicit Refresh icon causes the private editor server to contact that destination. Reordering/show/title-only save reuses existing cached icon. This is an exception to locally bundled reader libraries/fonts, not a general claim that all author/editor behavior is offline.
| Fetch limit | Value |
|---|---|
| Addresses per save | At most 5 icon fetch operations |
| Page response | Up to 256 KiB |
| Icon response | Up to 100 KiB |
| Redirects per request | At most 3 |
| Candidates | At most 5 distinct attempted icons |
| Timeout | 5 seconds per request by default |
| Icon formats | PNG, ICO, GIF, JPEG, WebP signatures |
Only HTTP/HTTPS on standard ports is fetched, without URL credentials. DNS must resolve only to accepted public addresses; checked address is pinned for connection, redirects revalidated. Private/reserved network ranges and SVG/unknown signatures are refused. This is bounded validation, not a claim of immunity to every network or image-parser risk.
The fetcher reads page icon links then fallback /favicon.ico, tries distinct candidates, and caches accepted bytes under link ID. Timeouts apply per request, not a guaranteed five-second whole-save deadline. Multiple page/icon candidates/redirects can take longer.
| Situation | Saved icon behavior |
|---|---|
| New/changed URL, failure | Old icon dropped; generic |
| Same URL Refresh, failure | Prior icon kept when available |
| More than 5 new/refresh links | Remaining note says refresh later |
| Missing icon | Link can still save |
| Accepted cached icon | Served locally after build |
| Removed/unreferenced cache | Matching cached files cleaned on list save |
The initial URL/DNS/public-address refusal can produce a specific “Icon not fetched” note. Later page failures (including size, timeout and redirects) are caught and trigger the fallback icon; individual candidate failures are caught and tried onward. Exhaustion returns no icon. Therefore “Response too large”, “Timed out” and “Too many redirects” are internal reasons, not guaranteed text in the final browser note. Do not claim every fetch failure is surfaced verbatim.
Read the returned icon notes separately from overall link success. “No icon found” does not mean address was not saved; “saved” does not prove destination access or trustworthy ownership. Link-list read skips bad entries and damaged/missing files becomes empty, unlike site-settings’ fail-closed JSON read. An unexpectedly empty header needs storage inspection before overwriting the old file.
Exact validation reasons
These strings belong to different layers. List errors stop a links save with 400. Favicon refusal becomes an icon note when caught by saveLinks; it does not normally reject the valid destination list. Site validation stops saving before revision replacement. Public reader use of the link is a separate action.
| Link reason | Fix/check |
|---|---|
| Links must be a list | Send the intended whole array |
| At most 30 links | Count hidden entries too |
| Not a link | Entry must be object |
| Every link needs a title | Nonblank text after collapse |
| A title can be at most 40 characters | Shorten displayed title |
| Address reason | Full HTTP/HTTPS, no credentials, max 2000 |
The parameterized address reason names the normalized title:
The address for "TITLE" must be a full http or https address
Initial icon input/refusal reasons include these exact messages. They describe server fetching, not whether the reader can follow an accepted link:
Not a valid web address
Only http and https addresses are allowed
Addresses with a user name or password are not allowed
The address has no host name
Only the standard web ports are allowed
The host name did not resolve
The address points to a private or reserved network
A no-host branch can be hard to reach through standard URL parsing. Its presence is source evidence, not a claim the browser form exercises every reason. Later request errors are caught as described above. Do not weaken DNS/public-address checks to fetch an internal icon.
| Site reason | Boundary |
|---|---|
| Invalid settings object | Non-null object, not array |
| Maximum characters | Supplied string/type, per-field limit |
| Cannot be empty | Site/header title after trim |
| Invalid siteUrl | Full HTTP/HTTPS and URL policy |
| Invalid showHero | Actual boolean |
| Settings changed | Revision conflict 409 |
Parameterized site messages have these forms; FIELD and LIMIT are placeholders for the real validated key/limit:
Invalid FIELD: maximum LIMIT characters
Invalid FIELD: cannot be empty
Invalid siteUrl: use a full http or https URL
Invalid siteUrl: use http or https without credentials, query or fragment
Invalid showHero: must be a boolean
Settings changed. Reload before saving.
Malformed stored JSON may report a generic server/build failure rather than one of these safe input strings. Preserve the protected file and inspect the actual handler/diagnostics. Module boundary fixtures test exact limits and rejection, not every browser/form/storage failure.
Showcase and destination verification
This showcase’s GitHub header destination uses the existing link mechanism and local icon. Drawing that icon does not request GitHub from reader; following it does. Repository visibility still controls destination access. Public title/icon is not evidence a private repository is publicly readable.
For any destination, open the actual resolved page and verify intended item, not just successful load/domain. Test direct link, More entry, keyboard and phone layout after build. Never change application link/settings state merely to document the feature; this handbook’s example is not a production-settings operation.
Publish, backup and recover
| Check | Evidence |
|---|---|
| Saved form/list | Actual server settings/links |
| Build data | Intended selected runtime path |
| Reader | Header, home hero, titles and metadata |
| Icons | Local accepted bytes or generic fallback |
| Host | All pages updated, no stale cached header |
| Backup | Settings, links and favicon cache protected |
Back up site-settings.json, links.json and favicons/ with selected runtime data. Generated HTML can support reader rollback but does not reconstruct all private configuration/account state. A correction requires new save/build/release, not a silent remote-account mutation.
No production settings/account deployment is certified by these examples. Validation limits separates local tests from provider, TLS, access, cache and recovery work.