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: console

Notifications path

The notifications key points to the root directory containing your notification folders:

notifications: ./notifications

All 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: console

Routing

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: console

If 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: woff2

Color 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/norq

Supported 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 date

Codegen 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 WelcomeData
import { 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/norq

See Data Contracts for data.schema.yaml and data.samples.yaml format.