diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73fbe0a..76e27fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,6 +78,17 @@ jobs: - run: bun run --filter @stackmap/site test - run: bun run --filter @stackmap/site typecheck - run: bun run --filter @stackmap/site build + - name: Site smoke against the production build + working-directory: site + run: | + bunx playwright install --with-deps chromium + bunx playwright test + - name: Upload site Playwright results on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: site-playwright-results + path: site/test-results/ e2e: name: e2e · visual diff --git a/bun.lock b/bun.lock index e0a12ff..ebcbdfe 100644 --- a/bun.lock +++ b/bun.lock @@ -100,14 +100,17 @@ "name": "@stackmap/site", "version": "0.0.0", "dependencies": { + "@gsap/react": "^2.1.2", "@stackmap/core": "workspace:*", "@stackmap/viewer": "workspace:*", "geist": "^1.7.2", + "gsap": "^3.15.0", "next": "^16.3.7", "react": "^19.3.0", "react-dom": "^19.3.0", }, "devDependencies": { + "@playwright/test": "^1.63.0", "@stackmap/layout": "workspace:*", "@stackmap/schema": "workspace:*", "@tailwindcss/postcss": "^4.3.3", @@ -257,6 +260,8 @@ "@fontsource-variable/geist-mono": ["@fontsource-variable/geist-mono@5.3.0", "", {}, "sha512-vBbuwDEo9AkrqADMXOrlAR3DFcJi4/JxeuU43FoiQERnNwsfXNnvxvReZG02cQKmyk4DZkZdBZX3oTDvy2zBAw=="], + "@gsap/react": ["@gsap/react@2.1.2", "", { "peerDependencies": { "gsap": "^3.12.5", "react": ">=17" } }, "sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw=="], + "@hyamero/stackmap": ["@hyamero/stackmap@workspace:packages/cli"], "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], @@ -793,6 +798,8 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "gsap": ["gsap@3.15.0", "", {}, "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A=="], + "handlebars": ["handlebars@4.7.9", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], diff --git a/site/app/docs/page.tsx b/site/app/docs/page.tsx index 6535dab..0007dbd 100644 --- a/site/app/docs/page.tsx +++ b/site/app/docs/page.tsx @@ -6,7 +6,7 @@ import { Ask, Code, docs } from '@/components/docs/prose'; import { CodeBlock, Command } from '@/components/ui/CodeBlock'; import { TypeChip } from '@/components/ui/TypeChip'; import { spell } from '@/lib/words'; -import { QUICK_START, SOURCES } from '@/lib/diagrams'; +import { SOURCES, stillOf } from '@/lib/diagrams'; import { OPEN_GRAPH } from '@/lib/seo'; import { SITE } from '@/lib/site-data'; @@ -46,7 +46,7 @@ function Step({ n, title, children }: { n: number; title: string; children: Reac return (
  • {n} -

    {title}

    +

    {title}

    {children}
  • ); @@ -129,7 +129,7 @@ export default function DocsPage() { ))} file:///…/.stackmap/bookshop/diagram.html - +
    The same JSON, laid out by stackmap.
    diff --git a/site/app/examples/page.tsx b/site/app/examples/page.tsx index 229fac9..6ce39bc 100644 --- a/site/app/examples/page.tsx +++ b/site/app/examples/page.tsx @@ -22,7 +22,7 @@ const FILTERS: Filter[] = [ const agents = EXAMPLES.filter((e) => e.prompt).length; export default function ExamplesPage() { - const { items, thumbs } = galleryProps(EXAMPLES); + const { items, thumbs, rest } = galleryProps(EXAMPLES); return (
    @@ -31,7 +31,7 @@ export default function ExamplesPage() { {spell(EXAMPLES.length, true)} diagrams laid out by stackmap: {spell(EXAMPLES.length - agents)} across the {spell(DIAGRAM_KINDS.length)} kinds, and{' '} {spell(agents)} that coding agents wrote from a plain request in the skill’s eval runs. Pick one to open it in the viewer.

    - +
    ); diff --git a/site/app/kinds/[kind]/page.tsx b/site/app/kinds/[kind]/page.tsx index fdb1b7f..0b22172 100644 --- a/site/app/kinds/[kind]/page.tsx +++ b/site/app/kinds/[kind]/page.tsx @@ -36,7 +36,7 @@ export default async function KindPage({ params }: PageProps<'/kinds/[kind]'>) { const { kind } = await params; if (!isKind(kind)) notFound(); const page = KIND_PAGES[kind]; - const { items, thumbs } = galleryProps(kindEntries(kind)); + const { items, thumbs, rest } = galleryProps(kindEntries(kind)); const file = `${SKILL_EXAMPLE[kind]}.json`; const next = DIAGRAM_KINDS[(DIAGRAM_KINDS.indexOf(kind) + 1) % DIAGRAM_KINDS.length]!; return ( @@ -53,7 +53,7 @@ export default async function KindPage({ params }: PageProps<'/kinds/[kind]'>) {

    {page.lede}

    {page.use}

    - +
    diff --git a/site/app/page.tsx b/site/app/page.tsx index 1fbdeca..238b1e3 100644 --- a/site/app/page.tsx +++ b/site/app/page.tsx @@ -1,4 +1,6 @@ import type { Metadata } from 'next'; +import { Landing } from '@/components/landing/Landing'; +import { CHECKOUT, DEMO } from '@/lib/diagrams'; import { SITE } from '@/lib/site-data'; import { OPEN_GRAPH, siteUrl, softwareApplication } from '@/lib/seo'; @@ -12,16 +14,9 @@ const jsonLd = JSON.stringify(softwareApplication(siteUrl(), SITE.version)).repl export default function Home() { return ( -
    +