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>
182 lines
6.1 KiB
Markdown
182 lines
6.1 KiB
Markdown
# 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
|