From 764a7502a3e9049abbe824adeeefcc68a3802866 Mon Sep 17 00:00:00 2001 From: Offending Commit Date: Fri, 24 Apr 2026 10:51:56 -0500 Subject: [PATCH] docs: add project docs, GitHub DX, fire-tools stamp - CLAUDE.md with commands, structure, key constraints - .claude/rules/ coding standards + workflows - docs/architecture.md with design decisions - .github/ CI workflow, issue templates, PR template - LICENSE (MIT) - .fire-tools.json initialization stamp - README.md rewritten with features, quick start, stack table --- .claude/rules/coding-standards.md | 31 +++++ .claude/rules/workflows.md | 50 ++++++++ .fire-tools.json | 12 ++ .github/ISSUE_TEMPLATE/bug_report.yml | 47 +++++++ .github/ISSUE_TEMPLATE/feature_request.yml | 24 ++++ .github/pull_request_template.md | 21 ++++ .github/workflows/ci.yml | 38 ++++++ CLAUDE.md | 47 +++++++ LICENSE | 21 ++++ README.md | 140 ++++++++++++--------- docs/architecture.md | 44 +++++++ 11 files changed, 417 insertions(+), 58 deletions(-) create mode 100644 .claude/rules/coding-standards.md create mode 100644 .claude/rules/workflows.md create mode 100644 .fire-tools.json create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yml create mode 100644 CLAUDE.md create mode 100644 LICENSE create mode 100644 docs/architecture.md diff --git a/.claude/rules/coding-standards.md b/.claude/rules/coding-standards.md new file mode 100644 index 0000000..13b3c41 --- /dev/null +++ b/.claude/rules/coding-standards.md @@ -0,0 +1,31 @@ +--- +description: Coding conventions — read when writing or reviewing any code file +--- + +# Coding Standards + +## DO +- Use TypeScript strict mode (`"strict": true` in tsconfig) +- Use Zod only at user-input boundaries (settings form) — not for internal types +- Use named constants — never magic numbers or strings +- Keep components focused; co-locate sub-components in the same file if < 80 lines +- Use `type` imports for framer-motion's `Variants` type to avoid widening issues +- Cast TanStack Router `params` as `as never` for cross-route navigation + +## NEVER +- Use `any` — use `unknown` and narrow explicitly +- Inline Honcho base URL — always read from `loadConfig()` in `src/lib/config.ts` +- Use Tailwind color classes for theme-sensitive values — use CSS `var(--*)` instead +- Use `React.FormEvent` (deprecated in TS6) — use `React.SyntheticEvent` +- Add `as const` to framer-motion variant objects — annotate with `const x: Variants = {}` + +## Test Standards +- One assertion per test case +- Test behavior, not implementation +- Run targeted: `pnpm vitest run src/path/to/file.test.ts` +- Never mock internal modules — mock only external API boundaries (openapi-fetch client) + +## API Query Patterns +- All data fetching via TanStack Query hooks in `src/api/queries.ts` +- POST body shapes are fixed per the openapi schema — do not guess field names +- Use `client.current` (getter) to always get fresh config at call time diff --git a/.claude/rules/workflows.md b/.claude/rules/workflows.md new file mode 100644 index 0000000..1774bca --- /dev/null +++ b/.claude/rules/workflows.md @@ -0,0 +1,50 @@ +--- +description: Recurring task patterns — read when fixing issues, adding features, or running tests +--- + +# Workflows + +## Add a Feature + +1. Read `docs/architecture.md` to understand where new code belongs +2. Write the test first (failing) +3. Implement minimum code to pass +4. `pnpm test` — full suite +5. `pnpm lint:fix` — Biome +6. Commit: `feat: ` + +## Fix a Bug + +1. Grep codebase for identifiers mentioned in the bug report +2. Read the 2–3 most relevant files +3. Write a failing test that reproduces the problem +4. Implement the minimal fix +5. `pnpm vitest run ` — verify test passes +6. `pnpm lint:fix` — pass lint +7. Commit: `fix: ` + +## Regenerate API Types + +Run after updating `openapi.json`: + +```bash +pnpm generate:api +# → overwrites src/api/schema.d.ts +# Do not edit schema.d.ts manually +``` + +## Run Targeted Tests + +```bash +pnpm vitest run src/path/to/file.test.ts +pnpm vitest run --testNamePattern="" +pnpm vitest src/path/to/file.test.ts # watch mode +``` + +## Add a New Route + +1. Create `src/routes/.tsx` using TanStack Router flat-route syntax +2. Export `const Route = createFileRoute("/")({ component: Foo })` +3. Vite plugin auto-regenerates `src/routeTree.gen.ts` on save +4. Add nav link to `src/components/layout/Sidebar.tsx` if top-level +5. Cast all `navigate()` / `` params as `as never` diff --git a/.fire-tools.json b/.fire-tools.json new file mode 100644 index 0000000..f7c084b --- /dev/null +++ b/.fire-tools.json @@ -0,0 +1,12 @@ +{ + "fire_tools_version": "0.1.0", + "initialized_at": "2026-04-24T00:00:00Z", + "profile": "other", + "features": ["pnpm", "biome", "vitest", "zod"], + "deviations": [ + "No SQL database (Honcho API handles persistence)", + "No turborepo (single package)", + "No commitlint/husky (small solo project)", + "No semantic-release (not publishing to npm)" + ] +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..d8da7cc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,47 @@ +name: Bug report +description: Something isn't working as expected +labels: [bug] +body: + - type: markdown + attributes: + value: Thanks for taking the time to report a bug! + + - type: input + id: honcho-version + attributes: + label: Honcho version / commit + description: What version of Honcho are you connecting to? + validations: + required: false + + - type: textarea + id: description + attributes: + label: What happened? + description: A clear description of the bug. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What did you expect? + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + placeholder: | + 1. Go to ... + 2. Click ... + 3. See error + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Browser, OS, any relevant console errors. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..0e70da6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,24 @@ +name: Feature request +description: Suggest a new feature or improvement +labels: [enhancement] +body: + - type: textarea + id: problem + attributes: + label: What problem does this solve? + description: Describe the use case or pain point. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: What would you like to see? + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..f4096e8 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ +## Summary + + + +## Type + +- [ ] Bug fix +- [ ] New feature +- [ ] Refactor +- [ ] Docs / chore + +## Test plan + +- [ ] `pnpm lint` passes +- [ ] `pnpm test` passes +- [ ] `pnpm build` succeeds +- [ ] Tested in browser (describe what you verified) + +## Related issues + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b8b34c4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + check: + name: Lint, type-check & test + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - run: pnpm lint + name: Biome lint + + - run: pnpm exec tsc --noEmit -p tsconfig.app.json + name: Type check + + - run: pnpm test + name: Tests + + - run: pnpm build + name: Production build diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ed49eb3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,47 @@ +# honcho-ui + +Frontend UI for self-hosted Honcho instances — browse memories, peers, sessions, conclusions, and chat with memory context. + +## Commands + +| Command | Purpose | +|---------|---------| +| `pnpm dev` | Start Vite dev server (http://localhost:5173) | +| `pnpm build` | Production build to `dist/` | +| `pnpm lint` | Biome lint check | +| `pnpm lint:fix` | Biome lint + auto-fix | +| `pnpm format` | Biome format check | +| `pnpm test` | Run Vitest tests | +| `pnpm generate:api` | Regenerate `src/api/schema.d.ts` from `openapi.json` | + +## Structure + +| Path | Purpose | +|------|---------| +| `src/routes/` | TanStack Router file-based routes (flat-route syntax) | +| `src/components/` | Feature components grouped by domain | +| `src/api/` | openapi-fetch client + TanStack Query hooks | +| `src/lib/` | Config (localStorage) + theme utilities | +| `src/hooks/` | Custom React hooks | +| `.claude/rules/` | Coding conventions (auto-loaded) | +| `docs/` | Architecture and references | + +## Code Style + +Read `.claude/rules/coding-standards.md` when writing or reviewing any code file. + +## Workflows + +Read `.claude/rules/workflows.md` for recurring task patterns. + +## Architecture + +Read `docs/architecture.md` for component overview, data flow, and design decisions. + +## Key Constraints + +- **No hardcoded URLs** — all connection config lives in `localStorage` under `honcho-ui:config` +- **TanStack Router flat-route params** — always cast `params` as `as never` at `navigate()` and `` callsites +- **`framer-motion` Variants typing** — import `type Variants` and annotate objects; never use `as const` on variant objects +- **Auth is optional** — token header only sent when non-empty; `checkConnection()` detects if auth is required +- **CSS variables only** — no Tailwind color utilities for theme-aware colors; use `var(--text-1)` etc. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..83810df --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 offendingcommit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 7dbf7eb..e36a9ad 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,97 @@ -# React + TypeScript + Vite +# Honcho UI -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +A clean, fast frontend for browsing and chatting with a self-hosted [Honcho](https://github.com/plastic-labs/honcho) instance. -Currently, two official plugins are available: +> **Privacy-first**: all connection details (base URL, optional token) are stored locally in your browser — never sent anywhere except directly to your Honcho instance. -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) +--- -## React Compiler +## Features -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). +- **Dashboard** — workspace count and queue status at a glance, auto-refreshes every 10 s +- **Workspaces** — paginated list with per-workspace navigation +- **Peers** — browse peers, view representations, context, and peer cards +- **Sessions** — paginated message history with summaries and context +- **Conclusions** — semantic search across conclusions with observer/subject display +- **Chat** — conversational interface that sends messages through Honcho's chat endpoint with memory context +- **Dark / light mode** — persisted per browser, instant toggle +- **Optional auth** — token field is optional; a connection health check auto-detects whether auth is required -## Expanding the ESLint configuration +## Quick Start -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: +### Prerequisites -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... +- Node.js ≥ 20 +- pnpm ≥ 9 +- A running Honcho instance (local or remote) - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, +### Install & run - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) +```bash +git clone https://github.com/offendingcommit/honcho-ui.git +cd honcho-ui +pnpm install +pnpm dev ``` -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: +Open http://localhost:5173 — you'll be prompted to enter your Honcho URL. -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' +### Connect to your instance -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) +1. Enter the base URL of your Honcho instance (e.g. `http://localhost:8000`) +2. Optionally enter an API token if your instance requires auth +3. Click **Test connection** — the UI will tell you if auth is needed +4. Click **Save** — you're in + +### Build for production + +```bash +pnpm build +# Output in dist/ — serve with any static host ``` + +## Stack + +| Layer | Library | +|-------|---------| +| Framework | React 19 + Vite 8 | +| Routing | TanStack Router v1 (file-based) | +| Data fetching | TanStack Query v5 | +| API client | openapi-fetch (typed from `openapi.json`) | +| Styling | Tailwind CSS v4 + CSS custom properties | +| Animation | framer-motion | +| Icons | lucide-react | +| Lint / format | Biome | +| Tests | Vitest + Testing Library | + +## Development + +```bash +pnpm dev # dev server with HMR +pnpm lint:fix # Biome lint + format +pnpm test # run tests +pnpm generate:api # regenerate src/api/schema.d.ts from openapi.json +``` + +## Regenerating API types + +If your Honcho instance is updated, grab a fresh `openapi.json` and run: + +```bash +curl http://your-honcho-url/openapi.json -o openapi.json +pnpm generate:api +``` + +## Privacy + +- Base URL and token are stored in `localStorage` under `honcho-ui:config` +- Theme preference is stored in `localStorage` under `honcho-ui:theme` +- No telemetry, no analytics, no external requests beyond your configured Honcho instance + +## Contributing + +Issues and PRs welcome. Open an issue first for significant changes. + +## License + +MIT diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..97d4f8d --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,44 @@ +# Architecture: honcho-ui + +## Overview + +Single-page application for browsing and interacting with a self-hosted [Honcho](https://github.com/plastic-labs/honcho) instance. Configurable at runtime — no URLs baked in. + +Stack: React 19, Vite 8, TypeScript 6, TanStack Router v1, TanStack Query v5, Tailwind CSS v4, framer-motion, openapi-fetch. + +## Key Components + +| Component | Location | Responsibility | +|-----------|----------|---------------| +| API client | `src/api/client.ts` | openapi-fetch client, reads config from localStorage at call time | +| Query hooks | `src/api/queries.ts` | All TanStack Query hooks, typed via generated schema | +| Config | `src/lib/config.ts` | localStorage read/write, health check, Zod validation | +| Theme | `src/lib/theme.ts` | Dark/light theme via `data-theme` on `` | +| Root route | `src/routes/__root.tsx` | Auth guard (redirect to /settings), Sidebar layout | +| Sidebar | `src/components/layout/Sidebar.tsx` | Nav with animated active indicator | +| Settings | `src/components/settings/SettingsForm.tsx` | Base URL + optional token, connection test | + +## Data Flow + +1. App boots → `__root.tsx` checks `localStorage` for config +2. No config → redirect to `/settings` +3. User saves URL (+ optional token) → `loadConfig()` returns it on every query +4. `client.current` getter recreates the openapi-fetch client on each call, always picking up latest config +5. TanStack Query caches responses; stale time 30s, retries 1x + +## External Dependencies + +- Honcho REST API — described by `openapi.json` (local copy, regenerate with `pnpm generate:api`) +- No external auth provider — token is optional, detected via health check + +## Design Decisions + + + +**2026-04-24**: Use CSS custom properties instead of Tailwind color tokens — enables instant dark/light switch via `data-theme` attribute without JS class manipulation per element. + +**2026-04-24**: `client.current` getter pattern instead of module-level singleton — config can change at runtime (user updates settings) without requiring page reload. + +**2026-04-24**: TanStack Router flat-route syntax — required by v1 Vite plugin; `params` cast as `as never` at callsites to satisfy the union type constraint without widening the app's own types. + +**2026-04-24**: Token is optional — self-hosted Honcho instances may not require auth; `checkConnection()` probes the API to detect whether a 401 is returned, then surfaces the result in the settings form.