diff --git a/.github/workflows/verification.yml b/.github/workflows/verification.yml new file mode 100644 index 0000000..d363dd6 --- /dev/null +++ b/.github/workflows/verification.yml @@ -0,0 +1,53 @@ +name: Workspace verification + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: verify-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 25 + env: + CI: "true" + NEXT_TELEMETRY_DISABLED: "1" + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + with: + persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: "22" + - name: Activate the repository-pinned pnpm + run: corepack enable + - name: Frozen dependency installation + run: pnpm install --frozen-lockfile + - name: Sharing source contract + run: node --test scripts/social-metadata.test.mjs + - name: Lint + run: pnpm lint + - name: Type checks + run: pnpm typecheck + - name: Production build + run: pnpm build + - name: Install Chromium + run: pnpm --dir apps/web exec playwright install --with-deps chromium + - name: Browser and rendered-image verification + run: pnpm test:e2e + - name: Retain synthetic browser evidence + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: ui-browser-evidence-${{ github.sha }} + path: apps/web/test-results/ + if-no-files-found: ignore + retention-days: 14 diff --git a/AGENTS.md b/AGENTS.md index c580f87..fe550c9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,16 +35,20 @@ Run from the repository root: pnpm lint pnpm typecheck pnpm build +pnpm test:e2e +node --test scripts/social-metadata.test.mjs ``` For UI changes, also inspect the component's Preview and Source tabs, Install and Import examples, `/lab`, keyboard behavior, light/dark modes, narrow screens, and RTL. `pnpm format` writes files; avoid unrelated formatting churn. -There is no root unit-test or E2E script at this revision. Do not invent `pnpm test`, report manual inspection as automated coverage, or claim a build proves accessibility. State which checks ran, their results, and any environment limitation. +There is no root unit-test script named `test`; the root does define `test:e2e`. Do not invent `pnpm test`, report manual inspection as automated coverage, or claim a build proves accessibility. The standalone social-metadata check validates source invariants, not a rendered HTTP response. State which checks ran, their results, and any environment limitation. ## Documentation and handoff Keep README.md and CONTRIBUTING.md consistent with the manifests. Keep CLAUDE.md as a pointer to this file rather than a competing policy. Preserve attribution to shadcn/ui, Base UI, TypeSafe-inspired branding, and the OpenCoven layout inspiration; do not imply vendor endorsement. +Read `docs/discovery/README.md` for sharing and screenshot guidance. The generated OG route must use public editorial copy only, never request content, credentials, or live model calls. Preserve existing per-page metadata and do not canonicalize all routes to the homepage. + `repository-metadata.json` records intended GitHub About text/topics only. Applying it requires a separate authorized GitHub settings action; editing the file alone does not publish topics. Do not create release tags, publish packages, change licensing, or change repository visibility unless explicitly requested. diff --git a/README.md b/README.md index 57e0d17..bb41991 100644 --- a/README.md +++ b/README.md @@ -2,96 +2,103 @@ Reusable React components and interactive interface patterns for TypeSafe AI projects, built with shadcn/ui, Base UI, and Tailwind CSS. -**Small parts. Clear interfaces.** An independent community project maintained under `TypeSafeAI`, not an official TypeSafe AI component library or SDK. +**Small parts. Clear interfaces.** This is an independent community project under `TypeSafeAI`, not an official TypeSafe AI component library or SDK. The community organization was created by VC Moderator [@BunsDev](https://github.com/BunsDev). -[Contributing](CONTRIBUTING.md) · [Agent guide](AGENTS.md) · [TypeSafe API documentation](https://docs.typesafe.ai/api) +[Developer guide](docs/discovery/README.md) · [Contributing](CONTRIBUTING.md) · [Agent instructions](AGENTS.md) · [Jev Labs](docs/jev-labs.md) · [Official API documentation](https://docs.typesafe.ai/introduction/quickstart) -## What this repository provides + -A Turborepo + pnpm workspace with a Next.js component browser, source previews, install/import examples, and an interactive Lab. The UI uses the shadcn `base-nova` style, Base UI primitives, Tailwind v4, and RTL-aware components. +## What is here -The site pairs an original optical-glass photographic introduction with an OpenCoven-inspired workspace: a sticky topbar, grouped component rail, per-component Preview/Source and Install/Import tabs, and an “On this page” outline. Its TypeSafe-inspired theme uses pink primary, teal live-state accents, dark mode by default, IBM Plex typography, a dot-grid background, and softly illuminated preview surfaces. +A Turborepo and pnpm workspace with a Next.js component browser, source previews, install/import examples, and an interactive Lab. It uses the shadcn `base-nova` style, Base UI primitives, Tailwind v4, and RTL-aware components. The interface supports light/dark themes and TypeSafe-inspired pink/teal styling. -`@workspace/ui` is a **private workspace package**, not a published npm package. The imports below work inside this monorepo. For another application, deliberately port the components, styles, dependencies, and aliases you need; do not assume `npm install typesafe-ui` or a hosted registry exists. A visual “live” state is not proof of a real Jev API call. +`@workspace/ui` is a **private workspace package**, not a published npm package. Imports work inside this monorepo. For another application, deliberately port the components, styles, dependencies, and aliases you need; do not assume `npm install typesafe-ui` or a hosted registry exists. -## Getting started +The Jev Labs guide describes the upstream catalog examples, workspace scenarios, and interface patterns. Outputs in these previews are local fixtures. A visual live-state indicator is not proof of a Jev API call. -Use the pnpm version pinned in [package.json](package.json), currently `10.33.4`. The root manifest declares Node.js `>=20`; use a Node version supported by the checked-in Next.js dependency as well. Node.js 22+ is a practical development baseline. +## Run locally + +Use the exact pnpm version declared in [package.json](package.json). The manifest declares Node.js `>=20`; use a version supported by the checked-in Next.js dependency as well. Node.js 22+ is a practical development baseline. ```sh git clone https://github.com/TypeSafeAI/typesafe-ui.git cd typesafe-ui -# Install/activate the pnpm version declared in package.json. -# Where Corepack is installed, `corepack enable` enables its package-manager shims. +# Activate the pnpm version declared in package.json. +# Corepack can enable package-manager shims where it is installed. pnpm install --frozen-lockfile pnpm dev ``` -The [Jev Labs guide](docs/jev-labs.md) covers 169 local examples: all 110 upstream catalog examples, 56 workspace scenarios, and three interface patterns. Labs share the library’s sidebar, source inspection, and installation/import workflow. All outputs are explicitly local fixtures. - -Open the address printed by the development server, normally `http://localhost:3000`. The library is at `/`, and interactive scenes are at `/lab`. Press `d` to toggle dark mode and `⌘K` to search components. +Open the address printed by the development server, normally `http://localhost:3000`. The library is at `/` and the interactive scenes are at `/lab`. Press `d` to toggle dark mode and `Cmd+K` to search components. No provider credentials are needed to browse local fixtures. | Command | Purpose | | --- | --- | -| `pnpm dev` | Run the web application through Turborepo. | -| `pnpm build` | Build the workspace. | -| `pnpm lint` | Run workspace lint tasks. | -| `pnpm typecheck` | Run workspace TypeScript checks. | -| `pnpm test:e2e` | Run Playwright browser checks for the catalog, Lab, navigation, themes, and motion. | -| `pnpm format` | Format source files; this writes changes. | +| `pnpm dev` | Run the web application through Turborepo | +| `pnpm build` | Build the workspace | +| `pnpm lint` | Run workspace lint tasks | +| `pnpm typecheck` | Run workspace TypeScript checks | +| `pnpm test:e2e` | Run Playwright browser checks | +| `node --test scripts/social-metadata.test.mjs` | Check sharing-source invariants without installing dependencies | +| `pnpm format` | Format source files; this writes changes | -There is no root unit-test script. `pnpm test:e2e` runs the checked-in Playwright suite (local Google Chrome; bundled Chromium in CI). Browser checks complement visual and keyboard inspection; they do not prove accessibility. +There is no root `pnpm test` script. The E2E suite uses local Google Chrome, or bundled Chromium in CI. Source checks do not prove that a deployed image loads, and browser automation does not establish complete accessibility. -## Layout +## Project map ```text apps/web/ - app/ Next.js routes, layout, fonts, and metadata - components/ Site shell, component cards, demos, and Lab scenes - lib/ Site config, component registry, source loader, and shiki + app/ routes, layout, fonts, and social metadata + components/ shell, component cards, previews, and Lab scenes + lib/ site configuration, registries, source loader, and shiki packages/ - ui/ @workspace/ui: components, hooks, utilities, and styles - eslint-config/ Shared lint configuration - typescript-config/ Shared TypeScript configuration + ui/ @workspace/ui components, hooks, utilities, and styles + eslint-config/ shared lint configuration + typescript-config/ shared TypeScript configuration ``` -## Adding a component +## Add a component or lab -1. Add a component against the web app. The existing shadcn configuration places reusable components in `packages/ui/src/components`. +1. Add a component against the web app; the shadcn configuration places reusable components in `packages/ui/src/components`. ```sh pnpm dlx shadcn@latest add popover -c apps/web ``` - This is a generator operation that can change source and dependencies. Review its diff and the lockfile rather than treating it as a read-only command. + This is a generator operation that can modify source and dependencies. Review its complete diff and lockfile changes; it is not a read-only command. -2. Register the component in `apps/web/lib/registry.ts`: id, title, group, description, exports, and supported states. -3. Add a demo using the same id in `apps/web/components/demos.tsx`. -4. Verify its preview, source, import example, keyboard behavior, themes, narrow layout, and RTL behavior. +2. Register the component in `apps/web/lib/registry.ts` with its ID, group, description, exports, and supported states. +3. Add its demo using the same ID in `apps/web/components/demos.tsx`. +4. Verify preview, displayed source, imports, keyboard behavior, themes, narrow layout, and RTL. -The library reads component source from disk at build time and highlights it with shiki. Keep registry ids, exported paths, source paths, and demos aligned. +For a Jev Lab, follow [the Lab guide](docs/jev-labs.md) and preserve upstream IDs, declared A/B differences, local-fixture labels, and attribution. The library reads component source at build time and highlights it with shiki; keep registry IDs, source paths, exports, and demos aligned. -## Using components +## Use components ```tsx import { Button } from "@workspace/ui/components/button" ``` -Base UI triggers compose through the `render` prop rather than Radix-style `asChild`. A `Button` rendered as a link needs `nativeButton={false}`. Keep provider credentials and application-specific network clients out of reusable client components. +Base UI triggers compose through `render`, rather than Radix-style `asChild`. A Button rendered as a link needs `nativeButton={false}`. Keep provider credentials and application-specific network clients out of reusable client components. + +## Themes and RTL + +Tokens live in `packages/ui/src/styles/globals.css`: light values in `:root` and dark values in `.dark`. TypeSafe-oriented tokens include `--teal`, `--success`, `--warning`, and `--dot`. Fonts are wired through `next/font` in `apps/web/app/layout.tsx` and exposed as `--font-sans` and `--font-mono`. + +Site identity, links, navigation, language, and direction live in `apps/web/lib/site.ts`. The shadcn configuration has `rtl: true`. Set `dir` and `lang` deliberately for a locale, preserve DirectionProvider, and prefer logical CSS properties. -## Theming and RTL +## Sharing and screenshots -Tokens live in `packages/ui/src/styles/globals.css`: light values in `:root`, dark values in `.dark`. TypeSafe-oriented tokens include `--teal`, `--success`, `--warning`, and `--dot`. Fonts are wired through `next/font` in `apps/web/app/layout.tsx` and exposed as `--font-sans` and `--font-mono`. +`apps/web/app/opengraph-image.tsx` renders a public editorial PNG. Twitter metadata uses the same route. Verify the rendered tags and image response after building and deploying; do not claim production publication from a source diff alone. The SVG shown above is editable artwork, not an application screenshot. -Site name, tagline, links, navigation, language, and direction live in `apps/web/lib/site.ts`. The shadcn configuration has `"rtl": true`. Set `dir` to `"rtl"` and `lang` to the intended locale to update the root layout and `DirectionProvider`. Prefer logical CSS properties so components work in both directions. +The [developer guide](docs/discovery/README.md) links publishing and screenshot protocols. Use synthetic local previews, keep fixture labels visible, and record the source revision, viewport, theme, direction, and capture environment. Review media for private data. `repository-metadata.json` documents proposed About text/topics; it does not apply GitHub settings. ## Related community projects | Repository | Role | | --- | --- | -| [typesafe-ai-playground](https://github.com/BunsDev/typesafe-ai-playground) | Interactive Jev experiments and integration demos. | -| [clarity-judge](https://github.com/BunsDev/clarity-judge) | Separate, named writing-quality checks. | -| [typesafe-router](https://github.com/BunsDev/typesafe-router) | Closed-set tool and model routing, separate from execution. | -| [typesafe-ui](https://github.com/TypeSafeAI/typesafe-ui) | Reusable components and interface patterns. | +| [typesafe-playground](https://github.com/TypeSafeAI/typesafe-playground) | Interactive Jev experiments and integration demos | +| [clarity-judge](https://github.com/TypeSafeAI/clarity-judge) | Separate named writing-quality checks | +| [typesafe-router](https://github.com/TypeSafeAI/typesafe-router) | Closed-set selection, separate from authorization and execution | +| [jev-harness](https://github.com/TypeSafeAI/jev-harness) | Proposal-review evidence and synthetic fixtures | -These are separate repositories, not an automatically integrated or officially supported product suite. The proposed GitHub description and discovery topics are recorded in [repository-metadata.json](repository-metadata.json); that file does not change GitHub settings automatically. +These are independent community projects, not an automatically integrated or officially supported suite. Preserve shadcn/ui and Base UI attribution, TypeSafe-inspired branding, the OpenCoven layout inspiration, and existing source/license notices. Review the applicable licenses before reusing code; this change does not alter licensing. diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 84f2eb8..5701bf0 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -39,6 +39,7 @@ export const metadata: Metadata = { }, twitter: { card: "summary_large_image", + images: [{ url: "/opengraph-image", alt: "TypeSafe UI — unofficial community component workspace" }], }, } diff --git a/apps/web/app/opengraph-image.tsx b/apps/web/app/opengraph-image.tsx new file mode 100644 index 0000000..f8d4e8d --- /dev/null +++ b/apps/web/app/opengraph-image.tsx @@ -0,0 +1,28 @@ +import { ImageResponse } from "next/og" +import { site } from "@/lib/site" + +export const alt = "TypeSafe UI — unofficial community component workspace" +export const size = { width: 1200, height: 630 } +export const contentType = "image/png" + +// Public editorial artwork only: no request data, provider calls, or credentials. +export default function Image() { + return new ImageResponse( +