Project Configuration
The norq.config.yaml file controls project-wide settings: notification directory, provider credentials, channel routing, email theme, and code generation targets.
Minimal config
# norq.config.yaml
notifications: ./notifications
providers:
console:
config: {}
routing:
email: consoleNotifications path
The notifications key points to the root directory containing your notification folders:
notifications: ./notificationsAll notification type folders (system/, transactional/, promotional/) and the _shared/ partials directory live under this path.
Providers
A provider is a delivery service -- Resend for email, Twilio for SMS, etc. Declare provider credentials under providers. Environment variables use ${VAR} syntax and are substituted at load time.
providers:
resend:
config:
api_key: ${RESEND_API_KEY}
twilio:
config:
account_sid: ${TWILIO_SID}
auth_token: ${TWILIO_TOKEN}
from: "+1234567890"
console:
config: {}Console provider
The console provider prints compiled payloads to stdout. Use it for local development and CI -- no credentials needed:
providers:
console:
config: {}
routing:
email: console
sms: console
slack: consoleRouting
Routing maps each channel to the provider that delivers it. Only channels with a routing entry are deliverable via norq send.
routing:
email: resend
sms: twilio
slack: consoleIf a channel has no routing entry, norq send skips it (even if the template exists).
Theme
Theme settings control email rendering. All theme keys use camelCase -- snake_case keys are silently ignored.
theme:
brandColor: "#18181b"
buttonColor: "#18181b"
fontFamily: "Inter, sans-serif"
darkMode: auto
codeTheme: "base16-ocean.dark"
dark:
backgroundColor: "#1a1a1a"
textColor: "#e5e5e5"
cardColor: "#262626"
fonts:
- family: "Inter"
weight: 400
style: normal
src:
- url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2"
format: woff2Color tokens
| Key | Description |
|---|---|
brandColor |
Links, accents |
headingColor |
Heading text |
bodyColor |
Body text |
backgroundColor |
Outer background |
contentColor |
Content area background |
cardColor |
Callout/card background |
buttonColor |
Primary button background |
buttonTextColor |
Primary button text |
secondaryColor |
Secondary button background |
secondaryTextColor |
Secondary button text |
dangerColor |
Danger button background |
successColor |
Success button background |
warningColor |
Warning button background |
Additional text color variants: dangerTextColor, successTextColor, warningTextColor.
Typography
| Key | Description |
|---|---|
fontFamily |
Font stack |
fontSize |
Base font size (e.g., "16px") |
lineHeight |
Line height |
contentWidth |
Max width of content area (e.g., "600px") |
Custom web fonts
Load web fonts with the fonts array (top-level, not nested under theme):
fonts:
- family: "Inter"
weight: 400
style: normal
src:
- url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2"
format: woff2
theme:
fontFamily: "Inter, sans-serif"Fields: family (required), weight (default 400), style (default "normal"), src (list of {url, format} objects). Each entry generates a CSS @font-face rule in compiled email HTML. Reference the loaded font in fontFamily.
Dark mode
Control dark mode with the darkMode key:
theme:
darkMode: auto
dark:
brandColor: "#e4e4e7"
backgroundColor: "#09090b"
bodyColor: "#d4d4d8"
cardColor: "#18181b"| Value | Behavior |
|---|---|
omitted / off |
No dark mode styles |
auto |
Emits @media (prefers-color-scheme: dark) CSS |
dark |
Always renders in dark mode |
The dark: block accepts the same color and typography keys as the root theme. Unset keys fall back to light values.
Code syntax highlighting
Enable syntax highlighting for fenced code blocks in email:
theme:
codeTheme: "base16-ocean.dark"Fenced code blocks with a language tag (e.g., ```python) compile to syntax-highlighted HTML. Without codeTheme, code blocks render as plain monospace. Uses syntect themes.
Per-template overrides
Override theme keys in a template's frontmatter:
---
subject: "Special offer"
brandColor: "#7c3aed"
---Or apply the built-in dark theme: theme: dark.
See the email channel page for rendering examples.
Code generation
Generate type-safe SDK bindings from your data.schema.yaml files. Configure targets in the config file:
codegen:
- lang: typescript
out: ./src/generated/norq
- lang: python
out: ./generated/norqSupported languages: typescript, python, go, java, ruby.
norq codegen # use config targets
norq codegen --lang python --out ./generated/norq
norq codegen --check # CI: verify files are up to dateCodegen reads all data.schema.yaml files and generates one file per notification with short leaf names. The output directory mirrors the notification structure.
Output structure (Python example):
generated/norq/
__init__.py # re-exports all types
transactional/
welcome.py # WelcomeData, WelcomeChannel
account/
security_alert.py # SecurityAlertData
system/
password_reset.py # PasswordResetData
Top-level types are public (WelcomeData). Nested types are private (_WelcomeDataUser in Python/TypeScript/Ruby, unexported in Go, package-private in Java). Import from the module path:
from generated.norq.transactional.welcome import WelcomeDataimport { WelcomeData } from "./generated/norq/transactional/welcome";For full codegen details, see the Code Generation page.
Full example
# norq.config.yaml
notifications: ./notifications
providers:
resend:
config:
api_key: ${RESEND_API_KEY}
twilio:
config:
account_sid: ${TWILIO_SID}
auth_token: ${TWILIO_TOKEN}
from: "+1234567890"
console:
config: {}
routing:
email: resend
sms: twilio
slack: console
push: console
theme:
brandColor: "#18181b"
buttonColor: "#18181b"
fontFamily: "Inter, sans-serif"
fontSize: "16px"
contentWidth: "600px"
darkMode: auto
dark:
backgroundColor: "#1a1a1a"
textColor: "#e5e5e5"
cardColor: "#262626"
fonts:
- family: "Inter"
weight: 400
style: normal
src:
- url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2"
format: woff2
codegen:
- lang: typescript
out: ./src/generated/norqSee Data Contracts for data.schema.yaml and data.samples.yaml format.