Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
038763f
feat(landing): add apps workspace, astro tsconfig, and tooling ignores
HugoPerard Aug 26, 2026
96ec75e
feat(landing): add Astro 6 app config, Tailwind 4 theme, and fonts
HugoPerard Aug 26, 2026
2ea2133
feat(landing): add layout, static product UI, and app README
HugoPerard Aug 26, 2026
7746c4c
feat(landing): add React island using real getUiState match/exhaustive
HugoPerard Aug 26, 2026
568c897
feat(landing): add English marketing page for ui-state
HugoPerard Aug 26, 2026
f562db3
fix(landing): restore hero product UI cards and nested-ternary sample
HugoPerard Aug 26, 2026
c563669
fix(landing): escape Astro braces in payload example
HugoPerard Aug 26, 2026
275f0e2
fix(landing): use HTML entities for object-literal example
HugoPerard Aug 26, 2026
482d027
fix(landing): escape Astro braces in sample copy; add reduced-motion …
HugoPerard Aug 26, 2026
581e9d7
fix(landing): render default-match sample with HTML entities
HugoPerard Aug 26, 2026
e50ba58
polish(landing): one radius on nested-ternary sample
HugoPerard Aug 26, 2026
4995346
style(landing): restyle marketing page as two-column editorial
HugoPerard Aug 26, 2026
a0edc54
style(landing): unify 8px radius and focus rings
HugoPerard Aug 26, 2026
9f6169a
style(landing): pending skeleton plus reduced-motion spinner
HugoPerard Aug 26, 2026
17fc4e8
Polish landing: drop fake chrome, equal tiles, and dark invert
HugoPerard Aug 26, 2026
3ea1d59
style(landing): install command as primary CTA, POV eyebrow, more sec…
HugoPerard Aug 26, 2026
b653674
Polish landing layout: cream theme-color
HugoPerard Aug 26, 2026
0b5d8d2
Polish StateDemo: skeleton pending, no spinner
HugoPerard Aug 26, 2026
2944aea
Polish landing: drop kicker, add peer React fact
HugoPerard Aug 26, 2026
2bdb989
polish(landing): restore pending/error/default product states on hero…
HugoPerard Aug 26, 2026
c42ad6e
polish(landing): match-plus-exhaustive demo with skeleton pending
HugoPerard Aug 26, 2026
a45ed8a
polish(landing): two-column hero, text GitHub, three-item definition …
HugoPerard Aug 26, 2026
8b0ceaa
fix(landing): sell exhaustive() with the tsc error, not a second matc…
HugoPerard Aug 26, 2026
ff62edc
fix(landing): rust accent on the selected demo control
HugoPerard Aug 26, 2026
d6b738d
fix(landing): install as pre, tsc miss in copy
HugoPerard Aug 26, 2026
0d8dc09
update astro
HugoPerard Aug 26, 2026
82f84f9
feat(landing): without column as nested ternaries
HugoPerard Aug 26, 2026
fe7e3e2
feat(landing): with column plus tsc miss
HugoPerard Aug 26, 2026
4b74f45
feat(landing): presentational header and with/without compare
HugoPerard Aug 26, 2026
78bf494
fix(landing): restore getUiState braces in with sample
HugoPerard Aug 26, 2026
ac167c0
fix(landing): close getUiState sample without a stray space
HugoPerard Aug 26, 2026
e28675b
fix(landing): with sample closes as });
HugoPerard Aug 26, 2026
2eab1f1
fix(landing): without column on paper, no figcaption
HugoPerard Aug 26, 2026
0dbb489
fix(landing): with column is incomplete match plus tsc
HugoPerard Aug 26, 2026
884a28c
feat(landing): status option-wheel demo island
HugoPerard Aug 26, 2026
80011af
fix(landing): slim hero, compare headings, demo copy
HugoPerard Aug 26, 2026
f3a44cb
feat(landing): BearStudio tokens, drop rust and Plex Sans
HugoPerard Aug 26, 2026
f55a149
feat(landing): self-host Roboto Slab and Inter
HugoPerard Aug 26, 2026
830fabd
feat(landing): load Slab and Inter, theme-color brand-900
HugoPerard Aug 26, 2026
7e57019
feat(landing): brand-900 hero, Slab H1 in accent yellow
HugoPerard Aug 26, 2026
b3dc6e9
feat(landing): favicon in brand-900 and accent
HugoPerard Aug 26, 2026
2e0330b
feat(landing): yellow wheel selected with ink text
HugoPerard Aug 26, 2026
ead5207
clean and improve
HugoPerard Aug 26, 2026
f209fc9
update title
HugoPerard Aug 26, 2026
af12801
rework before/after and demo
HugoPerard Aug 27, 2026
0fa8476
tanstack highlighted to show diff
HugoPerard Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ coverage
# Vercel
.vercel

# Astro
.astro

