Plan 9 gives each process its own namespace — a different view of the filesystem based on who you are. The edge can do the same thing.
The idea
Pre-generate a site.json per role at build time:
s3://bucket/site/public.json
s3://bucket/site/user.json
s3://bucket/site/kids.json
s3://bucket/site/friends.json
The edge reads the JWT, determines the role, rewrites /site.json to /site/{role}.json. Static files, fully cacheable per role. No Lambda processing on every request.
What each user sees
- Public:
site/public.json→ public sections only - Logged-in:
site/user.json→ public + user sections - Kids group:
site/kids.json→ public + user + kids sections - Friends group:
site/friends.json→ public + user + friends sections
The namespace is composable and per-user. The files are static. The edge is the mount point.
Why this works
Same pattern as the existing role-scoped content.json files — already doing this for post feeds. Extending it to site.json means the browser never sees sections it can't access. No 403s, no wasted requests, no leaking what exists to unauthorized users.
Four files generated at build time. The edge picks the right one. No runtime filtering needed.
For the enterprise project
This is how multi-tenancy works without a server. Each tenant gets their own site.json variant. The edge routes by identity. Same bucket, different views. Scale to thousands of tenants with no infrastructure change — just more static files.
The journey
prev: content-json-at-the-edge The edge-filtering idea applied to site.json. Instead of filtering at runtime, pre-generate per role and let the edge pick. Same pattern already used for content.json. Plan 9 per-process namespaces realized on a CDN.