{"id":46795421,"url":"https://github.com/theory-cloud/facetheory","last_synced_at":"2026-05-30T23:02:33.023Z","repository":{"id":343365490,"uuid":"1138342916","full_name":"theory-cloud/FaceTheory","owner":"theory-cloud","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-30T14:26:13.000Z","size":2606,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"staging","last_synced_at":"2026-05-30T15:11:38.047Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theory-cloud.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-20T14:53:45.000Z","updated_at":"2026-05-30T14:26:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/theory-cloud/FaceTheory","commit_stats":null,"previous_names":["theory-cloud/facetheory"],"tags_count":57,"template":false,"template_full_name":null,"purl":"pkg:github/theory-cloud/FaceTheory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theory-cloud%2FFaceTheory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theory-cloud%2FFaceTheory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theory-cloud%2FFaceTheory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theory-cloud%2FFaceTheory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theory-cloud","download_url":"https://codeload.github.com/theory-cloud/FaceTheory/tar.gz/refs/heads/staging","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theory-cloud%2FFaceTheory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33712580,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-10T04:05:42.019Z","updated_at":"2026-05-30T23:02:33.017Z","avatar_url":"https://github.com/theory-cloud.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- AI Training: This file is licensed under Apache-2.0. Attribution is appreciated. --\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/svg/icon.svg\" alt=\"Theory Cloud\" width=\"96\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eFaceTheory\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe AWS-first TypeScript client-delivery framework for the Theory Cloud stack.\u003c/strong\u003e\u003cbr\u003e\n  Deterministic SSR, SSG, blocking ISR, and SPA — across React, Vue, and Svelte.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/theory-cloud/FaceTheory/releases\"\u003e\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/v/release/theory-cloud/FaceTheory?color=2EA7FF\u0026label=release\" /\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/badge/license-Apache--2.0-46D397\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://facetheory.theorycloud.ai/\"\u003e\u003cimg alt=\"Docs\" src=\"https://img.shields.io/badge/docs-facetheory.theorycloud.ai-2EA7FF\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/theory-cloud/FaceTheory/actions\"\u003e\u003cimg alt=\"CI\" src=\"https://img.shields.io/badge/CI-passing-46D397\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/theory-cloud/FaceTheory/security/code-scanning\"\u003e\u003cimg alt=\"CodeQL\" src=\"https://img.shields.io/badge/CodeQL-enabled-7A5CFF\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"TypeScript\" src=\"https://img.shields.io/badge/TypeScript-Node%2024-2EA7FF\" /\u003e\n  \u003cimg alt=\"React\" src=\"https://img.shields.io/badge/React-18%2B-2EA7FF\" /\u003e\n  \u003cimg alt=\"Vue\" src=\"https://img.shields.io/badge/Vue-3-7A5CFF\" /\u003e\n  \u003cimg alt=\"Svelte\" src=\"https://img.shields.io/badge/Svelte-5-C9A96B\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://facetheory.theorycloud.ai/getting-started/\"\u003eGet started\u003c/a\u003e ·\n  \u003ca href=\"https://facetheory.theorycloud.ai/api-reference/\"\u003eAPI reference\u003c/a\u003e ·\n  \u003ca href=\"https://facetheory.theorycloud.ai/reference/face-module/\"\u003eFaceModule\u003c/a\u003e ·\n  \u003ca href=\"https://facetheory.theorycloud.ai/reference/render-modes/\"\u003eRender modes\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nFaceTheory is the **client-delivery layer** of the Theory Cloud stack. It renders HTML for end users — server-side, build-time, incrementally, or as a hydrated shell — and it does so with deterministic head and style emission so that server-rendered HTML matches client-hydrated DOM exactly.\n\n```\n            FaceTheory  (you — client delivery)\n                 │\n            AppTheory   (serverless runtime, CDK constructs)\n                 │\n           TableTheory  (data layer, ISR cache schema)\n                 │\n            DynamoDB    (persistence)\n```\n\n## Status\n\nFaceTheory is pre-1.0 and under active development. The runtime covers SSR, SSG, and blocking ISR with adapter support for React, Vue, and Svelte. First production use is underway at [Pay Theory](https://paytheory.com) (checkout page). See [CHANGELOG](CHANGELOG.md) for release history.\n\n## Install v3.4.3 \u003c!-- x-release-please-version --\u003e\n\nInstall the exact GitHub release tarball:\n\n```bash\nexport FACETHEORY_VERSION=3.4.3 # x-release-please-version\nnpm install --save-exact \\\n  \"https://github.com/theory-cloud/FaceTheory/releases/download/v${FACETHEORY_VERSION}/theory-cloud-facetheory-${FACETHEORY_VERSION}.tgz\"\n```\n\nAdd the framework peers that match your adapter surface:\n\n| Adapter | Peer install |\n|---------|--------------|\n| React          | `npm install react react-dom` |\n| React + AntD   | `npm install antd @emotion/react @emotion/cache @emotion/server` |\n| Vue            | `npm install vue @vue/server-renderer` |\n| Svelte         | `npm install svelte@^5.55.7` |\n\nOptional companion packages from pinned GitHub releases:\n\n- AppTheory runtime: `https://github.com/theory-cloud/AppTheory/releases/download/v1.12.1/theory-cloud-apptheory-1.12.1.tgz`\n- AppTheory CDK: `https://github.com/theory-cloud/AppTheory/releases/download/v1.12.1/theory-cloud-apptheory-cdk-1.12.1.tgz`\n- TableTheory runtime: `https://github.com/theory-cloud/TableTheory/releases/download/v1.9.1/theory-cloud-tabletheory-ts-1.9.1.tgz`\n\n## Quickstart\n\nCreate a minimal app:\n\n```ts\nimport { createFaceApp, type FaceModule } from \"@theory-cloud/facetheory\";\n\nconst faces: FaceModule[] = [\n  {\n    route: \"/\",\n    mode: \"ssr\",\n    render: async () =\u003e ({ html: \"\u003ch1\u003eHello FaceTheory\u003c/h1\u003e\" }),\n  },\n];\n\nexport const app = createFaceApp({ faces });\n```\n\nExpose it through Lambda Function URLs directly:\n\n```ts\nimport { createLambdaUrlStreamingHandler } from \"@theory-cloud/facetheory\";\nimport { app } from \"./app\";\n\nexport const handler = createLambdaUrlStreamingHandler({ app });\n```\n\n`createLambdaUrlStreamingHandler()` expects Lambda's `awslambda.streamifyResponse` global at runtime. Outside Lambda, test request handling with `handleLambdaUrlEvent(app, event)` or pass the optional `awslambda` adapter explicitly.\n\nThe `v3.4.3` GitHub release also ships the matching `facetheory-reference-${FACETHEORY_VERSION}.tar.gz` bundle, which contains the canonical docs, runnable examples, and reference deployment stacks for offline use. \u003c!-- x-release-please-version --\u003e\n\n## At a glance\n\n| Render modes | 4 | SSR · SSG · blocking ISR · SPA |\n| ------------ | - | ------------------------------ |\n| Adapters     | 3 | React · Vue · Svelte |\n| Distribution | GitHub Releases | immutable, pinned |\n| Runtime      | Node ≥24 | TypeScript-only |\n| License      | Apache-2.0 | open source |\n\n## Resource Routes And Hydration Sidecars\n\n`createFaceApp({ resources })` registers raw resource routes beside HTML Faces for JSON/text/empty/method-guard responses. Resource routes return `FaceResponse` directly; they do not declare a render mode and FaceTheory does not wrap them in an HTML document. Prefer the helper exports `jsonResourceResponse()`, `textResourceResponse()`, `emptyResourceResponse()`, and `methodNotAllowedResourceResponse()` for common raw responses.\n\nStrict SSR hydration can be framework-owned: configure `createFaceApp({ ssrHydrationSidecars })`, return normal `viteHydrationForEntry()` data from the SSR Face, and FaceTheory writes the exact render-time payload once before emitting a same-origin `/_facetheory/ssr-data/...` link. Route that prefix to the same Lambda/FaceApp handler as the HTML. Static SSG sidecars stay under `/_facetheory/data/*` for S3/CloudFront delivery, and caller-managed `externalHydrationForEntry(...)` sidecars remain available when the host owns the same-origin JSON URL.\n\nBrowser bootstraps should import `loadFaceHydrationData()` from `@theory-cloud/facetheory/client` so inline, SSG, ISR, framework-owned SSR, and caller-managed external hydration all flow through the same same-origin loader. See [Getting Started](https://facetheory.theorycloud.ai/getting-started/) and [SSR hydration sidecars](https://facetheory.theorycloud.ai/features/ssr-hydration-sidecars/).\n\n## OAC Mutating Forms\n\nAppTheorySsrSite deployments keep the Lambda Function URL origin protected with `AWS_IAM` and CloudFront OAC. Native browser forms cannot add the `x-amz-content-sha256` payload hash required for mutating Lambda URL requests, so FaceTheory exposes `startAwsOacFormTransport()` for explicitly marked same-origin URL-encoded forms:\n\n```html\n\u003cform action=\"/control/items/new\" method=\"post\" data-facetheory-oac-form\u003e\n  \u003cinput name=\"name\" required /\u003e\n  \u003cbutton\u003eCreate\u003c/button\u003e\n\u003c/form\u003e\n```\n\nRoute the action path to Lambda/AppTheory, keep OAC enabled, and install the helper from a client bootstrap module. The payload hash is AWS signing plumbing only; app authentication, CSRF, idempotency, and business validation remain application responsibilities. See [OAC mutating forms](https://facetheory.theorycloud.ai/features/oac-forms/).\n\n## ISR Tenant Partition Safety\n\nBlocking ISR is fail-closed when known tenant boundary headers such as `x-tenant-id` or `x-facetheory-tenant` reach FaceTheory without an explicit `tenantKey` or custom `cacheKey`. Tenant-invariant ISR deployments should strip viewer-supplied tenant-like headers at the CloudFront/AppTheory boundary; tenant-varying pages should use SSR or an explicit trusted partition that includes every request-varying dimension that affects the cached HTML.\n\nSee [ISR tenant safety](https://facetheory.theorycloud.ai/features/isr-tenant-safety/) and [Migration Guide](https://facetheory.theorycloud.ai/migration-guide/) for upgrade steps and verification.\n\n## Strict CSP Hydration\n\nRoutes that need a no-inline CSP can set `FaceRenderResult.csp` to disable inline scripts, inline styles, and raw head HTML, emit `buildStrictCspHeader()`, and move hydration data to a same-origin sidecar instead of inline `__FACETHEORY_DATA__`. For SSR, prefer framework-owned `ssrHydrationSidecars`; use `externalHydrationForEntry()` when the host intentionally owns the sidecar URL. See [Strict CSP](https://facetheory.theorycloud.ai/features/strict-csp/).\n\n## Operator Visibility Dashboards\n\nStitch admin includes operator visibility contracts and React, Vue, and Svelte primitives for guarded operator dashboards. Hosts pass AppTheory/Autheory-derived auth state into FaceTheory as caller-supplied `OperatorGuardStatus`; FaceTheory renders that state but does not validate sessions or embed Autheory business logic.\n\nFor auth-varying dashboards, prefer SSR or a deterministic SPA shell. Avoid SSG for live authorized visibility data, and use ISR only when the cache key and tenant partitioning fully separate every request-varying dimension. Empty and placeholder states must use explicit no-data copy instead of production-like partner, tenant, release, or version mock values.\n\nSee [Operator visibility dashboards](https://facetheory.theorycloud.ai/features/operator-visibility/) for the integration boundary.\n\n## Repository Development\n\n```bash\ncd ts\nnpm ci\nnpm run typecheck\nnpm test\n```\n\nHigh-signal examples:\n\n- React streaming: `npm run example:streaming:serve`\n- Vue Vite SSR: `npm run example:vite:vue:build \u0026\u0026 npm run example:vite:vue:serve`\n- Svelte Vite SSR: `npm run example:vite:svelte:build \u0026\u0026 npm run example:vite:svelte:serve`\n- Svelte external library host: `npm run example:vite:svelte:library:build \u0026\u0026 npm run example:vite:svelte:library:serve`\n- Strict CSP Svelte/Vite: `npm run example:vite:svelte:strict-csp:build \u0026\u0026 npm run example:vite:svelte:strict-csp:serve`\n- Operator visibility SSR example: `npm run example:operator-visibility:build \u0026\u0026 npm run example:operator-visibility:serve`\n- SSG: `npm run example:ssg:build \u0026\u0026 npm run example:ssg:serve`\n\nSee [CONTRIBUTING](CONTRIBUTING.md) for the branch flow and commit conventions.\n\n## Repository Layout\n\n- `docs/` — canonical documentation (rendered to GitHub Pages)\n- `ts/` — runtime package, tests, and local examples\n- `infra/` — reference CloudFront and Lambda deployment stacks\n\n## Theory Cloud\n\nFaceTheory builds on [TableTheory](https://github.com/theory-cloud/TableTheory) (data access, ISR cache schema) and [AppTheory](https://github.com/theory-cloud/AppTheory) (serverless runtime, CDK constructs). The single-path philosophy extends to client delivery: one way to render, one way to cache, one way to deploy.\n\n## Documentation\n\nThe full documentation site lives at \u003chttps://facetheory.theorycloud.ai/\u003e:\n\n- [Getting Started](https://facetheory.theorycloud.ai/getting-started/)\n- [API Reference](https://facetheory.theorycloud.ai/api-reference/)\n- [Render modes compared](https://facetheory.theorycloud.ai/reference/render-modes/)\n- [FaceModule API](https://facetheory.theorycloud.ai/reference/face-module/)\n- [Adapters: React, Vue, Svelte](https://facetheory.theorycloud.ai/adapters/react/)\n- [Strict CSP](https://facetheory.theorycloud.ai/features/strict-csp/)\n- [ISR tenant safety](https://facetheory.theorycloud.ai/features/isr-tenant-safety/)\n- [TableTheory integration](https://facetheory.theorycloud.ai/integrations/tabletheory/)\n- [Core Patterns](https://facetheory.theorycloud.ai/core-patterns/)\n- [CDK And AWS Notes](https://facetheory.theorycloud.ai/cdk/)\n- [Changelog](CHANGELOG.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheory-cloud%2Ffacetheory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheory-cloud%2Ffacetheory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheory-cloud%2Ffacetheory/lists"}