---
url: https://docs.notice.cx/reference/configuration.md
description: >-
  Every setting the Tower may edit, generated from the one declaration of the
  configuration registers.
---

# 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](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `asset` | Site | `asset-id` | yes | the site this project belongs to | — |
| `prefix` | Task prefix | `string` | yes | 2–8 lowercase letters, e.g. demo | up to 8 characters; matches `^[a-z]{2,8}$` |
| `database` | Database | `string` | yes | start with a lowercase letter; use lowercase letters, digits or underscores | up to 32 characters; matches `^[a-z][a-z0-9_]*$`; defaults to `prefix` |
| `repo` | Repository | `string` | no | legacy checkout metadata; local repository access is configured on the host | up to 200 characters; fixed once written |

## config/counters.json

Its README: [config/counters.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `domain` | Domain | `string` | yes | lowercase, a name not a URL: example.com | up to 253 characters; matches `^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$`; fixed once written |
| `asset` | Site | `asset-id` | yes | the site that carries the cost | — |
| `kind` | Order | `enum` | yes | what was bought | one of `registration`, `renewal`, `transfer` |
| `paidUsd` | Paid (USD) | `number` | yes | as charged on the receipt | at least 0 |
| `paidOn` | Paid on | `date` | yes | the receipt date | — |

## config/entities.json

Its README: [config/entities.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `slug` | Id | `string` | yes | lowercase-with-dashes: acme-holdings | up to 40 characters; matches `^[a-z0-9]+(?:-[a-z0-9]+)*$`; fixed once written |
| `name` | Name | `string` | yes | as on its paperwork | up to 80 characters |
| `form` | Legal form | `string` | no | as the paperwork spells it: LLC, Ltd, sole proprietor | up to 40 characters |
| `jurisdiction` | Registered in | `string` | no | where it is registered: US-DE, Poland | up to 40 characters |
| `assets` | Sites | `string-list` | no | the site ids this entity owns | — |

## config/ga4-custom-dimensions.json

Its README: [config/ga4-custom-dimensions.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `param` | Parameter | `string` | yes | as the site sends it, e.g. message | up to 40 characters; matches `^[A-Za-z][A-Za-z0-9_]*$` |

## config/integrations.json

Its README: [config/integrations.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `status` | Posture | `enum` | yes | set up, or skipped with a reason | one of `live`, `degraded`, `needs-setup`, `skipped`, `not-applicable` |
| `note` | Reason | `string` | no | one line: why skipped, or what blocks it | up to 90 characters |
| `ref` | Source pointer | `string` | no | which credential reaches this site — a convention or placeholder, never a secret | up to 200 characters |
| `since` | Since | `date` | yes | when this posture was recorded, YYYY-MM-DD | — |
| `mediavineSiteId` | Mediavine site | `string` | no | copy the site id from Mediavine | up to 160 characters; matches `^[A-Za-z0-9+/=_-]+$` |
| `mediavineEnabled` | Automatic Mediavine sync | `boolean` | no | collect yesterday at 6:10 a.m. Pacific; disabling preserves saved revenue | — |
| `revenueHolidayCalendar` | Revenue forecast holiday calendar | `enum` | no | holidays compared with this site’s traffic | one of `none`, `US`, `CA`, `US,CA` |
| `stripeAccountId` | Stripe account | `string` | no | the acct\_ id from Stripe’s account settings | up to 64 characters; matches `^acct_[A-Za-z0-9]+$` |
| `propertyId` | GA4 property id | `string` | no | digits only, e.g. 123456789 | up to 20 characters; matches `^[1-9][0-9]{4,14}$` |
| `siteUrl` | Site | `string` | no | use sc-domain:example.com or https://example.com/ | up to 253 characters; matches `^(?:sc-domain:[a-z0-9][a-z0-9.-]*\.[a-z]{2,}|https?://\S+)$` |
| `locationCode` | Location | `integer` | no | DataForSEO's numeric location code — 2840 is the United States, the portfolio baseline | 1 to 99999999 |
| `languageCode` | Language | `enum` | no | DataForSEO's language code — 'en' is the portfolio baseline | one of `en`, `es`, `fr`, `de`, `pt`, `it`, `nl`, `pl` |
| `host` | PostHog region | `enum` | no | us or eu | one of `us`, `eu` |
| `projectId` | PostHog project id | `string` | no | the number in the project's URL (us.posthog.com/project/424242), digits only | up to 12 characters; matches `^[1-9][0-9]{0,11}$` |
| `funnels` | Funnels | `posthog-funnels` | no | 2 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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `id` | Id | `string` | yes | lowercase-with-dashes: bing-webmaster | up to 40 characters; matches `^[a-z0-9]+(?:-[a-z0-9]+)*$`; fixed once written |
| `label` | Label | `string` | yes | what the product calls it | up to 80 characters; fixed once written |
| `scope` | Scope | `enum` | yes | whether it collects for a site, for the OS, or both | one of `property`, `portfolio`, `both`; fixed once written |
| `layer` | Layer | `enum` | yes | whose failure a red cell reports | one of `os`, `provider`, `property`; fixed once written |
| `credential` | Credential | `enum` | yes | whether one credential can serve more than one site | one of `shared`, `per-property`; fixed once written |
| `docRef` | Doc | `string` | yes | the doc section that explains it | up to 200 characters; fixed once written |

## config/pull.json

Its README: [config/pull.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `id` | Id | `string` | yes | lowercase-with-dashes: claude-code | up to 64 characters; matches `^[a-z0-9]+(?:-[a-z0-9]+)*$`; fixed once written |
| `label` | Label | `string` | yes | what the charge is called on the statement | up to 80 characters |
| `asset` | Site | `asset-id` | yes | who carries it — the OS for anything portfolio-wide | — |
| `family` | Family | `enum` | yes | the ledger group it books under | one of `inference`, `api`, `infra`, `operator`, `os-overhead` |
| `amountUsdPerMonth` | USD / month | `number` | yes | the recurring charge | at least 0; fixed once written |
| `from` | From | `month` | yes | first month to book, YYYY-MM | — |
| `to` | To | `month` | no | last month to book, YYYY-MM | — |
| `note` | Note | `string` | no | copied onto each month's cost | up to 400 characters |

## config/serp-panel.json

Its README: [config/serp-panel.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `query` | Query | `string` | yes | verbatim, as a searcher types it | up to 120 characters |
| `label` | Bet | `string` | no | the bet this term counts toward | up to 60 characters; candidates suggest |

## config/signal-panels.json

Its README: [config/signal-panels.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `enabled` | Daily refresh | `boolean` | yes | rebuilt daily at no provider cost | — |
| `reason` | Reason | `enum` | yes | why it is on or off | one of `live-lanes`, `no-lane-yet`, `not-applicable` |
| `task` | Task | `string` | no | the id of the task that tracks this decision | up to 40 characters; matches `^[a-z]{2,8}-[a-z0-9]+(?:\.[0-9]+)*$` |
| `since` | Since | `date` | no | when 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](https://github.com/notice-cx/NoticeOS/blob/main/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).

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `list` | Home and Sites list | `boolean` | no | a row on Home and on the Sites page | — |
| `tv` | TV | `boolean` | no | every widget on the TV | — |
| `work` | Work this week | `boolean` | no | a row in the TV's Work this week | — |
| `lightIcon` | Light icon | `url` | no | drawn on light screens in place of the one read | up to 2048 characters |
| `darkIcon` | Dark icon | `url` | no | drawn on dark screens and the TV in place of the one read | up to 2048 characters |

## config/value-events.json

Its README: [config/value-events.README.md](https://github.com/notice-cx/NoticeOS/blob/main/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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `event` | GA4 event | `string` | yes | verbatim 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.

| Field | Label | Type | Required | Hint | Rule |
|---|---|---|---|---|---|
| `eventName` | GA4 event | `string` | yes | the saved event name | up to 40 characters; matches `^[A-Za-z][A-Za-z0-9_]*$` |
| `label` | Label | `string` | yes | the stage heading | up to 60 characters |
| `group` | Group | `enum` | yes | the display group | one of `primary`, `sharing`, `supporting` |
| `compareTo` | Compare to event | `string` | no | another declared event volume | up to 40 characters; matches `^[A-Za-z][A-Za-z0-9_]*$` |
| `comparisonLabel` | Comparison label | `string` | no | the independent-volume comparison heading | up to 60 characters |
