{"id":47607943,"url":"https://github.com/valencets/valence","last_synced_at":"2026-04-01T19:39:04.030Z","repository":{"id":343747974,"uuid":"1179014655","full_name":"valencets/valence","owner":"valencets","description":"Schema-driven web framework for Node.js and PostgreSQL. One TypeScript config derives database, admin UI, REST + GraphQL APIs, routing, and analytics. No runtime framework on the client. One schema to rule them all.","archived":false,"fork":false,"pushed_at":"2026-03-24T04:45:05.000Z","size":4225,"stargazers_count":7,"open_issues_count":124,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-24T17:49:34.941Z","etag":null,"topics":["cms","postgresql","schema-driven","typescript","web-components","web-framework"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valencets.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"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":null,"dco":null,"cla":null}},"created_at":"2026-03-11T15:46:21.000Z","updated_at":"2026-03-24T14:14:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/valencets/valence","commit_stats":null,"previous_names":["forrestblade/inertia","valencets/valence"],"tags_count":45,"template":false,"template_full_name":null,"purl":"pkg:github/valencets/valence","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valencets%2Fvalence","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valencets%2Fvalence/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valencets%2Fvalence/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valencets%2Fvalence/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valencets","download_url":"https://codeload.github.com/valencets/valence/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valencets%2Fvalence/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cms","postgresql","schema-driven","typescript","web-components","web-framework"],"created_at":"2026-04-01T19:39:00.156Z","updated_at":"2026-04-01T19:39:04.006Z","avatar_url":"https://github.com/valencets.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/logo-dark-animated.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"./assets/logo-light-animated.png\"\u003e\n    \u003cimg alt=\"Valence\" src=\"./assets/logo-light-animated.png\" width=\"280\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003cstrong\u003eSchema-driven full-stack framework for Node.js and PostgreSQL.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@valencets/valence\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@valencets/valence\" alt=\"npm\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://socket.dev/npm/package/@valencets/valence\"\u003e\u003cimg src=\"https://socket.dev/api/badge/npm/package/@valencets/valence\" alt=\"Socket\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/valencets/valence/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/valencets/valence/ci.yml?branch=master\u0026label=CI\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/TypeScript-strict-blue\" alt=\"TypeScript\"\u003e\n\u003c/p\u003e\n\n---\n\n\u003e **Status: Pre-1.0.** Valence is in active development. The API surface is stabilizing but breaking changes may occur. Security hardening and package-by-package audits are ongoing.\n\nDefine collections and fields in one TypeScript config. Valence derives database tables, a server-rendered admin panel, REST and GraphQL APIs, typed routes with loaders and actions, entity codegen, database migrations, and a first-party analytics pipeline from that single schema. No runtime framework on public pages. No vendor scripts. Minimal, audited dependencies.\n\n```typescript\n// valence.config.ts\nimport { defineConfig, collection, field } from '@valencets/valence'\n\nexport default defineConfig({\n  db: {\n    host: process.env.DB_HOST ?? 'localhost',\n    port: Number(process.env.DB_PORT ?? 5432),\n    database: process.env.DB_NAME ?? 'mysite',\n    username: process.env.DB_USER ?? 'postgres',\n    password: process.env.DB_PASSWORD ?? 'postgres',\n    sslmode: process.env.DB_SSLMODE as 'disable' | 'require' | 'verify-ca' | 'verify-full' | undefined,\n    sslrootcert: process.env.DB_SSLROOTCERT\n  },\n  server: { port: Number(process.env.PORT ?? 3000) },\n  collections: [\n    collection({\n      slug: 'posts',\n      labels: { singular: 'Post', plural: 'Posts' },\n      versions: { drafts: true },\n      hooks: {\n        afterChange: [({ doc }) =\u003e console.log('saved', doc.id)]\n      },\n      fields: [\n        field.text({ name: 'title', required: true }),\n        field.slug({ name: 'slug', slugFrom: 'title', unique: true }),\n        field.richtext({ name: 'body' }),\n        field.tabs({\n          tabs: [\n            {\n              label: 'Details',\n              fields: [\n                field.boolean({ name: 'published' }),\n                field.date({ name: 'publishedAt', condition: (data) =\u003e data.published === 'true' })\n              ]\n            },\n            {\n              label: 'SEO',\n              fields: [\n                field.text({ name: 'metaTitle' }),\n                field.textarea({ name: 'metaDescription' })\n              ]\n            }\n          ]\n        })\n      ]\n    }),\n    collection({\n      slug: 'users',\n      auth: true,\n      fields: [\n        field.text({ name: 'name', required: true }),\n        field.select({\n          name: 'role',\n          defaultValue: 'editor',\n          access: { update: ({ user }) =\u003e user.role === 'admin' },\n          options: [\n            { label: 'Admin', value: 'admin' },\n            { label: 'Editor', value: 'editor' }\n          ]\n        })\n      ]\n    })\n  ],\n  routes: [\n    {\n      path: '/blog/:slug',\n      collection: 'posts',\n      type: 'detail',\n      loader: async ({ params, pool }) =\u003e {\n        const post = await pool`SELECT * FROM posts WHERE slug = ${params.slug}`\n        return { data: { post: post[0] } }\n      }\n    },\n    {\n      path: '/contact',\n      method: 'POST',\n      action: async ({ body }) =\u003e {\n        return { redirect: '/thank-you' }\n      }\n    }\n  ],\n  onServer ({ server, pool, cms, registerRoute }) {\n    registerRoute('GET', '/api/health', (_req, res) =\u003e {\n      res.writeHead(200).end('ok')\n    })\n  },\n  admin: { pathPrefix: '/admin', requireAuth: true },\n  graphql: true,\n  telemetry: {\n    enabled: true,\n    endpoint: '/api/telemetry',\n    siteId: 'mysite'\n  }\n})\n```\n\nThat config gives you: `posts` and `users` tables in Postgres, a server-rendered admin panel with form validation and session auth (Argon2id), a REST API at `/api/posts` and `/api/users`, a GraphQL endpoint at `/graphql`, typed routes with loaders and actions, an `onServer` hook for custom routes and WebSocket handlers, a typed `src/` scaffold with entity interfaces and API clients, Zod validators, database migrations, draft versioning with revision history, and a first-party analytics pipeline that tracks user intent without any third-party scripts on your public pages. One schema to rule them all.\n\n## Quick Start\n\n```bash\nnpx @valencets/valence init my-site\ncd my-site\npnpm dev\n```\n\nThe init wizard walks you through database setup, admin user creation, optional seed data, and framework choice (plain HTML templates, Astro, or bring your own). Pass `--yes` to skip prompts and accept defaults.\n\nOpen `http://localhost:3000/admin` to sign in. Open `http://localhost:3000` for the landing page.\n\n## What You Get\n\n### Schema Engine\n\n- **Database tables** derived from your field definitions. UUID primary keys, timestamps, soft deletes.\n- **22 field types.** text, textarea, richtext, number, boolean, select, date, slug, media, relation, group, email, url, password, json, color, multiselect, array, blocks, tabs, row, collapsible.\n- **Layout fields.** Tabs, rows, and collapsible sections for organizing complex admin forms without affecting the database schema.\n- **Conditional fields.** Show or hide fields based on other field values using the `condition` function.\n- **Field access control.** Per-field create, read, and update access control functions that receive the current user context.\n- **Field hooks.** `beforeValidate`, `beforeChange`, `afterChange`, `afterRead` hooks on individual fields.\n- **Globals.** Single-document configs (site settings, navigation, footer) via `global()` with the same field system.\n- **Migrations** generated from schema diffs. Deterministic SQL, idempotent, version-tracked.\n\n### Admin Panel\n\n- **Server-rendered** admin at `/admin`. HTML forms, CSRF protection, session auth with Argon2id.\n- **Rich text editor.** Tiptap-powered (ProseMirror) with heading, list, blockquote, link, code, divider, and code block formatting. Slash command menu for block insertion.\n- **Draft versioning.** Enable `versions: { drafts: true }` on a collection for publish/unpublish workflow with revision history and diff view.\n- **Autosave.** Automatic draft saving with visual indicator via the `\u003cval-autosave\u003e` component.\n- **Live preview.** Split-pane editor with real-time preview iframe via postMessage.\n- **Bulk operations.** Select multiple documents in list view for bulk delete, publish, or unpublish.\n- **Image processing.** Automatic image resizing and optimization via Sharp on media upload.\n\n### API Layer\n\n- **REST API** at `/api/:collection`. CRUD with Zod validation, parameterized queries, `Result\u003cT, E\u003e` error handling.\n- **GraphQL API.** Auto-generated schema from collections with resolvers wired to the Local API. Enable with `graphql: true`.\n- **Local API.** Programmatic access to all CRUD operations with the same validation and hooks as the REST layer.\n- **Full-text search.** PostgreSQL tsvector/tsquery with relevance ranking, configurable per collection.\n\n### Routing\n\n- **Page routing.** `src/pages/` maps to URL paths.\n- **Routes with loaders.** Server-side data loading injected into pages.\n- **Routes with actions.** Form handling that returns redirects or field-level errors.\n- **`onServer` hook.** Access the raw `http.Server`, database pool, CMS instance, and `registerRoute` for custom endpoints or WebSocket upgrade handlers.\n- **View transitions.** Built-in presets for smooth page navigation.\n\n### Frontend\n\n- **23 Web Components.** ARIA-compliant, i18n-ready, telemetry hooks, hydration directives. OKLCH design tokens. Zero dependencies.\n- **Entity codegen.** Typed interfaces and API clients generated from your schema. `// @generated` files regenerate on config change; user-edited files are never overwritten.\n- **Static file serving.** `public/` served with MIME types and path traversal protection.\n\n### Security\n\n- Argon2id password hashing for admin authentication.\n- CSRF protection on admin forms (double-submit cookie with `crypto.randomBytes`).\n- Session auth with `httpOnly`, `Secure`, `SameSite=Strict` cookie flags.\n- Path traversal protection on static file serving, media uploads, and cloud storage.\n- URL redirect validation to prevent open redirect attacks.\n- Parameterized SQL everywhere. No string concatenation in queries.\n- CodeQL and Socket auditing in CI.\n\n### Telemetry\n\nFirst-party analytics that runs entirely in your Postgres. No Google Analytics, no Plausible, no third-party scripts on your public pages. Your data stays in your database.\n\nAnnotate HTML elements with `data-telemetry-*` attributes. The client library captures events in a pre-allocated ring buffer (zero allocation in the hot path) and auto-flushes via `navigator.sendBeacon()`. The server ingests payloads, stores raw events, and aggregates into daily summaries.\n\n11 intent types: CLICK, SCROLL, VIEWPORT_INTERSECT, FORM_INPUT, INTENT_NAVIGATE, INTENT_CALL, INTENT_BOOK, INTENT_LEAD, LEAD_PHONE, LEAD_EMAIL, LEAD_FORM.\n\n### Plugins\n\n- `@valencets/plugin-seo` — auto-title, meta field injection.\n- `@valencets/plugin-nested-docs` — tree structures with breadcrumb computation.\n- `@valencets/plugin-cloud-storage` — S3-compatible object storage adapter.\n\nPlugins are config transformers: a function that receives a `CmsConfig` and returns a modified `CmsConfig`.\n\n## Packages\n\n| Package | What it does | External deps |\n|---------|-------------|---------------|\n| `@valencets/ui` | 23 Web Components. ARIA, i18n, telemetry hooks, hydration directives. OKLCH tokens. | none |\n| `@valencets/core` | Router + server. pushState nav, fragment swaps, prefetch, view transitions, server islands. | @valencets/resultkit |\n| `@valencets/db` | PostgreSQL query layer. Tagged template SQL, validated config, explicit SSL modes, Result-based error mapping, migration runner. | postgres, @valencets/resultkit, zod |\n| `@valencets/cms` | Schema engine. `collection()` + `field.*` produces tables, validators, REST API, admin UI, auth, media. Rich text via Tiptap. | tiptap, argon2, sharp, zod, @valencets/resultkit |\n| `@valencets/graphql` | Auto-generated GraphQL schema + resolvers from CMS collections. | graphql, @valencets/resultkit |\n| `@valencets/telemetry` | Beacon ingestion, event storage, daily summaries, consent-aware aggregation, retention cleanup. | postgres, @valencets/resultkit |\n| `@valencets/reactive` | Zero-dependency signals package used by newer admin/login flows and available for app/runtime usage. | none |\n| `@valencets/valence` | CLI + FSD scaffold + entity codegen + route types. | tsx, zod, @valencets/resultkit |\n\nCore external runtime deps: 8. All MIT-licensed, all audited via Socket. Public-facing pages ship zero third-party JavaScript.\n\n## Constraints\n\n| Rule | Why |\n|------|-----|\n| Complexity \u003c 20 | Every function fits on one screen. |\n| `Result\u003cT, E\u003e` everywhere | If it can fail, the type says so. Both branches handled. |\n| 14kB critical shell | First paint in the first TCP round trip. |\n| Pre-allocated ring buffer | Zero allocation in the telemetry hot path. |\n| Zero third-party JS on public pages | Your site ships your code. Tiptap is admin-only. |\n| 3k+ tests | Strict TypeScript, neostandard, API review, contract checks, and CI on every push. |\n\n## Current Status\n\nValence is pre-1.0 and in active development. The schema engine, admin panel, REST API, GraphQL layer, telemetry pipeline, CLI, and Web Components are functional and tested. Recent work has focused on DB package hardening, stricter config/scaffold alignment, and tighter local-to-CI parity. Security hardening and API surface cleanup are still ongoing.\n\nSee the [Architecture](ARCHITECTURE.md) doc for a detailed overview of the framework design.\n\n## Documentation\n\n- [Getting Started](GETTING-STARTED.md)\n- [Architecture](ARCHITECTURE.md)\n- [CMS Guide](CMS-GUIDE.md)\n- [Developer Guide](DEVELOPER-GUIDE.md)\n- [Troubleshooting](TROUBLESHOOTING.md)\n\n## Contributing\n\n```bash\ngit clone https://github.com/valencets/valence.git\ncd valence\npnpm install\npnpm build\npnpm test\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for standards and the TDD workflow.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalencets%2Fvalence","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalencets%2Fvalence","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalencets%2Fvalence/lists"}