chore: add linting/formatting config and improve README

- Add ESLint flat config with TypeScript and React hooks plugins
- Add rustfmt.toml with edition 2021 defaults
- Rewrite README with setup instructions, project structure, and features
- Add lint script to package.json
- Install ESLint dev dependencies

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-05-01 14:10:15 -04:00
parent e74f92e0f5
commit f12047052e
5 changed files with 923 additions and 30 deletions

View File

@@ -1,35 +1,102 @@
# Tauri + React + Typescript
# MosaicIQ
This template should help get you started developing with Tauri, React and Typescript in Vite.
Equity research terminal built with Tauri 2. Local-first, free/open data sources, desktop-native.
## Tech Stack
| Layer | Technology |
|---|---|
| Desktop shell | Tauri 2 |
| Frontend | React 19, TypeScript 5.8, Vite 7, TailwindCSS 4 |
| State | Zustand (client), TanStack Query (server cache) |
| Backend | Rust (edition 2021) |
| Database | SQLite via rusqlite (bundled) |
| Data sources | Yahoo Finance, RSS/Atom, SEC EDGAR |
## Prerequisites
- [Node.js](https://nodejs.org/) 24+ (see `.nvmrc`)
- [bun](https://bun.sh/) — `curl -fsSL https://bun.sh/install | bash`
- [Rust](https://rustup.rs/) — stable toolchain with `cargo`
- Platform-specific Tauri prerequisites: see [Tauri setup guide](https://v2.tauri.app/start/prerequisites/)
## Getting Started
```bash
# Install frontend dependencies
bun install
# Start dev server (Vite + Tauri)
bun run tauri dev
```
The first run compiles the Rust backend (may take a few minutes). Subsequent starts are fast.
## Build
```bash
# Frontend only (TypeScript check + Vite bundle)
bun run build
# Production desktop build
bun run tauri build
```
## Test
```bash
# Frontend tests
bun test
# Backend tests
cd src-tauri && cargo test
# Lint frontend
bun run lint
```
## Project Structure
```
MosaicIQ/
├── src/ # React + TypeScript frontend
│ ├── components/ # UI components
│ ├── hooks/ # React hooks
│ ├── research/ # Research workspace frontend module
│ ├── news/ # News feed frontend module
│ ├── types/ # TypeScript type definitions
│ └── lib/ # Shared utilities
├── src-tauri/ # Rust backend (Tauri 2)
│ └── src/
│ ├── commands/ # Tauri command handlers (thin bridge)
│ ├── agent/ # AI agent integration
│ ├── news/ # News feed ingestion and storage
│ ├── research/ # Research workspaces, notes, models
│ ├── terminal/ # Terminal command parsing
│ ├── portfolio/ # Portfolio and quote data
│ ├── mappings/ # XBRL concept mapping
│ ├── state.rs # Shared app state
│ ├── error.rs # Typed errors
│ └── lib.rs # App entry point
├── package.json
├── vite.config.ts
└── tsconfig.json
```
## Features
- **Terminal interface** — slash-command system with tab completion for stock lookups, news, research
- **News feed** — RSS/Atom aggregation with keyword filtering, local-first caching
- **Research workspaces** — notes, financial models, XBRL concept mappings
- **AI assistant** — integrated AI chat with streaming and tool approval flows
- **Portfolio tracking** — watchlists and quote data via Yahoo Finance
- **SEC EDGAR** — filings, facts, earnings data with XBRL parsing
## Documentation
- [Rig Agent Harness Architecture](./docs/rig-agent-harness.md)
- [Contributing Guide](../CONTRIBUTING.md)
## Local-First News
## Recommended IDE
The news runtime lives in `src-tauri/src/news/` and stores feed state plus articles in a local SQLite database under the app data directory. Reads are local-first: the UI and `/news` terminal command render cached articles immediately, while refreshes update the local cache in the background.
Frontend example:
```ts
import { useNewsFeed } from './src/news';
const { articles, refresh, toggleSaved, markRead } = useNewsFeed({
onlyHighlighted: true,
limit: 20,
});
```
Terminal usage:
```text
/news
/news NVDA
```
`/news` never fetches the network at read time. It filters articles already persisted in the local news database.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
[VS Code](https://code.visualstudio.com/) with [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) extensions.

File diff suppressed because it is too large Load Diff

33
MosaicIQ/eslint.config.js Normal file
View File

@@ -0,0 +1,33 @@
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import { globalIgnores } from "eslint/config";
export default tseslint.config(
[
globalIgnores(["dist", "node_modules"]),
],
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
...tseslint.configs.recommended,
],
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
},
},
);

View File

@@ -8,7 +8,8 @@
"build": "tsc && vite build",
"preview": "vite preview",
"tauri": "tauri",
"test": "bun test"
"test": "bun test",
"lint": "eslint src"
},
"dependencies": {
"@llamaindex/liteparse": "^1.5.3",
@@ -35,11 +36,16 @@
"zustand": "^5.0.12"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@tauri-apps/cli": "^2",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.6.0",
"eslint": "^10.3.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
"typescript": "~5.8.3",
"typescript-eslint": "^8.59.1",
"vite": "^7.0.4"
}
}

View File

@@ -0,0 +1,6 @@
edition = "2021"
max_width = 100
use_small_heuristics = "Max"
fn_single_line = true
imports_granularity = "Crate"
group_imports = "StdExternalCrate"