-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path.env.example
More file actions
105 lines (95 loc) · 6.07 KB
/
Copy path.env.example
File metadata and controls
105 lines (95 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# This file is committed to version control — never put secrets in it.
# Copy it to .env.local and fill in the real values:
# cp .env.example .env.local
# ── App ────────────────────────────────────────────────────────────────────
# Canonical site URL. Used in email links, sitemap, OG tags. Default in code
# is https://adamastor.blog if unset.
NEXT_PUBLIC_APP_URL=
# ── Supabase ───────────────────────────────────────────────────────────────
NEXT_PUBLIC_SUPABASE_URL=
# "anon" / "publishable" key — browser-safe, RLS-respecting.
NEXT_PUBLIC_SUPABASE_ANON_KEY=
# "service_role" / "secret" key — SERVER ONLY, bypasses RLS.
# Used by /api/events/submissions so anonymous form posts can insert. Never
# expose to the browser. See docs/security-and-rls.md for the threat model.
SUPABASE_SERVICE_ROLE_KEY=
# Personal access token for the Supabase CLI (db push, gen types). Only
# needed if you run the CLI locally.
SUPABASE_ACCESS_TOKEN=
# ── Cloudflare Turnstile (event submission spam protection) ────────────────
# Required in prod. If unset, the widget doesn't render and verification is
# skipped with a warning — convenient for dev, dangerous for prod.
# Cloudflare provides always-pass dummy keys for local testing:
# NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
# TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
TURNSTILE_SECRET_KEY=
# ── Event submissions ──────────────────────────────────────────────────────
# Optional. Comma-separated extra emails to cc on new-submission notifications,
# in addition to every profiles.role='admin' user.
EVENT_SUBMISSIONS_NOTIFY_EXTRA=
# ── Resend (transactional + newsletter) ────────────────────────────────────
RESEND_API_KEY=
# Weekly editorial digest segment. New unspecified signups (e.g. the footer
# form on /posts/*) land here by default.
RESEND_SEGMENT_ID=
# Legacy alias kept for backward compatibility with older configs.
RESEND_AUDIENCE_ID=
# Base segment containing every contact. Broadcasts always need a base
# segment ID; per-category broadcasts additionally pass a topicId to filter
# to opted-in contacts. Create one segment in Resend that matches all
# contacts in your audience.
RESEND_SEGMENT_ALL_SUBSCRIBERS=
# Per-category event newsletters use Resend Topics (opt-in/opt-out
# preferences) — created manually in the Resend dashboard with
# defaultSubscription: opt_out and Visibility: Public. Paste topic IDs here.
# A missing var is treated as "this category isn't wired up yet" and skipped;
# local dev works without setting all five. See docs/newsletter-subscriptions.md.
RESEND_TOPIC_AI=
RESEND_TOPIC_SOFTWARE_ENGINEERING=
RESEND_TOPIC_DESIGN=
RESEND_TOPIC_PRODUCT=
RESEND_TOPIC_STARTUPS_FUNDRAISING=
# ── Newsletter send auth (REQUIRED) ─────────────────────────────────────────
# Gates /api/sendNewsletter — the route that can broadcast to ALL subscribers.
# REQUIRED: the route fails closed (rejects everything) until this is set.
# Pass it as `Authorization: Bearer <value>` for manual sends/QA. The cron
# route forwards it automatically. Generate with `openssl rand -hex 32`.
NEWSLETTER_SEND_SECRET=
# ── Newsletter cron (Cloudflare worker → /api/cron/send-newsletter) ─────────
# Automated per-category sends need BOTH gates below — on top of deploying the
# worker. Deploying the worker is NOT enough; it stays silent until both are
# set. (A Monday send was missed exactly this way: worker deployed, gates unset.)
#
# 1. NEWSLETTER_CRON_SECRET — shared secret the worker presents. Set the SAME
# value HERE (Vercel) *and* on the worker:
# cd workers/newsletter-cron && npx wrangler secret put NEWSLETTER_CRON_SECRET
# Set here but missing on the worker → every tick 401s and nothing sends.
# Distinct from NEWSLETTER_SEND_SECRET on purpose: the worker never holds
# the send secret (least privilege). Generate with `openssl rand -hex 32`.
# 2. NEWSLETTER_CRON_ENABLED — master switch. Until it equals EXACTLY "true",
# every cron call is a DRY RUN that sends nothing. Leave unset until ready.
#
# Smoke-test both after any deploy, without sending (dryRun never sends):
# curl -X POST https://adamastor.blog/api/cron/send-newsletter \
# -H "Authorization: Bearer <NEWSLETTER_CRON_SECRET>" \
# -H 'Content-Type: application/json' -d '{"category":"design","dryRun":true}'
# → 200 + "enabled":true means armed. 401 = secret mismatch; enabled:false = switch off.
# Full setup: workers/newsletter-cron/README.md.
NEWSLETTER_CRON_SECRET=
NEWSLETTER_CRON_ENABLED=
# ── PostHog (analytics) ────────────────────────────────────────────────────
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=
# Server-side analytics queries (e.g. dashboard WAU). Keep these server-only.
POSTHOG_API_HOST=
POSTHOG_PERSONAL_API_KEY=
POSTHOG_PROJECT_ID=
# ── Vercel Blob (image uploads in the rich-text editor) ────────────────────
# Without this, image upload in the post editor falls back to a local read
# and a console warning. Required for the dashboard editor to upload images.
BLOB_READ_WRITE_TOKEN=
# ── Dev flags ──────────────────────────────────────────────────────────────
# Uncomment to surface admin UI controls in environments where you don't
# have a real admin session — useful for local UI work.
# NEXT_ALLOW_BAD_UI=true