Skip to content

Configuration ​

Settings live in the store once an installation is seeded; the config/*.json files in the repository are the generic defaults a new installation starts from, and each has a README beside it that explains why the file exists. What the Tower may edit in each file is declared once, in scripts/config-registers.mts, and this page is generated from that declaration. Each editable entry is either a list of rows (a site's data sources, a recurring cost) or a single value.

config/beads.json ​

Its README: config/beads.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Task projects (task-hub-spokes) — one task project per site. Rows live at /spokes of config/beads.json (array, keyed by asset); edited from /settings.

FieldLabelTypeRequiredHintRule
assetSiteasset-idyesthe site this project belongs to—
prefixTask prefixstringyes2–8 lowercase letters, e.g. demoup to 8 characters; matches ^[a-z]{2,8}$
databaseDatabasestringyesstart with a lowercase letter; use lowercase letters, digits or underscoresup to 32 characters; matches ^[a-z][a-z0-9_]*$; defaults to prefix
repoRepositorystringnolegacy checkout metadata; local repository access is configured on the hostup to 200 characters; fixed once written

config/counters.json ​

Its README: config/counters.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Site counter cards (asset-counters) — one site's counter cards. Rows live at /assets of config/counters.json (object, keyed by asset-id); edited from Add a site, then the site's Settings tab (Card totals). Rows are added and removed whole; no field inside one is set through the register.

config/domain-costs.json ​

Its README: config/domain-costs.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Domain orders (domain-costs) — one prepaid domain order. Rows live at /domains of config/domain-costs.json (array, keyed by domain); edited from /financials.

FieldLabelTypeRequiredHintRule
domainDomainstringyeslowercase, a name not a URL: example.comup to 253 characters; matches ^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$; fixed once written
assetSiteasset-idyesthe site that carries the cost—
kindOrderenumyeswhat was boughtone of registration, renewal, transfer
paidUsdPaid (USD)numberyesas charged on the receiptat least 0
paidOnPaid ondateyesthe receipt date—

config/entities.json ​

Its README: config/entities.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Entities (entities) — one legal entity, and the sites it owns. Rows live at /entities of config/entities.json (array, keyed by slug); edited from /settings.

FieldLabelTypeRequiredHintRule
slugIdstringyeslowercase-with-dashes: acme-holdingsup to 40 characters; matches ^[a-z0-9]+(?:-[a-z0-9]+)*$; fixed once written
nameNamestringyesas on its paperworkup to 80 characters
formLegal formstringnoas the paperwork spells it: LLC, Ltd, sole proprietorup to 40 characters
jurisdictionRegistered instringnowhere it is registered: US-DE, Polandup to 40 characters
assetsSitesstring-listnothe site ids this entity owns—

config/ga4-custom-dimensions.json ​

Its README: config/ga4-custom-dimensions.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Sites with registered dimensions (ga4-event-params-assets) — one site's registered-dimension declaration, holding its list. Rows live at /assets of config/ga4-custom-dimensions.json (object, keyed by asset-id); edited from the site's Data sources tab. Rows are added and removed whole; no field inside one is set through the register.

Registered event parameters (ga4-event-params) — a parameter registered as a GA4 custom dimension. Rows live at /assets/{asset}/eventParams of config/ga4-custom-dimensions.json (array, keyed by param); edited from the site's Data sources tab.

FieldLabelTypeRequiredHintRule
paramParameterstringyesas the site sends it, e.g. messageup to 40 characters; matches ^[A-Za-z][A-Za-z0-9_]*$

config/integrations.json ​

Its README: config/integrations.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Site data sources (asset-integrations) — one site's data sources. Rows live at /assets of config/integrations.json (object, keyed by asset-id); edited from Add a site (/assets/new). Rows are added and removed whole; no field inside one is set through the register.

Site data sources (asset-lane) — one data source on one site. Rows live at /assets/{asset} of config/integrations.json (object, keyed by lane-id); edited from the site's Data sources tab.

FieldLabelTypeRequiredHintRule
statusPostureenumyesset up, or skipped with a reasonone of live, degraded, needs-setup, skipped, not-applicable
noteReasonstringnoone line: why skipped, or what blocks itup to 90 characters
refSource pointerstringnowhich credential reaches this site — a convention or placeholder, never a secretup to 200 characters
sinceSincedateyeswhen this posture was recorded, YYYY-MM-DD—
mediavineSiteIdMediavine sitestringnocopy the site id from Mediavineup to 160 characters; matches ^[A-Za-z0-9+/=_-]+$
mediavineEnabledAutomatic Mediavine syncbooleannocollect yesterday at 6:10 a.m. Pacific; disabling preserves saved revenue—
revenueHolidayCalendarRevenue forecast holiday calendarenumnoholidays compared with this site’s trafficone of none, US, CA, US,CA
stripeAccountIdStripe accountstringnothe acct_ id from Stripe’s account settingsup to 64 characters; matches ^acct_[A-Za-z0-9]+$
propertyIdGA4 property idstringnodigits only, e.g. 123456789up to 20 characters; matches ^[1-9][0-9]{4,14}$
siteUrlSitestringnouse sc-domain:example.com or https://example.com/up to 253 characters; matches `^(?:sc-domain:[a-z0-9][a-z0-9.-]*.[a-z]
locationCodeLocationintegernoDataForSEO's numeric location code — 2840 is the United States, the portfolio baseline1 to 99999999
languageCodeLanguageenumnoDataForSEO's language code — 'en' is the portfolio baselineone of en, es, fr, de, pt, it, nl, pl
hostPostHog regionenumnous or euone of us, eu
projectIdPostHog project idstringnothe number in the project's URL (us.posthog.com/project/424242), digits onlyup to 12 characters; matches ^[1-9][0-9]{0,11}$
funnelsFunnelsposthog-funnelsno2 to 10 steps each, in order—

Data-source catalog (data-source-catalog) — one data source the product can collect. Rows live at /catalog of config/integrations.json (array, keyed by id); edited from none — it ships with NoticeOS and changes with a product update.

FieldLabelTypeRequiredHintRule
idIdstringyeslowercase-with-dashes: bing-webmasterup to 40 characters; matches ^[a-z0-9]+(?:-[a-z0-9]+)*$; fixed once written
labelLabelstringyeswhat the product calls itup to 80 characters; fixed once written
scopeScopeenumyeswhether it collects for a site, for the OS, or bothone of property, portfolio, both; fixed once written
layerLayerenumyeswhose failure a red cell reportsone of os, provider, property; fixed once written
credentialCredentialenumyeswhether one credential can serve more than one siteone of shared, per-property; fixed once written
docRefDocstringyesthe doc section that explains itup to 200 characters; fixed once written

config/pull.json ​

Its README: config/pull.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Site metrics endpoints (asset-pull) — one site's own metrics endpoint. Rows live at / of config/pull.json (array, keyed by asset); edited from Add a site, then the site's Settings tab (Fetch from an endpoint). Rows are added and removed whole; no field inside one is set through the register.

config/recurring-costs.json ​

Its README: config/recurring-costs.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Recurring costs (recurring-costs) — one unmetered subscription, booked every month it runs. Rows live at /costs of config/recurring-costs.json (array, keyed by id); edited from /financials.

FieldLabelTypeRequiredHintRule
idIdstringyeslowercase-with-dashes: claude-codeup to 64 characters; matches ^[a-z0-9]+(?:-[a-z0-9]+)*$; fixed once written
labelLabelstringyeswhat the charge is called on the statementup to 80 characters
assetSiteasset-idyeswho carries it — the OS for anything portfolio-wide—
familyFamilyenumyesthe ledger group it books underone of inference, api, infra, operator, os-overhead
amountUsdPerMonthUSD / monthnumberyesthe recurring chargeat least 0; fixed once written
fromFrommonthyesfirst month to book, YYYY-MM—
toTomonthnolast month to book, YYYY-MM—
noteNotestringnocopied onto each month's costup to 400 characters

config/serp-panel.json ​

Its README: config/serp-panel.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Sites buying a tracked panel (serp-panel-assets) — one site's tracked-query panel, holding its terms. Rows live at /assets of config/serp-panel.json (object, keyed by asset-id); edited from the site's Growth tab. Rows are added and removed whole; no field inside one is set through the register.

Tracked queries (serp-panel-queries) — one tracked term, and the bet it measures. Rows live at /assets/{asset}/queries of config/serp-panel.json (array, keyed by query); edited from the site's Growth tab.

FieldLabelTypeRequiredHintRule
queryQuerystringyesverbatim, as a searcher types itup to 120 characters
labelBetstringnothe bet this term counts towardup to 60 characters; candidates suggest

config/signal-panels.json ​

Its README: config/signal-panels.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Panel refresh roster (signal-panels) — whether a site stays on the standing panel-refresh cadence. Rows live at /assets of config/signal-panels.json (object, keyed by asset-id); edited from the site's Growth tab.

FieldLabelTypeRequiredHintRule
enabledDaily refreshbooleanyesrebuilt daily at no provider cost—
reasonReasonenumyeswhy it is on or offone of live-lanes, no-lane-yet, not-applicable
taskTaskstringnothe id of the task that tracks this decisionup to 40 characters; matches ^[a-z]{2,8}-[a-z0-9]+(?:\.[0-9]+)*$
sinceSincedatenowhen the decision was taken, YYYY-MM-DD—

Panel history window (panel-refresh-window) — days of history each refresh reads (Days). One value at /refresh/windowDays of config/signal-panels.json, edited from /settings; integer, 1 to 365.

Panel freshness bar (panel-freshness-bar) — how old a source may get before it reads stale (Days). One value at /refresh/freshnessMaxAgeDays of config/signal-panels.json, edited from /settings; integer, 1 to 365.

config/tower.json ​

Its README: config/tower.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Where each site shows (site-display) — where one site shows and the icons it uses. Rows live at /sites of config/tower.json (object, keyed by asset-id); edited from Sites → Arrange, Settings → Sites, and the site's Settings tab (Identity, Where it shows).

FieldLabelTypeRequiredHintRule
listHome and Sites listbooleannoa row on Home and on the Sites page—
tvTVbooleannoevery widget on the TV—
workWork this weekbooleannoa row in the TV's Work this week—
lightIconLight iconurlnodrawn on light screens in place of the one readup to 2048 characters
darkIconDark iconurlnodrawn on dark screens and the TV in place of the one readup to 2048 characters

config/value-events.json ​

Its README: config/value-events.README.md.

What the Tower may edit here ​

Generated by pnpm generate from scripts/config-registers.mts, the one declaration of every list and single value the Tower may edit; scripts/config-docs.test.mjs fails when this block is stale.

Sites declaring value events (value-events-assets) — one site's value-event declaration, holding its list. Rows live at /assets of config/value-events.json (object, keyed by asset-id); edited from the site's Data sources tab. Rows are added and removed whole; no field inside one is set through the register.

Value events (value-events) — one GA4 event this site calls a value event. Rows live at /assets/{asset}/valueEvents of config/value-events.json (array, keyed by event); edited from the site's Data sources tab.

FieldLabelTypeRequiredHintRule
eventGA4 eventstringyesverbatim as the site emits it (calculation_complete, never "Calculation complete")up to 40 characters; matches ^[A-Za-z][A-Za-z0-9_]*$

Product use stages (product-use-stages) — saved event counts shown in Product use. Rows live at /assets/{asset}/productUseStages of config/value-events.json (array, keyed by eventName); edited from the site's Data sources tab.

FieldLabelTypeRequiredHintRule
eventNameGA4 eventstringyesthe saved event nameup to 40 characters; matches ^[A-Za-z][A-Za-z0-9_]*$
labelLabelstringyesthe stage headingup to 60 characters
groupGroupenumyesthe display groupone of primary, sharing, supporting
compareToCompare to eventstringnoanother declared event volumeup to 40 characters; matches ^[A-Za-z][A-Za-z0-9_]*$
comparisonLabelComparison labelstringnothe independent-volume comparison headingup to 60 characters

Released under the AGPL-3.0 license.