npm run build compiles TypeScript into dist/. The runtime directory must
include dist/, package.json, package-lock.json, and production
dependencies.
npm ci
npm run buildCreate config/sites.yml from config/sites.yml.example. The repository
includes a local dallas.lu registry as a starting point; adjust its root for
deployment. The read APIs are public, so a public article can lazy-load its
own data without exposing a token to browser scripts. Existing per-site
token settings remain accepted for compatibility with the provider
configuration.
PM2 should run dist/server.js. If dist/ is copied to another runtime
directory, install production dependencies there with npm ci --omit=dev.
Point interact at the Press sites directory:
SITES_ROOT=../press/sites npm run devFor a site whose primary domain is xxx.com, configure Press to use interact:
interaction:
endpoint: 'http://localhost:8787/api/v1/interaction'
webmention:
endpoint: 'http://localhost:8787/api/v1/webmention'
pingback:
endpoint: 'http://localhost:8787/api/v1/pingback'
postal:
endpoint: 'http://localhost:8787/api/v1/postal/interact?secret=...'
unsubscribe_endpoint: 'http://localhost:8787/api/v1/postal/unsubscribe?secret=...'Press includes the public article URL when it calls the interaction endpoint. interact uses that URL's host to map the request to the correct site directory.
Postal callbacks are mapped to a site by the message recipient address. The
recipient must match the site's email.sender, postal.email,
postal.address, or postal.recipient/postal.recipients value.
interact sends new-comment notification emails after native comments are saved
through either /api/v1/interaction/* or /api/v1/postal/interact.
Use the existing Press-style site configuration:
email:
sender: 'comments@example.com'
postal:
enabled: true
endpoint: 'http://localhost:8787/api/v1/postal/interact?site=xxx.com&secret=...'
unsubscribe_endpoint: 'http://localhost:8787/api/v1/postal/unsubscribe?site=xxx.com&secret=...'
private:
email:
admin:
value: 'admin@example.com'
smtp:
host: 'smtp.example.com'
port: 587
secure: false
user: 'comments@example.com'The read APIs are:
GET /api/v1/comment/<route> -> { replies, mentions }
GET /api/v1/interaction/<route> -> { replies, mentions }
GET /api/v1/webmention/<route> -> { mentions }
All read APIs accept since=<ISO date> and return only records changed after
that time. The interaction endpoint remains backwards compatible and returns
both channels; the comment and webmention endpoints are convenient channel
specific aliases.
Set SMTP_PASS and SECRET_KEY in data/config/env.yml or the process
environment. INTERACT_SECRET_KEY can override SECRET_KEY for interact.
interact applies the Press-style request rate limit before handling endpoints,
at the platform level: 1,000 water units per IP per 60 seconds, with API GET
requests costing 5 units and API POST requests costing 100 units. Configure
global allowlisted IPs with the process environment IP_LIMIT_WHITE_LIST. Set
RATE_LIMIT_FILE to persist buckets across restarts.
Native comments are scored for spam before they are saved. The scorer checks
missing author fields, verified/user authors, language mismatch, .ru signals,
content length, links, URLs, bare domains, link-heavy content, and comment
language probability.