Add Formfire design document
Design for structured data input plugin completing the Fire-Suite (Input -> Observe -> Output). Covers data model, architecture, UI concept, and scope for V1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
4f02ba3d37
1 changed files with 182 additions and 0 deletions
182
docs/plans/2026-02-13-formfire-design.md
Normal file
182
docs/plans/2026-02-13-formfire-design.md
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# Formfire Design Document
|
||||
|
||||
**Date**: 2026-02-13
|
||||
**Status**: Approved
|
||||
**Plugin**: obsidian-formfire
|
||||
**Suite**: Fire-Suite (Promptfire = Output, Logfire = Observe, Formfire = Input)
|
||||
|
||||
## Problem
|
||||
|
||||
Obsidian has no native solution for structured data input. Every vault power user reaches a point where they want a form instead of manually typing frontmatter. Existing community solutions (Templater, MetaEdit) solve this only fragmentarily.
|
||||
|
||||
Formfire closes the Input gap in the Fire-Suite triangle: **Input (Formfire) -> Observe (Logfire) -> Output (Promptfire)**.
|
||||
|
||||
## Decisions
|
||||
|
||||
| Aspect | Decision |
|
||||
|--------|----------|
|
||||
| Form Storage | Plugin Settings |
|
||||
| Output Mode | Both: create new note OR update existing frontmatter |
|
||||
| Access | Command Palette + Sidebar View |
|
||||
| Field Types | Text, Textarea, Number, Toggle, Date, Dropdown, Tags, Note-Link, Folder-Picker, Rating |
|
||||
| Body Template | Yes, with `{{variable}}` substitution |
|
||||
| Form Editor | Visual Form Builder in Settings Tab |
|
||||
| Architecture | A+B Hybrid (pragmatic with clean separation) |
|
||||
|
||||
## Data Model
|
||||
|
||||
```typescript
|
||||
interface FormDefinition {
|
||||
id: string; // UUID
|
||||
name: string; // "Meeting-Notiz", "Buchrezension"
|
||||
icon: string; // Obsidian icon name
|
||||
mode: "create" | "update";
|
||||
|
||||
// mode: "create" only
|
||||
targetFolder?: string;
|
||||
fileNameTemplate?: string; // e.g. "{{datum}}-{{titel}}"
|
||||
bodyTemplate?: string; // Markdown with {{variables}}
|
||||
|
||||
// mode: "update" only
|
||||
targetFile?: "active" | "prompt";
|
||||
|
||||
fields: FormField[];
|
||||
}
|
||||
|
||||
interface FormField {
|
||||
id: string; // Unique key (becomes frontmatter property)
|
||||
label: string; // Display name
|
||||
type: FieldType;
|
||||
required: boolean;
|
||||
defaultValue?: any;
|
||||
placeholder?: string;
|
||||
options?: string[]; // For dropdown/tags
|
||||
folder?: string; // For note-link: which folder to search
|
||||
}
|
||||
|
||||
type FieldType =
|
||||
| "text" | "textarea" | "number" | "toggle"
|
||||
| "date" | "dropdown" | "tags"
|
||||
| "note-link" | "folder-picker" | "rating";
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
obsidian-formfire/
|
||||
├── src/
|
||||
│ ├── main.ts // Plugin class, commands, view registration
|
||||
│ ├── types.ts // All interfaces
|
||||
│ ├── core/
|
||||
│ │ ├── form-store.ts // CRUD for FormDefinitions in Settings
|
||||
│ │ └── form-processor.ts // Create note / update frontmatter
|
||||
│ ├── ui/
|
||||
│ │ ├── settings-tab.ts // Settings tab with form builder
|
||||
│ │ ├── form-builder.ts // Visual form builder (add/edit fields)
|
||||
│ │ ├── form-modal.ts // The form modal for filling out
|
||||
│ │ ├── form-sidebar.ts // Sidebar view with form list
|
||||
│ │ └── field-renderers.ts // Renderer per field type
|
||||
│ └── utils/
|
||||
│ ├── template-engine.ts // {{variable}} substitution
|
||||
│ └── validators.ts // Field validation
|
||||
├── styles.css
|
||||
├── manifest.json
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
└── esbuild.config.mjs
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
User opens form (Command/Sidebar)
|
||||
|
|
||||
FormStore loads FormDefinition from Settings
|
||||
|
|
||||
FormModal renders fields via FieldRenderers
|
||||
|
|
||||
User fills out -> Submit
|
||||
|
|
||||
FormProcessor:
|
||||
mode:"create" -> Template Engine -> vault.create()
|
||||
mode:"update" -> processFrontMatter() on active/chosen note
|
||||
```
|
||||
|
||||
## UI Concept
|
||||
|
||||
### A) Settings Tab: Visual Form Builder
|
||||
|
||||
- **Top**: List of all forms (name, mode, field count) with Add/Edit/Delete/Duplicate buttons
|
||||
- **Bottom / Modal**: Form builder opens on edit with:
|
||||
- Name, Icon, Mode selector (create/update)
|
||||
- Field list with reorder (up/down buttons)
|
||||
- Per field: type dropdown, label, key, required toggle, type-specific options
|
||||
- For create mode: target folder, filename template, body template textarea
|
||||
|
||||
### B) Form Modal (for filling out)
|
||||
|
||||
- Title: form name + icon
|
||||
- Fields rendered vertically by type:
|
||||
- `text` -> Obsidian Setting with text input
|
||||
- `textarea` -> Multi-line text field
|
||||
- `number` -> Number input
|
||||
- `toggle` -> Obsidian Toggle component
|
||||
- `date` -> Native HTML date picker
|
||||
- `dropdown` -> Obsidian Dropdown component
|
||||
- `tags` -> Multi-select with autocomplete (from existing vault tags)
|
||||
- `note-link` -> Text input with vault file suggest
|
||||
- `folder-picker` -> Text input with folder suggest
|
||||
- `rating` -> 5 clickable stars
|
||||
- Bottom: Submit button + validation feedback for required fields
|
||||
- For `mode: "update"` + `targetFile: "prompt"`: File picker first, then form (pre-filled with existing frontmatter values)
|
||||
|
||||
### C) Sidebar View
|
||||
|
||||
- Simple list of all forms with icon + name
|
||||
- Click -> opens FormModal
|
||||
- Gear icon -> opens Settings directly
|
||||
|
||||
**Note**: Detailed UI will be designed using the frontend-design skill during implementation.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `formfire:open-form` | Opens picker modal with all forms, then the chosen FormModal |
|
||||
| `formfire:open-form-<name>` | Dynamically registered commands per form (direct access) |
|
||||
| `formfire:open-sidebar` | Open/focus sidebar view |
|
||||
| `formfire:open-settings` | Jump directly to Formfire settings |
|
||||
|
||||
**Ribbon Icon**: Form icon in left sidebar, opens form picker.
|
||||
|
||||
## Template Engine
|
||||
|
||||
Intentionally simple:
|
||||
|
||||
```
|
||||
{{fieldname}} -> Value of the field
|
||||
{{date}} -> Current date (YYYY-MM-DD)
|
||||
{{time}} -> Current time (HH:mm)
|
||||
{{datetime}} -> Date + time
|
||||
```
|
||||
|
||||
Used in:
|
||||
- `fileNameTemplate` (filename for new notes)
|
||||
- `bodyTemplate` (markdown content of new notes)
|
||||
|
||||
## Out of Scope for V1
|
||||
|
||||
- No conditional logic (show field X only if field Y = ...)
|
||||
- No multi-step wizard
|
||||
- No export/import of form definitions
|
||||
- No computed fields
|
||||
- No custom CSS per form
|
||||
- No API for other plugins
|
||||
|
||||
## Technical Conventions (from Fire-Suite)
|
||||
|
||||
- Build: esbuild, ES2022 target
|
||||
- Settings: deep merge pattern (from Logfire)
|
||||
- Plugin lifecycle: standard Obsidian pattern (loadSettings -> register -> start)
|
||||
- Feedback: Obsidian Notice API
|
||||
- File access: vault.create(), processFrontMatter(), metadataCache
|
||||
Loading…
Reference in a new issue