# Build Outputs
.next/
out/
Expand Down
2 changes: 1 addition & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
"typescript/no-unnecessary-type-parameters": "off",
"typescript/no-unsafe-type-assertion": "off"
},
"ignorePatterns": ["**/dist/**", "**/coverage/**"]
"ignorePatterns": ["**/dist/**", "**/coverage/**", "**/.astro/**"]
}
46 changes: 46 additions & 0 deletions apps/landing/PRODUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Product

<!-- impeccable:product-schema 1 -->

## Platform

web

## Users

TypeScript and React engineers drowning in nested loading / error / empty UI.

## Product Purpose

`@bearstudio/ui-state` is an OSS TypeScript helper. `getUiState` plus `match` plus `exhaustive()` map pending, error, and the statuses a screen already has onto one typed chain. Success is a compile error when a status is unmatched — not a new store.

## Positioning

exhaustive() is a type error until every status is matched. Statuses are inferred from set(), not a fixed enum. React is a peer. There is no store.

## Operating Context

Library landing (Persuade).
Engineers arrive from GitHub, read a short example, and wire getUiState to query flags they already have.

## Capabilities and Constraints

- Surface API: getUiState, set(), match, exhaustive(), when().
- Do not demo is() as a type guard; it does not narrow on current main (PR #5).
- MIT. React peer. No store, no context, no extra runtime.
- Do not invent download counts or testimonials.

## Brand Commitments

Voice: specific, technical, no hype. Anti-references: Relume/v0 indigo bento, fake browser chrome, equal feature cards, Unleash. Identity: cream/ink tokens, IBM Plex Sans and Mono.

## Evidence on Hand

No download counts, testimonials, or case studies. Do not fabricate them. Facts: MIT, React peer, no store, exhaustive() fails the type check until every status is matched.

## Product Principles

1. A missed status is a type error, not a blank screen.
2. Statuses come from the app, not a library enum.
3. No new store; wire to flags the screen already has.
4. Marketing copy stays factual; no hype words.
35 changes: 35 additions & 0 deletions apps/landing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# landing

Marketing site for `@bearstudio/ui-state`. Unpublished; no changeset.

## Run

From the repo root (Node 24, pnpm 10.34.5):

```bash
pnpm install
pnpm --filter landing dev
```

Root `pnpm dev` / `pnpm build` / `pnpm check-types` / `pnpm lint` also
include this app via turbo. `dev` depends on `^build` so the library
dist exists before the Astro island imports it.

## Stack

- Astro 6 SSG + one React island (`client:visible`)
- Tailwind 4 via `@tailwindcss/vite` (not `@astrojs/tailwind`)
- Tokens in `@theme inline`
- `@bearstudio/ui-state` as `workspace:*`
- Fonts: Astro 6 Fonts API, Fontsource, latin + latin-ext, self-hosted

## Typecheck split

Library stays NodeNext (`react-library.json`). This app does **not**
extend `react-library.json`. It extends
`@bearstudio/typescript-config/astro.json` (`moduleResolution: Bundler`).

`check-types` is `tsc --noEmit` on `src/**/*.ts(x)` (the island).
`astro check` is not the source of truth on TypeScript 7 (no compiler API).

Lint: oxlint. Format: oxfmt.
39 changes: 39 additions & 0 deletions apps/landing/astro.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import react from "@astrojs/react";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig, fontProviders } from "astro/config";

export default defineConfig({
output: "static",
compressHTML: true,
integrations: [react()],
vite: {
plugins: [tailwindcss()],
},
fonts: [
{
name: "Roboto Slab",
cssVariable: "--font-roboto-slab",
provider: fontProviders.fontsource(),
weights: [700],
styles: ["normal"],
subsets: ["latin", "latin-ext"],
},
{
name: "Inter",
cssVariable: "--font-inter",
provider: fontProviders.fontsource(),
weights: [400, 500, 600],
styles: ["normal"],
subsets: ["latin", "latin-ext"],
},
{
name: "IBM Plex Mono",
cssVariable: "--font-ibm-plex-mono",
provider: fontProviders.fontsource(),
weights: [400, 500],
styles: ["normal"],
subsets: ["latin", "latin-ext"],
fallbacks: ["monospace"],
},
],
});
30 changes: 30 additions & 0 deletions apps/landing/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "landing",
"private": true,
"license": "MIT",
"type": "module",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"check-types": "tsc --noEmit",
"lint": "oxlint .",
"format": "oxfmt"
},
"dependencies": {
"@astrojs/react": "6.0.4",
"@bearstudio/ui-state": "workspace:*",
"@tanstack/highlight": "0.0.10",
"astro": "7.2.7",
"react": "19.2.8",
"react-dom": "19.2.8"
},
"devDependencies": {
"@bearstudio/typescript-config": "workspace:*",
"@tailwindcss/vite": "4.3.3",
"@types/react": "19.2.18",
"@types/react-dom": "19.2.5",
"tailwindcss": "4.3.3",
"typescript": "7.0.2"
}
}
Binary file added apps/landing/public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/landing/public/favicon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/landing/public/favicon.ico
Binary file not shown.
5 changes: 5 additions & 0 deletions apps/landing/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading