chore: update documentation and add MIT License

Enhance CLAUDE.md with detailed architecture, key modules, and AI configuration. Introduce LICENSE file with MIT License terms. Remove obsolete Header component to streamline the codebase.
This commit is contained in:
Kayshen-X 2026-02-18 22:02:56 +08:00
parent 515801ce26
commit 03c44e51b0
4 changed files with 66 additions and 89 deletions

View file

@ -14,9 +14,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Architecture ## Architecture
OpenPencil is an open-source vector design tool (alternative to Pencil.dev) with a Design-as-Code philosophy. Built as a **TanStack Start** full-stack React application with Bun runtime. OpenPencil is an open-source vector design tool (alternative to Pencil.dev) with a Design-as-Code philosophy. Built as a **TanStack Start** full-stack React application with Bun runtime. Server API powered by **Nitro**.
**Key technologies:** React 19, Fabric.js v7 (canvas engine), Zustand v5 (state management), TanStack Router (file-based routing), Tailwind CSS v4, Vite 7, TypeScript (strict mode). **Key technologies:** React 19, Fabric.js v7 (canvas engine), Zustand v5 (state management), TanStack Router (file-based routing), Tailwind CSS v4, shadcn/ui (UI primitives), Vite 7, Nitro (server), TypeScript (strict mode).
### Data Flow ### Data Flow
@ -43,12 +43,19 @@ React Components (Toolbar, LayerPanel, PropertyPanel)
### Key Modules ### Key Modules
- **`src/canvas/`** — Fabric.js integration: canvas init, drawing events, viewport (pan/zoom), selection sync, bidirectional document↔canvas sync, object factory - **`src/canvas/`** — Fabric.js integration: canvas init, drawing events, viewport (pan/zoom), selection sync, smart guides, bidirectional document↔canvas sync, object factory
- **`src/stores/`** — Zustand stores: `canvas-store` (UI state), `document-store` (PenDocument tree CRUD) - **`src/stores/`** — Zustand stores: `canvas-store` (UI/tool/selection/viewport), `document-store` (PenDocument tree CRUD), `history-store` (undo/redo), `ai-store` (chat/code generation state)
- **`src/types/`** — Type system: `pen.ts` (PenDocument/PenNode), `canvas.ts` (ToolType), `styles.ts` (Fill/Stroke/Effect) - **`src/types/`** — Type system: `pen.ts` (PenDocument/PenNode), `canvas.ts` (ToolType), `styles.ts` (Fill/Stroke/Effect), `variables.ts` (VariableDefinition)
- **`src/components/editor/`** — Editor layout, toolbar, tool buttons - **`src/components/editor/`** — Editor layout, toolbar, tool buttons, status bar
- **`src/components/panels/`** — Layer panel, property panel with section components - **`src/components/panels/`** — Layer panel, property panel (fill/stroke/size/corner-radius/effects/text/appearance sections), AI chat panel, code panel
- **`src/components/shared/`** — Reusable UI: ColorPicker, NumberInput, SliderInput - **`src/components/shared/`** — Reusable UI: ColorPicker, NumberInput, DropdownSelect, ExportDialog, SaveDialog
- **`src/components/ui/`** — shadcn/ui primitives: Button, Select, Separator, Slider, Toggle, Tooltip
- **`src/services/ai/`** — AI chat service, design prompts, design-to-node generation
- **`src/services/codegen/`** — React+Tailwind and HTML+CSS code generators
- **`src/hooks/`** — `use-keyboard-shortcuts` (global keyboard event handling)
- **`src/lib/`** — Utility functions (`utils.ts` with `cn()` for class merging)
- **`src/utils/`** — File operations (save/open .pen), export (PNG/SVG), node clone, pen file normalization, syntax highlight
- **`server/api/ai/`** — Nitro server API: `chat.ts` (streaming chat), `generate.ts` (non-streaming generation). Supports Anthropic API key or Claude Agent SDK (local OAuth) as dual providers
### Fabric.js v7 Gotchas ### Fabric.js v7 Gotchas
@ -70,7 +77,7 @@ File-based routing via TanStack Router. Routes in `src/routes/`, auto-generated
### Styling ### Styling
Tailwind CSS v4 imported via `src/styles.css`. Icons from `lucide-react`. Tailwind CSS v4 imported via `src/styles.css`. UI primitives from shadcn/ui (`src/components/ui/`). Icons from `lucide-react`. shadcn/ui config in `components.json`.
## Code Style ## Code Style
@ -109,3 +116,7 @@ Tailwind CSS v4 imported via `src/styles.css`. Icons from `lucide-react`.
- subject 用英文,小写开头,不加句号,祈使语气(如 `add`、`fix`、`remove`)。 - subject 用英文,小写开头,不加句号,祈使语气(如 `add`、`fix`、`remove`)。
- body 可选,解释 **why** 而非 what可用中英文。 - body 可选,解释 **why** 而非 what可用中英文。
- 一个 commit 只做一件事。不要把不相关的改动混在一起。 - 一个 commit 只做一件事。不要把不相关的改动混在一起。
## License
MIT License. See [LICENSE](./LICENSE) for details.

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 ZSeven—W
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.

