Frontend Architecture
May 12, 2026 · View on GitHub
This directory contains the React / TypeScript frontend for HardwareVisualizer.
The frontend talks to the Rust backend through Tauri commands generated by
tauri-specta.
Directory Layout
src/
├── App.tsx # App shell, settings load, language/theme setup
├── main.tsx # React entry point
├── components/ # Reusable UI, charts, shared app components
│ ├── ui/ # Radix/Tailwind primitives
│ ├── charts/ # Recharts wrappers
│ └── shared/ # App-level shared components
├── features/ # Feature-owned UI, hooks, stores, and types
│ ├── hardware/ # Dashboard, usage graphs, insights
│ ├── settings/ # Settings screen and settings state
│ ├── menu/ # Sidebar navigation
│ ├── tray/ # Tray widget flyout UI
│ └── updater/ # App update UI
├── hooks/ # Cross-feature React hooks
├── lang/ # i18next translation JSON files
├── lib/ # Framework-agnostic helpers and Tauri wrappers
├── rspc/bindings.ts # Generated Tauri command bindings; do not edit
├── store/ # Cross-feature Jotai atoms
└── types/ # Shared frontend-only types
Keep feature-specific code under features/<feature>/ when the code is not
meaningfully reused elsewhere. Put reusable primitives in components/,
cross-feature hooks in hooks/, and pure helpers in lib/.
Backend IPC
- Use generated commands from
src/rspc/bindings.ts. - Do not edit
src/rspc/bindings.tsby hand. - To expose a new backend command, add/register the Rust command in
src-tauri, runnpm run tauri:dev, then consume the regenerated binding. - Command results use the typed
Resultshape fromsrc/types/result.ts; check for errors before readingdata.
Backend error events are emitted as error_event. The frontend listener lives
in src/hooks/useTauriEventListener.ts and displays the error dialog.
State And Persistence
Use the existing boundary when choosing where state lives:
- User-facing application preferences belong in
settings.json. Add typed Rust setter commands insrc-tauri/src/commands/settings.rs, persist through the Rust settings service, regenerate bindings, and updatefeatures/settings/hooks/useSettingsAtom.ts. - UI-local or transient state can use Tauri Store through
src/lib/tauriStore.tsandsrc/hooks/useTauriStore.ts. Examples include ephemeral selections, cached UI choices, or view state that can be reset without losing an explicit user configuration. - Cross-feature frontend state should use Jotai atoms under the owning feature
or
src/store/when it is genuinely shared.
Do not write user-facing preferences directly from the frontend with Tauri Store.
Internationalization
Translations use i18next and react-i18next.
Current language files live in src/lang/:
en.jsonja.jsonru.json
src/lib/i18n.ts imports these files and registers them as i18next resources.
src/types/i18next.d.ts keeps translation resources typed. The Settings
language selector derives its options from registered i18next resources, while
the Rust language service controls the default language fallback for first run.
Add A New Language
New officially supported languages must be registered in both frontend i18next
resources and Rust SUPPORTED_LANGUAGES.
See docs/development/add-language.md
for the full checklist.
Styling And UI
- Tailwind CSS is the styling layer.
- Reuse components from
src/components/ui/before adding new primitives. - Use feature-owned components for screen-specific UI.
- Use
react-i18nextfor display strings instead of hardcoded user-facing text. - Keep chart-specific wrappers in
src/components/charts/unless the chart is tightly owned by one feature.
Testing
Frontend tests are co-located with the code they cover:
- components:
Component.test.tsx - hooks:
useThing.test.ts - pure helpers:
helper.test.ts - feature workflows: under the owning
features/<feature>/tree
Use Vitest and Testing Library patterns already present in the repository. Prefer focused tests around behavior, command result handling, formatting, and state transitions.