6.2 KiB
6.2 KiB
Frontend Architecture
Overview
Verstak frontend is a Svelte 3 application running inside Wails v2 (Go bridge). The app manages a hierarchical vault of nodes (folders/cases, notes, files, links, actions) with sync capabilities, worklog/journal, and activity tracking.
Technology Stack
- UI Framework: Svelte 3 (plain JS, no TypeScript in components)
- Desktop Bridge: Wails v2 (
window.go.main.App.*) - Bundler: Vite (via Wails)
- Markdown: Custom renderer in
lib/markdown/ - i18n: Custom lightweight system in
lib/i18n/ - Styling: Scoped CSS in Svelte components, dark theme
Directory Structure
frontend/src/
├── App.svelte # Root component (being modularised)
├── TreeNode.svelte # Tree node for sidebar (inline)
├── FileTreeRow.svelte # File row in file tab (inline)
├── wailsjs/go/main/App.js # Auto-generated Wails bindings
├── lib/
│ ├── components/ # Reusable UI components
│ │ └── notes/
│ │ ├── NoteEditorPanel.svelte
│ │ ├── MarkdownEditor.svelte
│ │ ├── MarkdownPreview.svelte
│ │ ├── InternalLinkPicker.svelte
│ │ └── ObjectPickerModal.svelte
│ ├── services/ # API/Data access layer
│ │ ├── wails.js # Base Wails call helper
│ │ ├── notes.js # Notes API
│ │ ├── files.js # Files API
│ │ ├── search.js # Search API
│ │ ├── inbox.js # Inbox API
│ │ ├── trash.js # Trash API
│ │ ├── sync.js # Sync API
│ │ ├── journal.js # Journal/Worklog API
│ │ ├── actions.js # Actions API
│ │ ├── links.js # Links API
│ │ └── activity.js # Activity API
│ ├── state/ # State management (planned)
│ │ ├── navigation.js # Navigation state
│ │ └── uiState.js # UI state
│ ├── markdown/ # Markdown processing
│ │ ├── markdown.ts
│ │ └── internalLinks.ts
│ ├── i18n/ # Internationalisation
│ │ ├── index.js
│ │ └── locales/
│ │ ├── en.js
│ │ └── ru.js
│ ├── util/ # Utilities
│ │ ├── keyboardLayout.ts
│ │ └── markdown.test.js
│ ├── AppHeader.svelte
│ ├── GlobalSearch.svelte
│ ├── FileBreadcrumbs.svelte
│ ├── FileIcon.svelte
│ ├── FilePreviewModal.svelte
│ ├── ConfirmModal.svelte
│ ├── TodayScreen.svelte
│ ├── BrowserEvents.svelte
│ ├── FirstRun.svelte
│ ├── VaultRecovery.svelte
│ ├── SyncStatus.svelte
│ ├── TemplateIcon.svelte
│ ├── CalendarPluginPage.svelte
│ ├── SettingsWindow.svelte
│ ├── SettingsSidebar.svelte
│ ├── SettingsGeneral.svelte
│ ├── SettingsSync.svelte
│ ├── SettingsPlugins.svelte
│ ├── SettingsBrowserBridge.svelte
│ ├── SettingsWorkspace.svelte
│ ├── SettingsTemplates.svelte
│ ├── SettingsFiles.svelte
│ ├── SettingsBackup.svelte
│ ├── SettingsActivity.svelte
│ ├── actionIcons.js
│ └── fileUtils.js
Wails Bridge
All backend calls go through window.go.main.App[method](...).
The wailsCall() helper in lib/services/wails.js provides error handling.
Planned Components (to extract from App.svelte)
Layout
AppShell.svelte— root layout wrapperSidebar.svelte— navigation sidebarMainWorkspace.svelte— main content area
Pages/Tab Content
OverviewTab.svelte— node overview with meta and quick actionsNotesTab.svelte— notes list and creationFilesTab.svelte— file browser with breadcrumbsInboxContent.svelte+InboxFullScreen.svelteLinksTab.svelteActionsTab.svelteWorklogTab.svelteActivityTabContent.svelteTrashContent.svelteJournalScreen.svelteActivityFeedScreen.svelteWelcomeScreen.svelte
Modals
CreateNodeModal.svelteWorklogModal.svelteCreateActionModal.svelteImportModal.svelteRenameModal.svelteAssignInboxModal.svelteEditLinkModal.svelteLinkInsertModal.svelteNoteRenameModal.svelteContextMenu.svelte
Data Flow
- User interacts with UI component
- Component calls a service function (e.g.,
notesApi.createNote(...)) - Service calls
wailsCall('CreateNote', ...) - Wails bridge forwards to Go backend
- Go backend returns result → Wails → service → component updates state
State Management
Currently all state lives in App.svelte as local variables.
Target: extract into lib/state/navigation.js and lib/state/uiState.js.
Files Flow
- Component:
lib/components/files/FilesTab.svelte— self-contained file browser - API services:
lib/services/files.js,lib/services/nodes.js - Events emitted:
on:openNote— when a .md file linked to a note is openedon:refreshParent— after file operations that modify the treeon:error— on operation failureson:rename— requests parent to show rename modalon:confirm— requests parent to show confirm dialog
- Public methods:
resetToNode(nodeId)— reset state when selected node changesfilesHandleKeydown(e)— keyboard handler for files tab
- .md → note editor flow: Handled inside FilesTab via
CheckFileActionWails call. If action is 'note', emitsopenNote. If 'external', opens in system viewer. Otherwise shows built-in preview. - File preview:
FilePreviewModal.svelte(already existed), invoked by FilesTab - Import dialog: Inline in FilesTab template (moved from App.svelte)
Build & Verification
npm run buildinfrontend/directorygo test ./...from project rootbash scripts/build.sh guifor full GUI binary- Manual smoke testing via Wails dev server