Skip to content

InstanceConfig schema

Per-deployment configuration for a BulletinMail instance. Lives at deployments/<apex>/instance.config.json and is loaded at Worker startup via loadFromEnv in packages/shared/src/config.ts. The JSON Schema is at packages/shared/instance.config.schema.json.

Schema

Identity

FieldTypeDefaultDescription
apexDomainstring (required)Root domain serving the instance, e.g. bulletinmail.org.
adminDomainstring (required)Host serving the admin app, e.g. app.bulletinmail.org. Must be a subdomain of apexDomain.
productNamestring (required)Display name, e.g. "BulletinMail". Used in email subject prefixes, From-header decorations, and page titles.
productNameShortstring (required)Short form, e.g. "Bulletin". Used where space is tight.
taglinestring (required)Marketing line shown on the apex landing and email footers.

System addresses

All values are local-parts (no @<apex>); combined with apexDomain at runtime.

FieldTypeDefaultDescription
supportAddressstring"support"Operator support contact.
abuseAddressstring"abuse"Abuse reports.
dmarcAddressstring"dmarc"DMARC aggregate / forensic report destination.
noreplyAddressstring"noreply"Default From local-part for system-generated mail.
unsubscribeAddressPrefixstring"unsubscribe+"Local-part prefix for one-click unsubscribe tokens. The full pattern is <prefix><token>@<apex>.

URL templates

Placeholders {tenant}, {group}, {token}, {apex} are interpolated at template-expansion time.

FieldTypeDefaultDescription
archiveUrlTemplatestring (required)Per-group archive URL. Supports {tenant}, {group}, {apex}.
unsubscribeUrlTemplatestring (required)RFC 8058 one-click URL. Supports {token}, {apex}.
adminUrlstring (required)Fully-qualified URL of the admin app (typically https://<adminDomain>).

Slug policy

Tenant slugs become DNS subdomains; the policy below is enforced by validateTenantSlug in packages/shared/src/slug.ts.

FieldTypeDefaultDescription
additionalReservedSlugsstring[][]Per-instance reserved slugs, added to the base list in packages/shared/src/slug.ts.
minSlugLengthinteger3Minimum slug length.
maxSlugLengthinteger40Maximum slug length.

Rate limits

Defaults applied to new tenants. Individual tenant rows may override.

FieldTypeDefaultDescription
defaultDailyMessageLimitPerTenantinteger1000Maximum outbound messages per tenant per UTC day.
defaultMaxRecipientsPerGroupinteger500Maximum active members per group.

Operator metadata

Rendered in footers, abuse reports, and as the DMARC contact.

FieldTypeDescription
operator.legalNamestring (required)Legal name of the operator (CAN-SPAM compliance).
operator.mailingAddressstring (required)Postal address rendered in email footers (CAN-SPAM compliance).
operator.contactUrlstring (required)URL to the operator’s contact / support page.

Feature toggles

FieldTypeDefaultDescription
features.byoDomainEnabledbooleanfalseWhether self-service “bring-your-own-domain” signup is offered.
features.publicArchivesAllowedbooleantrueMaster switch for public archives. Per-group archive_visibility setting still applies.
features.signupSelfServicebooleanfalseWhether public signup is enabled. false in V1 (operator creates tenants via CLI).

Sources of values, by environment

LayerSource
Generic defaultspackages/shared/src/config.ts exports defaults: Partial<InstanceConfig>.
Reference deploymentdeployments/bulletinmail.org/instance.config.json.
Operator deploymentdeployments/<their-apex>/instance.config.json.
Local devinstance.config.local.json at repo root (gitignored).
Runtime injectionscripts/render-wrangler.ts merges layers, emits [vars] per Worker.

Wrangler [vars] mapping

Each field renders to a single [vars] entry in wrangler.generated.toml. Naming convention is INSTANCE_<UPPER_SNAKE>:

Config fieldWrangler var
apexDomainINSTANCE_APEX_DOMAIN
adminDomainINSTANCE_ADMIN_DOMAIN
productNameINSTANCE_PRODUCT_NAME
productNameShortINSTANCE_PRODUCT_NAME_SHORT
taglineINSTANCE_TAGLINE
supportAddressINSTANCE_SUPPORT_ADDRESS
abuseAddressINSTANCE_ABUSE_ADDRESS
dmarcAddressINSTANCE_DMARC_ADDRESS
noreplyAddressINSTANCE_NOREPLY_ADDRESS
unsubscribeAddressPrefixINSTANCE_UNSUB_PREFIX
archiveUrlTemplateINSTANCE_ARCHIVE_URL
unsubscribeUrlTemplateINSTANCE_UNSUB_URL
adminUrlINSTANCE_ADMIN_URL
additionalReservedSlugsINSTANCE_RESERVED_SLUGS (CSV)
minSlugLengthINSTANCE_MIN_SLUG_LENGTH
maxSlugLengthINSTANCE_MAX_SLUG_LENGTH
defaultDailyMessageLimitPerTenantINSTANCE_DEFAULT_DAILY_MSG_LIMIT
defaultMaxRecipientsPerGroupINSTANCE_DEFAULT_MAX_RECIPIENTS
operator.legalNameINSTANCE_OPERATOR_LEGAL_NAME
operator.mailingAddressINSTANCE_OPERATOR_MAILING_ADDRESS
operator.contactUrlINSTANCE_OPERATOR_CONTACT_URL
features.byoDomainEnabledINSTANCE_FEATURE_BYO_DOMAIN ("true"/"false")
features.publicArchivesAllowedINSTANCE_FEATURE_PUBLIC_ARCHIVES
features.signupSelfServiceINSTANCE_FEATURE_SIGNUP_SELF_SERVICE

Example

The reference deployment overlay (deployments/bulletinmail.org/instance.config.json):

{
"apexDomain": "bulletinmail.org",
"adminDomain": "app.bulletinmail.org",
"productName": "BulletinMail",
"productNameShort": "Bulletin",
"tagline": "Mailing lists that just work.",
"archiveUrlTemplate": "https://bulletinmail.org/g/{tenant}/{group}",
"unsubscribeUrlTemplate": "https://bulletinmail.org/u/{token}",
"adminUrl": "https://app.bulletinmail.org",
"operator": {
"legalName": "Scott Pierce",
"mailingAddress": "...",
"contactUrl": "https://bulletinmail.org/contact"
},
"features": {
"byoDomainEnabled": false,
"publicArchivesAllowed": true,
"signupSelfService": false
}
}