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
This commit is contained in:
Offending Commit
2026-04-24 10:51:56 -05:00
parent 8eff34b3c6
commit 764a7502a3
11 changed files with 417 additions and 58 deletions

View File

@@ -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<HTMLFormElement>`
- 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

View File

@@ -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: <description>`
## Fix a Bug
1. Grep codebase for identifiers mentioned in the bug report
2. Read the 23 most relevant files
3. Write a failing test that reproduces the problem
4. Implement the minimal fix
5. `pnpm vitest run <path/to/test.ts>` — verify test passes
6. `pnpm lint:fix` — pass lint
7. Commit: `fix: <description>`
## 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="<substring>"
pnpm vitest src/path/to/file.test.ts # watch mode
```
## Add a New Route
1. Create `src/routes/<flat-route-name>.tsx` using TanStack Router flat-route syntax
2. Export `const Route = createFileRoute("/<path>")({ 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()` / `<Link>` params as `as never`

12
.fire-tools.json Normal file
View File

@@ -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)"
]
}

47
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -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.

View File

@@ -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

21
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,21 @@
## Summary
<!-- What does this PR change and why? -->
## 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
<!-- Closes #N -->

38
.github/workflows/ci.yml vendored Normal file
View File

@@ -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

47
CLAUDE.md Normal file
View File

@@ -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 `<Link>` 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.

21
LICENSE Normal file
View File

@@ -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.

140
README.md
View File

@@ -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 - Node.js ≥ 20
export default defineConfig([ - pnpm ≥ 9
globalIgnores(['dist']), - A running Honcho instance (local or remote)
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this ### Install & run
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs... ```bash
], git clone https://github.com/offendingcommit/honcho-ui.git
languageOptions: { cd honcho-ui
parserOptions: { pnpm install
project: ['./tsconfig.node.json', './tsconfig.app.json'], pnpm dev
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
``` ```
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 ### Connect to your instance
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default defineConfig([ 1. Enter the base URL of your Honcho instance (e.g. `http://localhost:8000`)
globalIgnores(['dist']), 2. Optionally enter an API token if your instance requires auth
{ 3. Click **Test connection** — the UI will tell you if auth is needed
files: ['**/*.{ts,tsx}'], 4. Click **Save** — you're in
extends: [
// Other configs... ### Build for production
// Enable lint rules for React
reactX.configs['recommended-typescript'], ```bash
// Enable lint rules for React DOM pnpm build
reactDom.configs.recommended, # Output in dist/ — serve with any static host
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
``` ```
## 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

44
docs/architecture.md Normal file
View File

@@ -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 `<html>` |
| 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
<!-- Format: **YYYY-MM-DD**: Decision — Rationale -->
**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.