From ac3a240e9bda3b39beeebfabc7961c7136e94bb1 Mon Sep 17 00:00:00 2001 From: Eric Luce <37158449+eluce2@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:28:42 -0600 Subject: [PATCH 1/4] add beads --- .beads/.gitignore | 39 ++++++++++++ .beads/README.md | 81 ++++++++++++++++++++++++ .beads/config.yaml | 62 ++++++++++++++++++ .beads/interactions.jsonl | 0 .beads/issues.jsonl | 0 .beads/metadata.json | 4 ++ .claude/CLAUDE.md | 2 + .cursor/rules/beads.mdc | 38 +++++++++++ .gitattributes | 5 +- .github/workflows/continuous-release.yml | 8 ++- .github/workflows/release.yml | 2 + AGENTS.md | 40 ++++++++++++ 12 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 .beads/.gitignore create mode 100644 .beads/README.md create mode 100644 .beads/config.yaml create mode 100644 .beads/interactions.jsonl create mode 100644 .beads/issues.jsonl create mode 100644 .beads/metadata.json create mode 100644 .cursor/rules/beads.mdc create mode 100644 AGENTS.md diff --git a/.beads/.gitignore b/.beads/.gitignore new file mode 100644 index 00000000..4a7a77df --- /dev/null +++ b/.beads/.gitignore @@ -0,0 +1,39 @@ +# SQLite databases +*.db +*.db?* +*.db-journal +*.db-wal +*.db-shm + +# Daemon runtime files +daemon.lock +daemon.log +daemon.pid +bd.sock +sync-state.json +last-touched + +# Local version tracking (prevents upgrade notification spam after git ops) +.local_version + +# Legacy database files +db.sqlite +bd.db + +# Worktree redirect file (contains relative path to main repo's .beads/) +# Must not be committed as paths would be wrong in other clones +redirect + +# Merge artifacts (temporary files from 3-way merge) +beads.base.jsonl +beads.base.meta.json +beads.left.jsonl +beads.left.meta.json +beads.right.jsonl +beads.right.meta.json + +# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here. +# They would override fork protection in .git/info/exclude, allowing +# contributors to accidentally commit upstream issue databases. +# The JSONL files (issues.jsonl, interactions.jsonl) and config files +# are tracked by git by default since no pattern above ignores them. diff --git a/.beads/README.md b/.beads/README.md new file mode 100644 index 00000000..50f281f0 --- /dev/null +++ b/.beads/README.md @@ -0,0 +1,81 @@ +# Beads - AI-Native Issue Tracking + +Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code. + +## What is Beads? + +Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git. + +**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads) + +## Quick Start + +### Essential Commands + +```bash +# Create new issues +bd create "Add user authentication" + +# View all issues +bd list + +# View issue details +bd show + +# Update issue status +bd update --status in_progress +bd update --status done + +# Sync with git remote +bd sync +``` + +### Working with Issues + +Issues in Beads are: +- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code +- **AI-friendly**: CLI-first design works perfectly with AI coding agents +- **Branch-aware**: Issues can follow your branch workflow +- **Always in sync**: Auto-syncs with your commits + +## Why Beads? + +✨ **AI-Native Design** +- Built specifically for AI-assisted development workflows +- CLI-first interface works seamlessly with AI coding agents +- No context switching to web UIs + +🚀 **Developer Focused** +- Issues live in your repo, right next to your code +- Works offline, syncs when you push +- Fast, lightweight, and stays out of your way + +🔧 **Git Integration** +- Automatic sync with git commits +- Branch-aware issue tracking +- Intelligent JSONL merge resolution + +## Get Started with Beads + +Try Beads in your own projects: + +```bash +# Install Beads +curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash + +# Initialize in your repo +bd init + +# Create your first issue +bd create "Try out Beads" +``` + +## Learn More + +- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs) +- **Quick Start Guide**: Run `bd quickstart` +- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples) + +--- + +*Beads: Issue tracking that moves at the speed of thought* ⚡ diff --git a/.beads/config.yaml b/.beads/config.yaml new file mode 100644 index 00000000..1de3590e --- /dev/null +++ b/.beads/config.yaml @@ -0,0 +1,62 @@ +# Beads Configuration File +# This file configures default behavior for all bd commands in this repository +# All settings can also be set via environment variables (BD_* prefix) +# or overridden with command-line flags + +# Issue prefix for this repository (used by bd init) +# If not set, bd init will auto-detect from directory name +# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc. +# issue-prefix: "" + +# Use no-db mode: load from JSONL, no SQLite, write back after each command +# When true, bd will use .beads/issues.jsonl as the source of truth +# instead of SQLite database +# no-db: false + +# Disable daemon for RPC communication (forces direct database access) +# no-daemon: false + +# Disable auto-flush of database to JSONL after mutations +# no-auto-flush: false + +# Disable auto-import from JSONL when it's newer than database +# no-auto-import: false + +# Enable JSON output by default +# json: false + +# Default actor for audit trails (overridden by BD_ACTOR or --actor) +# actor: "" + +# Path to database (overridden by BEADS_DB or --db) +# db: "" + +# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON) +# auto-start-daemon: true + +# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE) +# flush-debounce: "5s" + +# Git branch for beads commits (bd sync will commit to this branch) +# IMPORTANT: Set this for team projects so all clones use the same sync branch. +# This setting persists across clones (unlike database config which is gitignored). +# Can also use BEADS_SYNC_BRANCH env var for local override. +# If not set, bd sync will require you to run 'bd config set sync.branch '. +sync-branch: "beads-sync" + +# Multi-repo configuration (experimental - bd-307) +# Allows hydrating from multiple repositories and routing writes to the correct JSONL +# repos: +# primary: "." # Primary repo (where this database lives) +# additional: # Additional repos to hydrate from (read-only) +# - ~/beads-planning # Personal planning repo +# - ~/work-planning # Work planning repo + +# Integration settings (access with 'bd config get/set') +# These are stored in the database, not in this file: +# - jira.url +# - jira.project +# - linear.url +# - linear.api-key +# - github.org +# - github.repo \ No newline at end of file diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl new file mode 100644 index 00000000..e69de29b diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl new file mode 100644 index 00000000..e69de29b diff --git a/.beads/metadata.json b/.beads/metadata.json new file mode 100644 index 00000000..c787975e --- /dev/null +++ b/.beads/metadata.json @@ -0,0 +1,4 @@ +{ + "database": "beads.db", + "jsonl_export": "issues.jsonl" +} \ No newline at end of file diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index bc449a57..1316c3a9 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -2,6 +2,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +@AGENTS.md + ## Project Overview ProofKit is a monorepo of TypeScript tools and libraries for building web applications integrated with Claris FileMaker. Documentation: https://proofkit.dev diff --git a/.cursor/rules/beads.mdc b/.cursor/rules/beads.mdc new file mode 100644 index 00000000..4b1e0173 --- /dev/null +++ b/.cursor/rules/beads.mdc @@ -0,0 +1,38 @@ +# Beads Issue Tracking +# Auto-generated by 'bd setup cursor' - do not remove these markers +# BEGIN BEADS INTEGRATION + +This project uses [Beads (bd)](https://github.com/steveyegge/beads) for issue tracking. + +## Core Rules +- Track ALL work in bd (never use markdown TODOs or comment-based task lists) +- Use `bd ready` to find available work +- Use `bd create` to track new issues/tasks/bugs +- Use `bd sync` at end of session to sync with git remote +- Git hooks auto-sync on commit/merge + +## Quick Reference +```bash +bd prime # Load complete workflow context +bd ready # Show issues ready to work (no blockers) +bd list --status=open # List all open issues +bd create --title="..." --type=task # Create new issue +bd update --status=in_progress # Claim work +bd close # Mark complete +bd dep add # Add dependency (issue depends on depends-on) +bd sync # Sync with git remote +``` + +## Workflow +1. Check for ready work: `bd ready` +2. Claim an issue: `bd update --status=in_progress` +3. Do the work +4. Mark complete: `bd close ` +5. Sync: `bd sync` (or let git hooks handle it) + +## Context Loading +Run `bd prime` to get complete workflow documentation in AI-optimized format (~1-2k tokens). + +For detailed docs: see AGENTS.md, QUICKSTART.md, or run `bd --help` + +# END BEADS INTEGRATION diff --git a/.gitattributes b/.gitattributes index 99915e35..17ccdc8f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ # mdx -*.mdx linguist-detectable=false \ No newline at end of file +*.mdx linguist-detectable=false + +# Use bd merge for beads JSONL files +.beads/issues.jsonl merge=beads diff --git a/.github/workflows/continuous-release.yml b/.github/workflows/continuous-release.yml index 53326a3f..3b1e7b9b 100644 --- a/.github/workflows/continuous-release.yml +++ b/.github/workflows/continuous-release.yml @@ -1,5 +1,11 @@ name: Publish Any Commit -on: [push, pull_request] +on: + push: + branches-ignore: + - beads-sync + pull_request: + branches-ignore: + - beads-sync env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6f9d52c..a559f461 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,8 @@ on: push: branches: - main + branches-ignore: + - beads-sync concurrency: ${{ github.workflow }}-${{ github.ref }} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..df7a4af9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,40 @@ +# Agent Instructions + +This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started. + +## Quick Reference + +```bash +bd ready # Find available work +bd show # View issue details +bd update --status in_progress # Claim work +bd close # Complete work +bd sync # Sync with git +``` + +## Landing the Plane (Session Completion) + +**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. + +**MANDATORY WORKFLOW:** + +1. **File issues for remaining work** - Create issues for anything that needs follow-up +2. **Run quality gates** (if code changed) - Tests, linters, builds +3. **Update issue status** - Close finished work, update in-progress items +4. **PUSH TO REMOTE** - This is MANDATORY: + ```bash + git pull --rebase + bd sync + git push + git status # MUST show "up to date with origin" + ``` +5. **Clean up** - Clear stashes, prune remote branches +6. **Verify** - All changes committed AND pushed +7. **Hand off** - Provide context for next session + +**CRITICAL RULES:** +- Work is NOT complete until `git push` succeeds +- NEVER stop before pushing - that leaves work stranded locally +- NEVER say "ready to push when you are" - YOU must push +- If push fails, resolve and retry until it succeeds + From 93cc480e7cffcc5fb1ac6f61c3a1b2bc64584c1e Mon Sep 17 00:00:00 2001 From: Eric Luce <37158449+eluce2@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:34:33 -0600 Subject: [PATCH 2/4] Remove branches-ignore for beads-sync from release workflow configuration --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a559f461..a6f9d52c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,8 +6,6 @@ on: push: branches: - main - branches-ignore: - - beads-sync concurrency: ${{ github.workflow }}-${{ github.ref }} From 0e67691327fbffedf78ecdfef21acace26d03fae Mon Sep 17 00:00:00 2001 From: Eric Luce <37158449+eluce2@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:40:55 -0600 Subject: [PATCH 3/4] update beads --- .beads/issues.jsonl | 1 + .gitignore | 3 +++ AGENTS.md | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index e69de29b..cb17a39e 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -0,0 +1 @@ +{"id":"proofkit-137","title":"Fix CLI scaffold missing component files","description":"## CLI Scaffold Missing Component Files\n\n**Test:** `@proofkit/cli` \u003e `browser-apps.test.ts` \u003e 'should create a project with FileMaker integration in CI mode'\n\n**Reproduced locally:** Yes (after deleting stale `packages/tmp/cli-tests/test-fm-project`)\n\n### Missing 3 components:\n1. `src/components/mode-toggle.tsx` - imported by `slot-header-right.tsx:4`\n2. `src/components/ui/sonner.tsx` - imported by `providers.tsx:4`\n3. `src/components/ui/button.tsx` - imported by `page.tsx:11`\n\n### Root cause:\nCLI scaffolding generates code that imports these shadcn/ui-style components but doesn't include the actual component files in the generated project.\n\n### Why it appeared to pass locally before:\nStale `test-fm-project` dir existed from previous runs. Turbo may have cached 'passed' result based on old inputs. Fresh scaffold exposes the missing files.\n\n### Fix needed:\nEnsure CLI registry/templates include all required UI components that generated code imports. Check:\n- `packages/registry/` for component definitions\n- CLI scaffold logic that copies/generates components\n\n### Additional warnings (non-blocking):\n```\nWarning: Invalid input options - For the \"define\". Invalid key: Expected never but received \"define\".\n```\nThis vitest config warning appears twice but doesn't cause failure.","status":"open","priority":2,"issue_type":"bug","created_at":"2026-01-10T13:34:47.060701-06:00","created_by":"ericluce","updated_at":"2026-01-10T13:40:47.804511-06:00"} diff --git a/.gitignore b/.gitignore index e01afaf6..3f02c647 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ packages/typegen/schema/metadata.xml # Prevent accidentally committing files with absolute paths Users/ + +# bv (beads viewer) local config and caches +.bv/ diff --git a/AGENTS.md b/AGENTS.md index df7a4af9..00f4ec6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,3 +38,66 @@ bd sync # Sync with git - NEVER say "ready to push when you are" - YOU must push - If push fails, resolve and retry until it succeeds + + + +--- + +## Beads Workflow Integration + +This project uses [beads_viewer](https://github.com/Dicklesworthstone/beads_viewer) for issue tracking. Issues are stored in `.beads/` and tracked in git. + +### Essential Commands + +```bash +# View issues (launches TUI - avoid in automated sessions) +bv + +# CLI commands for agents (use these instead) +bd ready # Show issues ready to work (no blockers) +bd list --status=open # All open issues +bd show # Full issue details with dependencies +bd create --title="..." --type=task --priority=2 +bd update --status=in_progress +bd close --reason="Completed" +bd close # Close multiple issues at once +bd sync # Commit and push changes +``` + +### Workflow Pattern + +1. **Start**: Run `bd ready` to find actionable work +2. **Claim**: Use `bd update --status=in_progress` +3. **Work**: Implement the task +4. **Complete**: Use `bd close ` +5. **Sync**: Always run `bd sync` at session end + +### Key Concepts + +- **Dependencies**: Issues can block other issues. `bd ready` shows only unblocked work. +- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (use numbers, not words) +- **Types**: task, bug, feature, epic, question, docs +- **Blocking**: `bd dep add ` to add dependencies + +### Session Protocol + +**Before ending any session, run this checklist:** + +```bash +git status # Check what changed +git add # Stage code changes +bd sync # Commit beads changes +git commit -m "..." # Commit code +bd sync # Commit any new beads changes +git push # Push to remote +``` + +### Best Practices + +- Check `bd ready` at session start to find available work +- Update status as you work (in_progress → closed) +- Create new issues with `bd create` when you discover tasks +- Use descriptive titles and set appropriate priority/type +- Always `bd sync` before ending session + + From 25d44075198b91a1cec344256bd315157e9c3cf8 Mon Sep 17 00:00:00 2001 From: Eric Luce <37158449+eluce2@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:53:06 -0600 Subject: [PATCH 4/4] fix(cli): include shadcn components in template - Add button, sonner, dropdown-menu, mode-toggle directly to template - Remove shadcnInstall() call from init.ts (unreliable in CI) - Add radix-ui, @radix-ui/react-slot, sonner deps to template - Fix test to clean up stale project dir before running Fixes: proofkit-137 Co-Authored-By: Claude Opus 4.5 --- .beads/issues.jsonl | 2 +- packages/cli/src/cli/init.ts | 5 - .../cli/template/nextjs-shadcn/package.json | 3 + .../cli/template/nextjs-shadcn/proofkit.json | 2 +- .../src/components/mode-toggle.tsx | 39 +++ .../src/components/ui/button.tsx | 61 ++++ .../src/components/ui/dropdown-menu.tsx | 267 ++++++++++++++++++ .../src/components/ui/sonner.tsx | 31 ++ packages/cli/tests/browser-apps.test.ts | 23 +- 9 files changed, 417 insertions(+), 16 deletions(-) create mode 100644 packages/cli/template/nextjs-shadcn/src/components/mode-toggle.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/ui/button.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx create mode 100644 packages/cli/template/nextjs-shadcn/src/components/ui/sonner.tsx diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index cb17a39e..bc329be6 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1 +1 @@ -{"id":"proofkit-137","title":"Fix CLI scaffold missing component files","description":"## CLI Scaffold Missing Component Files\n\n**Test:** `@proofkit/cli` \u003e `browser-apps.test.ts` \u003e 'should create a project with FileMaker integration in CI mode'\n\n**Reproduced locally:** Yes (after deleting stale `packages/tmp/cli-tests/test-fm-project`)\n\n### Missing 3 components:\n1. `src/components/mode-toggle.tsx` - imported by `slot-header-right.tsx:4`\n2. `src/components/ui/sonner.tsx` - imported by `providers.tsx:4`\n3. `src/components/ui/button.tsx` - imported by `page.tsx:11`\n\n### Root cause:\nCLI scaffolding generates code that imports these shadcn/ui-style components but doesn't include the actual component files in the generated project.\n\n### Why it appeared to pass locally before:\nStale `test-fm-project` dir existed from previous runs. Turbo may have cached 'passed' result based on old inputs. Fresh scaffold exposes the missing files.\n\n### Fix needed:\nEnsure CLI registry/templates include all required UI components that generated code imports. Check:\n- `packages/registry/` for component definitions\n- CLI scaffold logic that copies/generates components\n\n### Additional warnings (non-blocking):\n```\nWarning: Invalid input options - For the \"define\". Invalid key: Expected never but received \"define\".\n```\nThis vitest config warning appears twice but doesn't cause failure.","status":"open","priority":2,"issue_type":"bug","created_at":"2026-01-10T13:34:47.060701-06:00","created_by":"ericluce","updated_at":"2026-01-10T13:40:47.804511-06:00"} +{"id":"proofkit-137","title":"Fix CLI scaffold missing component files","description":"## CLI Scaffold Missing Component Files\n\n**Test:** `@proofkit/cli` \u003e `browser-apps.test.ts` \u003e 'should create a project with FileMaker integration in CI mode'\n\n**Reproduced locally:** Yes (after deleting stale `packages/tmp/cli-tests/test-fm-project`)\n\n### Missing 3 components:\n1. `src/components/mode-toggle.tsx` - imported by `slot-header-right.tsx:4`\n2. `src/components/ui/sonner.tsx` - imported by `providers.tsx:4`\n3. `src/components/ui/button.tsx` - imported by `page.tsx:11`\n\n### Root cause:\nCLI scaffolding generates code that imports these shadcn/ui-style components but doesn't include the actual component files in the generated project.\n\n### Why it appeared to pass locally before:\nStale `test-fm-project` dir existed from previous runs. Turbo may have cached 'passed' result based on old inputs. Fresh scaffold exposes the missing files.\n\n### Fix needed:\nEnsure CLI registry/templates include all required UI components that generated code imports. Check:\n- `packages/registry/` for component definitions\n- CLI scaffold logic that copies/generates components\n\n### Additional warnings (non-blocking):\n```\nWarning: Invalid input options - For the \"define\". Invalid key: Expected never but received \"define\".\n```\nThis vitest config warning appears twice but doesn't cause failure.","status":"in_progress","priority":2,"issue_type":"bug","created_at":"2026-01-10T13:34:47.060701-06:00","created_by":"ericluce","updated_at":"2026-01-10T13:41:51.749548-06:00"} diff --git a/packages/cli/src/cli/init.ts b/packages/cli/src/cli/init.ts index 372c76ec..ab8c1698 100644 --- a/packages/cli/src/cli/init.ts +++ b/packages/cli/src/cli/init.ts @@ -14,7 +14,6 @@ import { initializeGit } from "~/helpers/git.js"; import { installDependencies } from "~/helpers/installDependencies.js"; import { logNextSteps } from "~/helpers/logNextSteps.js"; import { setImportAlias } from "~/helpers/setImportAlias.js"; -import { getRegistryUrl, shadcnInstall } from "~/helpers/shadcn-cli.js"; import { buildPkgInstallerMap } from "~/installers/index.js"; import { ensureWebViewerAddonInstalled } from "~/installers/proofkit-webviewer.js"; import { initProgramState, state } from "~/state.js"; @@ -273,10 +272,6 @@ export const runInit = async (name?: string, opts?: CliFlags) => { await installDependencies({ projectDir }); - if (state.ui === "shadcn") { - await shadcnInstall([`${getRegistryUrl()}/r/components/mode-toggle`, "sonner", "button"]); - } - await runCodegenCommand(); if (!cliOptions.noGit) { diff --git a/packages/cli/template/nextjs-shadcn/package.json b/packages/cli/template/nextjs-shadcn/package.json index bfc6c12f..a61be86e 100644 --- a/packages/cli/template/nextjs-shadcn/package.json +++ b/packages/cli/template/nextjs-shadcn/package.json @@ -11,14 +11,17 @@ "format": "biome format --write" }, "dependencies": { + "@radix-ui/react-slot": "^1.2.3", "@t3-oss/env-nextjs": "^0.13.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.541.0", "next": "^15.5.8", "next-themes": "^0.4.6", + "radix-ui": "^1.4.2", "react": "19.1.1", "react-dom": "19.1.1", + "sonner": "^2.0.4", "tailwind-merge": "^3.3.1" }, "devDependencies": { diff --git a/packages/cli/template/nextjs-shadcn/proofkit.json b/packages/cli/template/nextjs-shadcn/proofkit.json index 4e4ff5e3..13d3916d 100644 --- a/packages/cli/template/nextjs-shadcn/proofkit.json +++ b/packages/cli/template/nextjs-shadcn/proofkit.json @@ -2,5 +2,5 @@ "ui": "shadcn", "envFile": ".env", "appType": "browser", - "registryTemplates": ["utils/t3-env", "components/mode-toggle"] + "registryTemplates": ["utils/t3-env"] } diff --git a/packages/cli/template/nextjs-shadcn/src/components/mode-toggle.tsx b/packages/cli/template/nextjs-shadcn/src/components/mode-toggle.tsx new file mode 100644 index 00000000..bff50676 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/mode-toggle.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { Moon, Sun } from "lucide-react"; +import { useTheme } from "next-themes"; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; + +export function ModeToggle() { + const { setTheme } = useTheme(); + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ); +} diff --git a/packages/cli/template/nextjs-shadcn/src/components/ui/button.tsx b/packages/cli/template/nextjs-shadcn/src/components/ui/button.tsx new file mode 100644 index 00000000..30f83b65 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/ui/button.tsx @@ -0,0 +1,61 @@ +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; +import type * as React from "react"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +function Button({ + className, + variant, + size, + asChild = false, + ref, + ...props +}: ButtonProps & { ref?: React.Ref }) { + const Comp = asChild ? Slot : "button"; + return ( + + ); +} + +export { Button, buttonVariants }; diff --git a/packages/cli/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx b/packages/cli/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx new file mode 100644 index 00000000..d1c32758 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,267 @@ +"use client"; + +import { Check, ChevronRight, Circle } from "lucide-react"; +import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"; +import type * as React from "react"; + +import { cn } from "@/lib/utils"; + +function DropdownMenu({ + ...props +}: React.ComponentProps) { + return ; +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ); +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuItem({ + className, + inset, + variant, + ...props +}: React.ComponentProps & { + inset?: boolean; + variant?: "destructive"; +}) { + return ( + + ); +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean; +}) { + return ( + + ); +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuShortcut({ + className, + ...props +}: React.HTMLAttributes) { + return ( + + ); +} + +function DropdownMenuSub({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean; +}) { + return ( + svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0 [&_svg:not([role=img]):not([class*=text-])]:opacity-60", + inset && "ps-8", + className + )} + data-slot="dropdown-menu-sub-trigger" + {...props} + > + {children} + + + ); +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +}; diff --git a/packages/cli/template/nextjs-shadcn/src/components/ui/sonner.tsx b/packages/cli/template/nextjs-shadcn/src/components/ui/sonner.tsx new file mode 100644 index 00000000..79926117 --- /dev/null +++ b/packages/cli/template/nextjs-shadcn/src/components/ui/sonner.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { useTheme } from "next-themes"; +import { Toaster as Sonner } from "sonner"; + +type ToasterProps = React.ComponentProps; + +function Toaster({ ...props }: ToasterProps) { + const { theme = "system" } = useTheme(); + + return ( + + ); +} + +export { Toaster }; diff --git a/packages/cli/tests/browser-apps.test.ts b/packages/cli/tests/browser-apps.test.ts index 106c123f..a9a9243a 100644 --- a/packages/cli/tests/browser-apps.test.ts +++ b/packages/cli/tests/browser-apps.test.ts @@ -1,5 +1,5 @@ import { execSync } from "node:child_process"; -import { existsSync, mkdirSync, readFileSync } from "node:fs"; +import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { beforeEach, describe, expect, it } from "vitest"; import { z } from "zod/v4"; @@ -10,6 +10,8 @@ describe("Non-Interactive CLI Tests", () => { // Use root-level tmp directory for test outputs const testDir = join(__dirname, "..", "..", "tmp", "cli-tests"); const cliPath = join(__dirname, "..", "dist", "index.js"); + const projectName = "test-fm-project"; + const projectDir = join(testDir, projectName); // Parse test environment variables const testEnv = z @@ -22,14 +24,19 @@ describe("Non-Interactive CLI Tests", () => { }) .parse(process.env); - beforeEach(() => { - // Ensure the test directory exists - mkdirSync(testDir, { recursive: true }); - }); + beforeEach( + () => { + // Clean up any stale test project from previous runs + if (existsSync(projectDir)) { + rmSync(projectDir, { recursive: true, force: true }); + } + // Ensure the test directory exists + mkdirSync(testDir, { recursive: true }); + }, + 30_000, // 30s timeout for cleanup of large node_modules + ); it("should create a project with FileMaker integration in CI mode", () => { - const projectName = "test-fm-project"; - // Build the command with all necessary flags for non-interactive mode const command = [ `node "${cliPath}" init`, @@ -57,8 +64,6 @@ describe("Non-Interactive CLI Tests", () => { }); }).not.toThrow(); - const projectDir = join(testDir, projectName); - // Verify project structure expect(existsSync(projectDir)).toBe(true); expect(existsSync(join(projectDir, "package.json"))).toBe(true);