View file

@ -14,7 +14,7 @@ Open-source vector design tool with a Design-as-Code philosophy. An alternative
- **File operations**: Save/open .pen files (JSON-based, Git-friendly), auto-save support - **File operations**: Save/open .pen files (JSON-based, Git-friendly), auto-save support
- **Export**: PNG and SVG export with scale options (Cmd+Shift+E) - **Export**: PNG and SVG export with scale options (Cmd+Shift+E)
- **Code generation**: Generate React+Tailwind or HTML+CSS code from designs (Cmd+Shift+C) - **Code generation**: Generate React+Tailwind or HTML+CSS code from designs (Cmd+Shift+C)
- **AI assistant**: Built-in AI chat panel for design assistance (Cmd+J) - **AI assistant**: Built-in AI chat panel for design assistance (Cmd+J), supports Anthropic API or local Claude Code
- **Keyboard shortcuts**: Tool keys (V/R/O/L/T/F/H), Delete, arrow nudge, bracket keys for z-order, Cmd+A select all - **Keyboard shortcuts**: Tool keys (V/R/O/L/T/F/H), Delete, arrow nudge, bracket keys for z-order, Cmd+A select all
## Tech Stack ## Tech Stack
@ -22,8 +22,10 @@ Open-source vector design tool with a Design-as-Code philosophy. An alternative
- **Framework:** [TanStack Start](https://tanstack.com/start) (React 19, SSR, file-based routing) - **Framework:** [TanStack Start](https://tanstack.com/start) (React 19, SSR, file-based routing)
- **Canvas:** [Fabric.js](http://fabricjs.com/) v7 - **Canvas:** [Fabric.js](http://fabricjs.com/) v7
- **State:** [Zustand](https://zustand-demo.pmnd.rs/) v5 - **State:** [Zustand](https://zustand-demo.pmnd.rs/) v5
- **UI:** [shadcn/ui](https://ui.shadcn.com/) (Radix + Tailwind primitives)
- **Styling:** [Tailwind CSS](https://tailwindcss.com/) v4 - **Styling:** [Tailwind CSS](https://tailwindcss.com/) v4
- **Icons:** [Lucide React](https://lucide.dev/) - **Icons:** [Lucide React](https://lucide.dev/)
- **Server:** [Nitro](https://nitro.build/) (API routes)
- **Runtime:** [Bun](https://bun.sh/) - **Runtime:** [Bun](https://bun.sh/)
- **Build:** [Vite](https://vite.dev/) 7 - **Build:** [Vite](https://vite.dev/) 7
@ -36,6 +38,13 @@ bun --bun run dev
Open http://localhost:3000 and click "New Design" to enter the editor. Open http://localhost:3000 and click "New Design" to enter the editor.
### AI Configuration
The AI assistant works in two modes:
- **Anthropic API**: Set `ANTHROPIC_API_KEY` in `.env`
- **Local Claude Code**: No config needed — uses Claude Agent SDK with OAuth login as fallback
## Scripts ## Scripts
| Command | Description | | Command | Description |
@ -49,21 +58,23 @@ Open http://localhost:3000 and click "New Design" to enter the editor.
``` ```
src/ src/
canvas/ # Fabric.js canvas engine, drawing, sync, guides canvas/ # Fabric.js canvas engine, drawing, sync, guides
components/ components/
editor/ # Editor layout, toolbar editor/ # Editor layout, toolbar, status bar
panels/ # Layer panel, property panel, AI chat, code panel panels/ # Layer panel, property panel, AI chat, code panel
shared/ # Reusable UI (ColorPicker, NumberInput, ExportDialog, etc.) shared/ # Reusable UI (ColorPicker, NumberInput, ExportDialog, etc.)
hooks/ # Keyboard shortcuts ui/ # shadcn/ui primitives (Button, Select, Slider, etc.)
hooks/ # Keyboard shortcuts
lib/ # Utility functions (cn class merging)
services/ services/
ai/ # AI chat service, prompts, design generation ai/ # AI chat service, prompts, design generation
codegen/ # React and HTML code generators codegen/ # React+Tailwind and HTML+CSS code generators
stores/ # Zustand stores (canvas, document, history, AI) stores/ # Zustand stores (canvas, document, history, AI)
types/ # PenDocument/PenNode types, style types types/ # PenDocument/PenNode types, style types, variables
utils/ # File operations, export, node clone, syntax highlight utils/ # File operations, export, node clone, syntax highlight
routes/ # TanStack Router pages (/, /editor) routes/ # TanStack Router pages (/, /editor)
server/ server/
api/ # Server-side API endpoints api/ai/ # Nitro API: streaming chat, AI generation
``` ```
## Roadmap ## Roadmap
@ -77,4 +88,4 @@ server/
## License ## License
MIT [MIT](./LICENSE)

View file

@ -1,66 +0,0 @@
import { Link } from '@tanstack/react-router'
import { useState } from 'react'
import { Home, Menu, X } from 'lucide-react'
import { Button } from '@/components/ui/button'
export default function Header() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<header className="p-4 flex items-center bg-card text-foreground border-b border-border">
<Button
variant="ghost"
size="icon"
onClick={() => setIsOpen(true)}
aria-label="Open menu"
>
<Menu size={20} />
</Button>
<h1 className="ml-4 text-xl font-semibold">
<Link to="/">
<img
src="/tanstack-word-logo-white.svg"
alt="TanStack Logo"
className="h-10"
/>
</Link>
</h1>
</header>
<aside
className={`fixed top-0 left-0 h-full w-80 bg-background text-foreground shadow-2xl z-50 transform transition-transform duration-300 ease-in-out flex flex-col ${
isOpen ? 'translate-x-0' : '-translate-x-full'
}`}
>
<div className="flex items-center justify-between p-4 border-b border-border">
<h2 className="text-xl font-bold">Navigation</h2>
<Button
variant="ghost"
size="icon"
onClick={() => setIsOpen(false)}
aria-label="Close menu"
>
<X size={20} />
</Button>
</div>
<nav className="flex-1 p-4 overflow-y-auto">
<Link
to="/"
onClick={() => setIsOpen(false)}
className="flex items-center gap-3 p-3 rounded-lg hover:bg-accent transition-colors mb-2"
activeProps={{
className:
'flex items-center gap-3 p-3 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors mb-2',
}}
>
<Home size={20} />
<span className="font-medium">Home</span>
</Link>
</nav>
</aside>
</>
)
}