-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrender.yaml
More file actions
193 lines (185 loc) · 9.69 KB
/
Copy pathrender.yaml
File metadata and controls
193 lines (185 loc) · 9.69 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# render.yaml — Render Blueprint for the dash-leaflet2 documentation site.
# Deploys run.py as a Docker web service, fronted by https://leaflet.2plot.dev.
# Blueprint spec: https://render.com/docs/blueprint-spec
#
# How to deploy:
# 1. Push this repo (with Dockerfile + render.yaml) to GitHub.
# 2. Render dashboard → New → Blueprint → select this repo.
# 3. Render builds the Dockerfile and serves run:server.
# 4. Add the custom domain leaflet.2plot.dev and point its CNAME at the
# service. The Clerk satellite domain below must match it exactly.
#
# Local equivalent (no Render needed):
# docker build -t dash-leaflet2-docs .
# docker run --rm -p 8050:8050 -e PORT=8050 dash-leaflet2-docs
# open http://localhost:8050
services:
- type: web
name: dash-leaflet2-docs
runtime: docker
dockerfilePath: ./Dockerfile
dockerContext: .
# Starter (always-on): the free tier sleeps after ~15 min idle, cold-starts
# on the next request, and its evictions swallow unreported analytics. The
# dashboard plan was upgraded 2026-08-16; this file matching it is what
# keeps a future blueprint sync from silently downgrading the service.
plan: starter
# /healthz is the 2plot network convention (lib/health.py) and is excluded
# from traffic counts, so it makes a cleaner check than /.
healthCheckPath: /healthz
autoDeploy: true
envVars:
# --- Core --------------------------------------------------------
# Flask (WSGI) backend, served by gunicorn. Do NOT set fastapi/quart
# here: those are ASGI and would need uvicorn instead of gunicorn.
- key: DASH_BACKEND
value: flask
# gunicorn worker processes. 2 is a reasonable default; drop to 1 if the
# free tier's 512 MB feels tight. The Dockerfile also runs 4 threads per
# worker for callback concurrency.
- key: WEB_CONCURRENCY
value: "2"
# Public origin for canonical URLs, sitemap.xml and llms.txt.
#
# BOTH spellings, deliberately. APP_BASE_URL is the network-standard name
# that the shared scripts/ and tests/ expect; DASH_LEAFLET2_BASE_URL is
# what this service has been running with. lib/constants reads the
# standard one first and falls back to the legacy one, so either alone
# works — but dropping the old name from a LIVE service is how a host
# starts advertising the wrong canonical origin, which deindexes it
# quietly. Keep both until the service is confirmed on the new name.
- key: APP_BASE_URL
value: https://leaflet.2plot.dev
- key: DASH_LEAFLET2_BASE_URL
value: https://leaflet.2plot.dev
# --- 2plot.dev ad network (lib/ad_client.py) ---------------------
# Without AD_SERVER_URL reachable the slot simply stays hidden, and a
# 60s circuit breaker stops retrying, so an outage never slows a page.
- key: AD_SERVER_URL
value: https://2plot.dev
# This app's identity in the ad network's /admin/ad-board tables.
# The hub's directory key, NOT the package name. `canonical_app_id()` on
# 2plot.dev folds the legacy `dash-leaflet2` in at ingest, so the change
# is safe mid-flight — but the hub's directory entry lists `dash-leaflet2`
# under `legacy_ids` precisely "until leaflet's own network-standard pass
# sets AD_APP_ID=leaflet". This is that pass.
- key: AD_APP_ID
value: leaflet
# --- 2plot.ai satellite analytics ---------------------------------
# (lib/analytics_tracker.py + lib/traffic_rollup.py +
# lib/satellite_reporter.py — the trio that replaced the Gen-1
# single-module tracker in the fleet's 1.3.x instrumentation sync.)
#
# The shared HMAC secret every satellite holds. Set it in the Render
# dashboard (same value as on 2plot.ai) — never in this file.
# Without it the app still serves /healthz but reports nothing.
# Hub side, to health-sweep this app hourly, add to 2plot.ai:
# PULSE_POLL_TARGETS=...,leaflet=https://leaflet.2plot.dev/healthz
- key: CROSS_APP_WEBHOOK_SECRET
sync: false
# The series name this app reports under on 2plot.ai/traffic. "leaflet"
# is this app's 2plot network-directory key — the hub labels and colours
# the series from that directory. (The Gen-1 spelling SATELLITE_APP_ID
# is retired with the module that read it; the trio reads only this
# name. The dashboard may still carry the old variable — harmlessly,
# nothing reads it now.)
- key: SATELLITE_APP_KEY
value: leaflet
# The hub takes the LAST report for a given (app, date). On an ephemeral
# filesystem a mid-day deploy wipes the ledger and the next hourly report
# overwrites the day's real total with whatever accrued since the
# restart. The disk below is what stops that.
- key: TRAFFIC_ANALYTICS_FILE
value: /var/data/visitor_analytics.json
# Behind Cloudflare the country header is already present, so the
# ip-api.com lookup is redundant latency.
- key: ANALYTICS_GEO_LOOKUP
value: "0"
# --- Corpus document tiers (lib/page_tiers.py; registered in run.py) --
# Access tiers for /llms-small.txt and /llms-full.txt
# (dash-improve-my-llms >= 2.4.0). Deliberately set to the default so
# the knob is visible here: the 402 experiment tightens the full corpus
# by flipping this to `auth`, per satellite, with no code change.
- key: LLMS_SMALL_TIER
value: public
- key: LLMS_FULL_TIER
value: public
# --- 2plot.dev network bulletin (lib/bulletin.py) -----------------
# The hub's announcement feed, rendered in the header of this site's
# llms.txt viewer. Opt-in — unset means the feature is simply off.
#
# NOTE: Render applies blueprint envVars on a BLUEPRINT SYNC, not on an
# autoDeploy from a git push. Adding this line alone leaves the variable
# absent on the service and the panel empty, which is exactly how
# email.2plot.dev shipped wired code and an unwired deployment. Sync the
# blueprint or add it in the dashboard.
- key: NETWORK_BULLETIN_URL
value: https://2plot.dev/api/network/bulletin
# --- Clerk satellite auth (lib/auth.py) --------------------------
# All of these are OPTIONAL: with them absent the site runs fully public
# and /admin/control-board returns a 404 (it fails CLOSED — see
# lib.auth.admin_access_open). Set ALL of the first three to turn auth on.
- key: CLERK_SECRET_KEY
sync: false
- key: CLERK_PUBLISHABLE_KEY
sync: false
# The 2plot.ai PRIMARY on its production Clerk instance. These are the
# Account Portal and Frontend API custom domains, not the *.accounts.dev
# hosts — those belong to the dev instance and cannot host satellites.
- key: CLERK_SIGN_IN_URL
value: https://accounts.2plot.ai/sign-in
- key: CLERK_SIGN_UP_URL
value: https://accounts.2plot.ai/sign-up
# REQUIRED in satellite mode. A production custom-domain instance cannot
# derive this from CLERK_SIGN_IN_URL — it must be set explicitly.
- key: CLERK_FRONTEND_API
value: https://clerk.2plot.ai
# The REGISTERED SATELLITE DOMAIN — deliberately NOT the host this app is
# served on. clerk-js derives the Frontend API from this value as
# `clerk.<domain>`, and Clerk only issues those DNS records per satellite
# domain. `clerk.2plot.dev` exists (CNAME -> frontend-api.clerk.services);
# `clerk.leaflet.2plot.dev` is NXDOMAIN, because leaflet.2plot.dev is an
# ALLOWED SUBDOMAIN of the 2plot.dev satellite rather than a satellite of
# its own. Setting the served host here sends the browser to a Frontend
# API that does not resolve, and sign-in hangs on
# /v1/client/sync?redirect_url=...
#
# Session cookies are scoped to .2plot.dev, so leaflet.2plot.dev reads
# them as a subdomain — which is exactly what the allowlist enables.
- key: CLERK_SATELLITE_DOMAIN
value: 2plot.dev
- key: CLERK_IS_SATELLITE
value: "true"
# Signs the session + __dca_identity cookies. Without it dash-clerk-auth
# falls back to a PUBLIC dev default string.
- key: SESSION_SECRET
generateValue: true
# Allowlist for /admin/control-board. The OWNER_EMAIL in lib/auth.py
# always counts, so this is for additional administrators.
- key: ADMIN_EMAILS
sync: false
# --- Page visibility (lib/page_visibility.py) --------------------
# Baseline tier for pages whose frontmatter does not set one. "public"
# keeps the component documentation readable without an account; the
# control board can still flip any individual page live.
- key: PAGE_DEFAULT_VISIBILITY
value: public
# Overrides are written here — on the analytics disk, so control-board
# changes now OUTLIVE a deploy (they used to live on the ephemeral
# container filesystem and reset with every one).
- key: PAGE_VISIBILITY_FILE
value: /var/data/page_visibility.json
# --- Optional ----------------------------------------------------
# MUI X Pro licence for the TreeViewPro tile browser on
# /tile-layers-pro. Absent → that one control renders watermarked; the
# rest of the page is unaffected.
- key: MUI_PRO_API_KEY
sync: false
# Persistent storage for the analytics ledger (and the control board's
# visibility overrides). The hub keeps only the LAST report per
# (app, date), so a ledger that dies with the container silently
# under-reports every deploy day.
disk:
name: analytics
mountPath: /var/data
sizeGB: 1