FaceTheory AWS Deployment Shape
This document captures the supported production topology and the request-routing assumptions behind the canonical AWS guidance.
Recommended Topology
FaceTheory’s supported production shape is:
- CloudFront as the public entrypoint
- S3 for static assets and optional SSG output
- Lambda Function URL for dynamic SSR and ISR regeneration
- DynamoDB metadata storage when using blocking ISR through TableTheory
Origin Layout
Primary components:
- S3 bucket for hashed assets, optional SSG HTML output, and strict-CSP SSG hydration JSON sidecars
- Lambda Function URL origin for SSR and ISR
- Optional S3 bucket or prefix for ISR HTML objects and pointer-derived strict-CSP hydration sidecars
- DynamoDB table for ISR metadata and lease state
Recommended static paths:
/assets/*/.vite/*/_facetheory/data/*
Recommended Lambda-reserved paths:
/_facetheory/ssr-data/*
AppTheory CDK Wiring
The reference stacks use AppTheory CDK and wire these runtime conventions:
| Variable | Meaning |
|---|---|
APPTHEORY_ASSETS_BUCKET |
Assets bucket name |
APPTHEORY_ASSETS_PREFIX |
Assets prefix |
APPTHEORY_ASSETS_MANIFEST_KEY |
Vite manifest key |
APPTHEORY_CACHE_TABLE_NAME |
Metadata table alias |
FACETHEORY_CACHE_TABLE_NAME |
Metadata table alias |
CACHE_TABLE_NAME |
Metadata table alias |
CACHE_TABLE |
Metadata table alias |
FACETHEORY_ISR_BUCKET |
ISR HTML bucket |
FACETHEORY_ISR_PREFIX |
ISR HTML prefix |
Reference-stack stance:
- prefer a CloudFront-signed
AWS_IAMFunction URL origin for read-only SSR traffic - do not model viewer-supplied tenant-header passthrough as the default copy-paste shape
- keep same-origin mutating form action paths on Lambda/AppTheory behaviors, usually through
ssrPathPatterns - use FaceTheory’s marked URL-encoded OAC form helper for browser forms that submit through Lambda Function URL OAC
- keep
/_facetheory/data/*on S3 for SSG hydration sidecars - keep
/_facetheory/ssr-data/*on Lambda/FaceTheory for SSR runtime hydration sidecars - keep ISR hydration query URLs on Lambda/FaceTheory
- attach strict CSP headers from the Face response; baseline CloudFront response headers do not substitute for a
route-owned
content-security-policy
Mutating Forms Behind Lambda Function URL OAC
AppTheorySsrSite keeps the Lambda Function URL origin protected by AWS_IAM and CloudFront Lambda URL OAC. Browser
forms that submit mutating methods cannot attach the x-amz-content-sha256 header that CloudFront must sign for the
exact payload bytes, so native form POSTs can fail before the request reaches AppTheory or FaceTheory.
Supported contract:
- render the form action as a same-origin CloudFront path, never a direct Lambda Function URL
- route the action path to Lambda through
ssrPathPatternseven when the page containing the form is SSG or ISR - mark URL-encoded forms with
data-facetheory-oac-form - install
startAwsOacFormTransport()from a client bootstrap module - keep app authentication, authorization, CSRF, idempotency, and business validation in application-owned code
The helper hashes the exact application/x-www-form-urlencoded bytes it sends and adds x-amz-content-sha256 for AWS
signing. It fails closed for marked multipart, text/plain, unknown encodings, cross-origin actions, unsafe redirect
handling, and default document replacement of CSP-protected HTML responses. Do not turn ssrUrlAuthType to NONE as a
durable solution; use it only as an explicitly authorized temporary rollback with an owner and removal date.
Strict CSP Hydration Sidecars
Strict no-inline CSP uses same-origin external hydration data instead of inline __FACETHEORY_DATA__.
SSG:
/_facetheory/data/*should be listed indirectS3PathPatternsso CloudFront serves generated hydration JSON from S3.- Upload and invalidate each generated HTML file and its hydration JSON sidecar together.
- Use JSON content type and cache headers coordinated with the referencing HTML; hashed client assets can still be immutable.
ISR:
- Hydration sidecars are stored in the same
S3HtmlStorenamespace as generated HTML, with.hydration.jsonderived from the HTML pointer. - The browser URL is the route URL plus
__facetheory_isr_hydration=<opaque-token>. Route that request to Lambda/FaceTheory so the runtime can resolve the same tenant/cache-key request variant before serving the sidecar. - Do not add a public S3 behavior for arbitrary ISR object keys or expose the raw pointer as a stable client contract.
A copied ISR sidecar URL is not a bearer credential; mismatched tenant, authorization-like headers, cookies, or query
variants fail closed with
404.
SSR:
- If a strict SSR Face uses
createFaceApp({ ssrHydrationSidecars }), FaceTheory emits signed same-origin hydration URLs under/_facetheory/ssr-data/*. - Route
/_facetheory/ssr-data/*to the same Lambda/FaceApp handler that rendered the SSR HTML so the runtime returns the exact payload produced during that render without rerunning the Face. - Do not route SSR hydration sidecars through
/_facetheory/data/*; that prefix remains reserved for SSG/static JSON on S3.
OAC navigation policy:
- Use
startAwsOacFormTransport()’s default full-page navigation for strict-CSP form outcomes unless the host has explicitly chosen the SPA navigation contract. - Use
navigationPolicy: "spa"only when the response is a FaceTheory document and external hydration can be loaded before DOM mutation, and do not use it as an escape hatch for HTML responses carryingContent-Security-Policy; choosenavigationPolicy: "full-page"or a caller-ownedonNavigate/onResponsepath for those responses.
CloudFront Behavior Options
Choose between these patterns based on how many SSG routes you have and whether you want static misses to fail over to Lambda automatically.
Strategy A: Origin Group For Large SSG Route Sets
Use:
- S3 as primary
- Lambda Function URL as failover on
403or404
This is useful when:
- many extensionless SSG routes should avoid Lambda
Requirements:
- rewrite extensionless paths to S3 HTML keys
- preserve the original viewer path for Lambda failover routing
- reserve
/_facetheory/data/*as a direct S3 behavior for SSG/static sidecars - reserve
/_facetheory/ssr-data/*as a direct Lambda behavior for SSR runtime sidecars - keep SSR cache headers explicit and conservative
- when using
AppTheorySsrSite, treatstaticPathPatternsas HTML sections,directS3PathPatternsas raw data/object paths, andssrPathPatternsas Lambda-only dynamic routes - if tenant identity matters, derive it from trusted context instead of forwarding raw viewer tenant headers by default
Strategy B: Explicit Static Behaviors
Use:
- dedicated S3 behaviors for known static routes
- Lambda Function URL as the default behavior
This is useful when:
- the static route set is small and predictable
Notes:
- use Origin Access Control for S3
- forward only headers/cookies/query actually required by app logic
- avoid modeling viewer-supplied tenant headers as part of the default origin request contract
Cache Policy By Rendering Mode
SSR:
- default to
cache-control: private, no-store - route strict-CSP SSR hydration sidecars under
/_facetheory/ssr-data/*to Lambda/FaceTheory with no shared cache - do not cache responses that set cookies
SSG:
- HTML can use bounded shared caching
- strict hydration JSON under
/_facetheory/data/*should use cache headers coordinated with the HTML that references it - hashed assets should be long-lived and immutable
ISR:
- use FaceTheory’s blocking ISR cache helper semantics
- observe
x-facetheory-isron responses - do not treat ISR HTML as immutable static content
- treat pointer-derived hydration sidecars as part of the ISR HTML generation result, not as independent static assets
- keep ISR hydration sidecar requests on the same tenant/auth/cookie/query variant boundary as the HTML that emitted them
ISR Storage Notes
S3HtmlStore.keyPrefixcontrols the physical object prefixhtmlPointerPrefixcontrols the logical pointer prefix stored in metadata- Do not duplicate the same non-empty prefix in both places unless that layout is intentional
Reference Stacks
These stacks are implementation references for the documented topology rather than separate contract surfaces.
infra/apptheory-ssr-site/for CloudFront plus S3 plus Lambda URL SSRinfra/apptheory-ssg-isr-site/for SSG failover and blocking ISR