* Add contributing section for jan * Update CONTRIBUTING.md Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
parent
a6e5273c7a
commit
b0eec07a01
262
CONTRIBUTING.md
262
CONTRIBUTING.md
@ -1,32 +1,266 @@
|
||||
# Contributing to jan
|
||||
# Contributing to Jan
|
||||
|
||||
First off, thank you for considering contributing to jan. It's people like you that make jan such an amazing project.
|
||||
First off, thank you for considering contributing to Jan. It's people like you that make Jan such an amazing project.
|
||||
|
||||
Jan is an AI assistant that can run 100% offline on your device. Think ChatGPT, but private, local, and under your complete control. If you're thinking about contributing, you're already awesome - let's make AI accessible to everyone, one commit at a time.
|
||||
|
||||
## Quick Links to Component Guides
|
||||
|
||||
- **[Web App](./web-app/CONTRIBUTING.md)** - React UI and logic
|
||||
- **[Core SDK](./core/CONTRIBUTING.md)** - TypeScript SDK and extension system
|
||||
- **[Extensions](./extensions/CONTRIBUTING.md)** - Supportive modules for the frontend
|
||||
- **[Tauri Backend](./src-tauri/CONTRIBUTING.md)** - Rust native integration
|
||||
- **[Tauri Plugins](./src-tauri/plugins/CONTRIBUTING.md)** - Hardware and system plugins
|
||||
|
||||
## How Jan Actually Works
|
||||
|
||||
Jan is a desktop app that runs local AI models. Here's how the components actually connect:
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Web App (Frontend) │
|
||||
│ (web-app/) │
|
||||
│ • React UI │
|
||||
│ • Chat Interface │
|
||||
│ • Settings Pages │
|
||||
│ • Model Hub │
|
||||
└────────────┬─────────────────────────────┬───────────────┘
|
||||
│ │
|
||||
│ imports │ imports
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────┐
|
||||
│ Core SDK │ │ Extensions │
|
||||
│ (core/) │ │ (extensions/) │
|
||||
│ │ │ │
|
||||
│ • TypeScript APIs │◄─────│ • Assistant Mgmt │
|
||||
│ • Extension System │ uses │ • Conversations │
|
||||
│ • Event Bus │ │ • Downloads │
|
||||
│ • Type Definitions │ │ • LlamaCPP │
|
||||
└──────────┬───────────┘ └───────────┬──────────┘
|
||||
│ │
|
||||
│ ┌──────────────────────┐ │
|
||||
│ │ Web App │ │
|
||||
│ └──────────┬───────────┘ │
|
||||
│ │ │
|
||||
└──────────────┼───────────────┘
|
||||
│
|
||||
▼
|
||||
Tauri IPC
|
||||
(invoke commands)
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ Tauri Backend (Rust) │
|
||||
│ (src-tauri/) │
|
||||
│ │
|
||||
│ • Window Management • File System Access │
|
||||
│ • Process Control • System Integration │
|
||||
│ • IPC Command Handler • Security & Permissions │
|
||||
└───────────────────────────┬───────────────────────────────┘
|
||||
│
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ Tauri Plugins (Rust) │
|
||||
│ (src-tauri/plugins/) │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ Hardware Plugin │ │ LlamaCPP Plugin │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ • CPU/GPU Info │ │ • Process Mgmt │ │
|
||||
│ │ • Memory Stats │ │ • Model Loading │ │
|
||||
│ │ • System Info │ │ • Inference │ │
|
||||
│ └──────────────────┘ └──────────────────┘ │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### The Communication Flow
|
||||
|
||||
1. **JavaScript Layer Relationships**:
|
||||
- Web App imports Core SDK and Extensions as JavaScript modules
|
||||
- Extensions use Core SDK for shared functionality
|
||||
- All run in the browser/webview context
|
||||
|
||||
2. **All Three → Backend**: Through Tauri IPC
|
||||
- **Web App** → Backend: `await invoke('app_command', data)`
|
||||
- **Core SDK** → Backend: `await invoke('core_command', data)`
|
||||
- **Extensions** → Backend: `await invoke('ext_command', data)`
|
||||
- Each component can independently call backend commands
|
||||
|
||||
3. **Backend → Plugins**: Native Rust integration
|
||||
- Backend loads plugins as Rust libraries
|
||||
- Direct function calls, no IPC overhead
|
||||
|
||||
4. **Response Flow**:
|
||||
- Plugin → Backend → IPC → Requester (Web App/Core/Extension) → UI updates
|
||||
|
||||
### Real-World Example: Loading a Model
|
||||
|
||||
Here's what actually happens when you click "Download Llama 3":
|
||||
|
||||
1. **Web App** (`web-app/`) - User clicks download button
|
||||
2. **Extension** (`extensions/download-extension`) - Handles the download logic
|
||||
3. **Tauri Backend** (`src-tauri/`) - Actually downloads the file to disk
|
||||
4. **Extension** (`extensions/llamacpp-extension`) - Prepares model for loading
|
||||
5. **Tauri Plugin** (`src-tauri/plugins/llamacpp`) - Starts llama.cpp process
|
||||
6. **Hardware Plugin** (`src-tauri/plugins/hardware`) - Detects GPU, optimizes settings
|
||||
7. **Model ready!** - User can start chatting
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
jan/
|
||||
├── web-app/ # React frontend (what users see)
|
||||
├── src-tauri/ # Rust backend (system integration)
|
||||
│ ├── src/core/ # Core Tauri commands
|
||||
│ └── plugins/ # Tauri plugins (hardware, llamacpp)
|
||||
├── core/ # TypeScript SDK (API layer)
|
||||
├── extensions/ # JavaScript extensions
|
||||
│ ├── assistant-extension/
|
||||
│ ├── conversational-extension/
|
||||
│ ├── download-extension/
|
||||
│ └── llamacpp-extension/
|
||||
├── docs/ # Documentation website
|
||||
├── website/ # Marketing website
|
||||
├── autoqa/ # Automated testing
|
||||
├── scripts/ # Build utilities
|
||||
│
|
||||
├── package.json # Root workspace configuration
|
||||
├── Makefile # Build automation commands
|
||||
├── mise.toml # Mise tool configuration
|
||||
├── LICENSE # Apache 2.0 license
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
### The Scenic Route (Build from Source)
|
||||
|
||||
**Prerequisites:**
|
||||
- Node.js ≥ 20.0.0
|
||||
- Yarn ≥ 1.22.0
|
||||
- Rust (for Tauri)
|
||||
- Make ≥ 3.81
|
||||
|
||||
**Option 1: The Easy Way (Make)**
|
||||
```bash
|
||||
git clone https://github.com/menloresearch/jan
|
||||
cd jan
|
||||
make dev
|
||||
```
|
||||
|
||||
**Option 2: The Easier Way (Mise)**
|
||||
```bash
|
||||
git clone https://github.com/menloresearch/jan
|
||||
cd jan
|
||||
|
||||
# Install mise
|
||||
curl https://mise.run | sh
|
||||
|
||||
# Let mise handle everything
|
||||
mise install # installs Node.js, Rust, and other tools
|
||||
mise dev # runs the full development setup
|
||||
```
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
- **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/menloresearch/jan/issues).
|
||||
- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/menloresearch/jan/issues/new).
|
||||
- **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/menloresearch/jan/issues)
|
||||
- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/menloresearch/jan/issues/new)
|
||||
- Include your system specs and error logs - it helps a ton
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
- Open a new issue with a clear title and description.
|
||||
- Open a new issue with a clear title and description
|
||||
- Explain why this enhancement would be useful
|
||||
- Include mockups or examples if you can
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
- Fork the repo.
|
||||
- Create a new branch (`git checkout -b feature-name`).
|
||||
- Commit your changes (`git commit -am 'Add some feature'`).
|
||||
- Push to the branch (`git push origin feature-name`).
|
||||
- Open a new Pull Request.
|
||||
**Choose Your Adventure:**
|
||||
- **Frontend UI and logic** → `web-app/`
|
||||
- **Shared API declarations** → `core/`
|
||||
- **Backend system integration** → `src-tauri/`
|
||||
- **Business logic features** → `extensions/`
|
||||
- **Dedicated backend handler** → `src-tauri/plugins/`
|
||||
|
||||
## Styleguides
|
||||
**The Process:**
|
||||
1. Fork the repo
|
||||
2. Create a new branch (`git checkout -b feature-name`)
|
||||
3. Make your changes (and write tests!)
|
||||
4. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
5. Push to the branch (`git push origin feature-name`)
|
||||
6. Open a new Pull Request against `dev` branch
|
||||
|
||||
### Git Commit Messages
|
||||
## Testing
|
||||
|
||||
- Use the present tense ("Add feature" not "Added feature").
|
||||
```bash
|
||||
yarn test # All tests
|
||||
cd src-tauri && cargo test # Rust tests
|
||||
cd autoqa && python main.py # End-to-end tests
|
||||
```
|
||||
|
||||
## Code Standards
|
||||
|
||||
### TypeScript/JavaScript
|
||||
- TypeScript required (we're not animals)
|
||||
- ESLint + Prettier
|
||||
- Functional React components
|
||||
- Proper typing (no `any` - seriously!)
|
||||
|
||||
### Rust
|
||||
- `cargo fmt` + `cargo clippy`
|
||||
- `Result<T, E>` for error handling
|
||||
- Document public APIs
|
||||
|
||||
## Git Conventions
|
||||
|
||||
### Branches
|
||||
- `main` - stable releases
|
||||
- `dev` - development (target this for PRs)
|
||||
- `feature/*` - new features
|
||||
- `fix/*` - bug fixes
|
||||
|
||||
### Commit Messages
|
||||
- Use the present tense ("Add feature" not "Added feature")
|
||||
- Be descriptive but concise
|
||||
- Reference issues when applicable
|
||||
|
||||
Examples:
|
||||
```
|
||||
feat: add support for Qwen models
|
||||
fix: resolve memory leak in model loading
|
||||
docs: update installation instructions
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If things go sideways:
|
||||
|
||||
1. **Check our [troubleshooting docs](https://jan.ai/docs/troubleshooting)**
|
||||
2. **Clear everything and start fresh:** `make clean` then `make dev`
|
||||
3. **Copy your error logs and system specs**
|
||||
4. **Ask for help in our [Discord](https://discord.gg/FTk2MvZwJH)** `#🆘|jan-help` channel
|
||||
|
||||
Common issues:
|
||||
- **Build failures**: Check Node.js and Rust versions
|
||||
- **Extension not loading**: Verify it's properly registered
|
||||
- **Model not working**: Check hardware requirements and GPU drivers
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [Documentation](https://jan.ai/docs) - The manual you should read
|
||||
- [Discord Community](https://discord.gg/jan) - Where the community lives
|
||||
- [GitHub Issues](https://github.com/janhq/jan/issues) - Report bugs here
|
||||
- [GitHub Discussions](https://github.com/janhq/jan/discussions) - Ask questions
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0 - Because sharing is caring. See [LICENSE](./LICENSE) for the legal stuff.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
Thank you for contributing to jan!
|
||||
We're building something pretty cool here - an AI assistant that respects your privacy and runs entirely on your machine. Every contribution, no matter how small, helps make AI more accessible to everyone.
|
||||
|
||||
Thanks for being part of the journey. Let's build the future of local AI together! 🚀
|
||||
|
||||
71
core/CONTRIBUTING.md
Normal file
71
core/CONTRIBUTING.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Contributing to Jan Core
|
||||
|
||||
[← Back to Main Contributing Guide](../CONTRIBUTING.md)
|
||||
|
||||
TypeScript SDK providing extension system, APIs, and type definitions for all Jan components.
|
||||
|
||||
## Key Directories
|
||||
|
||||
- **`/src/browser`** - Core APIs (events, extensions, file system)
|
||||
- **`/src/browser/extensions`** - Built-in extensions (assistant, inference, conversational)
|
||||
- **`/src/types`** - TypeScript type definitions
|
||||
- **`/src/test`** - Testing utilities
|
||||
|
||||
## Development
|
||||
|
||||
### Key Principles
|
||||
|
||||
1. **Platform Agnostic** - Works everywhere (browser, Node.js)
|
||||
2. **Extension-Based** - New features = new extensions
|
||||
3. **Type Everything** - TypeScript required
|
||||
4. **Event-Driven** - Components communicate via events
|
||||
|
||||
### Building & Testing
|
||||
|
||||
```bash
|
||||
# Build the SDK
|
||||
yarn build
|
||||
|
||||
# Run tests
|
||||
yarn test
|
||||
|
||||
# Watch mode
|
||||
yarn test:watch
|
||||
```
|
||||
|
||||
### Event System
|
||||
|
||||
```typescript
|
||||
// Emit events
|
||||
events.emit('model:loaded', { modelId: 'llama-3' })
|
||||
|
||||
// Listen for events
|
||||
events.on('model:loaded', (data) => {
|
||||
console.log('Model loaded:', data.modelId)
|
||||
})
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```typescript
|
||||
describe('MyFeature', () => {
|
||||
it('should do something', () => {
|
||||
const result = doSomething()
|
||||
expect(result).toBe('expected')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep it simple
|
||||
- Use TypeScript fully (no `any`)
|
||||
- Write tests for critical features
|
||||
- Follow existing patterns
|
||||
- Export new modules in index files
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **TypeScript** - Type safety
|
||||
- **Rolldown** - Bundling
|
||||
- **Vitest** - Testing
|
||||
137
extensions/CONTRIBUTING.md
Normal file
137
extensions/CONTRIBUTING.md
Normal file
@ -0,0 +1,137 @@
|
||||
# Contributing to Jan Extensions
|
||||
|
||||
[← Back to Main Contributing Guide](../CONTRIBUTING.md)
|
||||
|
||||
Extensions add specific features to Jan as self-contained modules.
|
||||
|
||||
## Current Extensions
|
||||
|
||||
### `/assistant-extension`
|
||||
- Assistant CRUD operations
|
||||
- `src/index.ts` - Main implementation
|
||||
|
||||
### `/conversational-extension`
|
||||
- Message handling, conversation state
|
||||
- `src/index.ts` - Chat logic
|
||||
|
||||
### `/download-extension`
|
||||
- Model downloads with progress tracking
|
||||
- `src/index.ts` - Download logic
|
||||
- `settings.json` - Download settings
|
||||
|
||||
### `/llamacpp-extension`
|
||||
- Local model inference via llama.cpp
|
||||
- `src/index.ts` - Entry point
|
||||
- `src/backend.ts` - llama.cpp integration
|
||||
- `settings.json` - Model settings
|
||||
|
||||
## Creating Extensions
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
mkdir my-extension
|
||||
cd my-extension
|
||||
yarn init
|
||||
```
|
||||
|
||||
### Structure
|
||||
|
||||
```
|
||||
my-extension/
|
||||
├── package.json
|
||||
├── rolldown.config.mjs
|
||||
├── src/index.ts
|
||||
└── settings.json (optional)
|
||||
```
|
||||
|
||||
### Basic Extension
|
||||
|
||||
```typescript
|
||||
import { Extension } from '@janhq/core'
|
||||
|
||||
export default class MyExtension extends Extension {
|
||||
async onLoad() {
|
||||
// Extension initialization
|
||||
}
|
||||
|
||||
async onUnload() {
|
||||
// Cleanup
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Building & Testing
|
||||
|
||||
```bash
|
||||
# Build extension
|
||||
yarn build
|
||||
|
||||
# Run tests
|
||||
yarn test
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Service Registration
|
||||
```typescript
|
||||
async onLoad() {
|
||||
this.registerService('myService', {
|
||||
doSomething: async () => 'result'
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Event Handling
|
||||
```typescript
|
||||
async onLoad() {
|
||||
this.on('model:loaded', (model) => {
|
||||
console.log('Model loaded:', model.id)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Extension Lifecycle
|
||||
|
||||
1. **Jan starts** → Discovers extensions
|
||||
2. **Loading** → Calls `onLoad()` method
|
||||
3. **Active** → Extension responds to events
|
||||
4. **Unloading** → Calls `onUnload()` on shutdown
|
||||
|
||||
## Debugging Extensions
|
||||
|
||||
```bash
|
||||
# Check if extension loaded
|
||||
console.log(window.core.extensions)
|
||||
|
||||
# Debug extension events
|
||||
this.on('*', console.log)
|
||||
|
||||
# Check extension services
|
||||
console.log(window.core.api)
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
**Extension not loading?**
|
||||
- Check package.json format: `@janhq/extension-name`
|
||||
- Ensure `onLoad()` doesn't throw errors
|
||||
- Verify exports in index.ts
|
||||
|
||||
**Events not working?**
|
||||
- Check event name spelling
|
||||
- Ensure listeners are set up in `onLoad()`
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep extensions focused on one feature
|
||||
- Use async/await for all operations
|
||||
- Clean up resources in onUnload()
|
||||
- Handle errors gracefully
|
||||
- Don't depend on other extensions
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **@janhq/core** - Core SDK and extension system
|
||||
- **TypeScript** - Type safety
|
||||
- **Rolldown** - Bundling
|
||||
111
src-tauri/CONTRIBUTING.md
Normal file
111
src-tauri/CONTRIBUTING.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Contributing to Tauri Backend
|
||||
|
||||
[← Back to Main Contributing Guide](../CONTRIBUTING.md)
|
||||
|
||||
Rust backend that handles native system integration, file operations, and process management.
|
||||
|
||||
## Key Modules
|
||||
|
||||
- **`/src/core/app`** - App state and commands
|
||||
- **`/src/core/downloads`** - Model download management
|
||||
- **`/src/core/filesystem`** - File system operations
|
||||
- **`/src/core/mcp`** - Model Context Protocol
|
||||
- **`/src/core/server`** - Local API server
|
||||
- **`/src/core/system`** - System information and utilities
|
||||
- **`/src/core/threads`** - Conversation management
|
||||
- **`/utils`** - Shared utility crate (CLI, crypto, HTTP, path utils). Used by plugins and the main backend.
|
||||
- **`/plugins`** - Native Tauri plugins ([see plugins guide](./plugins/CONTRIBUTING.md))
|
||||
|
||||
## Development
|
||||
|
||||
### Adding Tauri Commands
|
||||
|
||||
```rust
|
||||
#[tauri::command]
|
||||
async fn my_command(param: String) -> Result<String, String> {
|
||||
Ok(format!("Processed: {}", param))
|
||||
}
|
||||
|
||||
// Register in lib.rs
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![my_command])
|
||||
```
|
||||
|
||||
## Building & Testing
|
||||
|
||||
```bash
|
||||
# Development
|
||||
yarn tauri dev
|
||||
|
||||
# Build
|
||||
yarn tauri build
|
||||
|
||||
# Run tests
|
||||
cargo test
|
||||
```
|
||||
|
||||
### State Management
|
||||
|
||||
```rust
|
||||
#[tauri::command]
|
||||
async fn get_data(state: State<'_, AppState>) -> Result<Data, Error> {
|
||||
state.get_data().await
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```rust
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum AppError {
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
```rust
|
||||
// Enable debug logging
|
||||
env::set_var("RUST_LOG", "debug");
|
||||
|
||||
// Debug print in commands
|
||||
#[tauri::command]
|
||||
async fn my_command() -> Result<String, String> {
|
||||
println!("Command called"); // Shows in terminal
|
||||
dbg!("Debug info");
|
||||
Ok("result".to_string())
|
||||
}
|
||||
```
|
||||
|
||||
## Platform-Specific Notes
|
||||
|
||||
**Windows**: Requires Visual Studio Build Tools
|
||||
**macOS**: Needs Xcode command line tools
|
||||
**Linux**: May need additional system packages
|
||||
|
||||
```rust
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
**Build failures**: Check Rust toolchain version
|
||||
**IPC errors**: Ensure command names match frontend calls
|
||||
**Permission errors**: Update capabilities configuration
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Always use `Result<T, E>` for fallible operations
|
||||
- Validate all input from frontend
|
||||
- Use async for I/O operations
|
||||
- Follow Rust naming conventions
|
||||
- Document public APIs
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Tauri** - Desktop app framework
|
||||
- **Tokio** - Async runtime
|
||||
- **Serde** - JSON serialization
|
||||
- **thiserror** - Error handling
|
||||
119
src-tauri/plugins/CONTRIBUTING.md
Normal file
119
src-tauri/plugins/CONTRIBUTING.md
Normal file
@ -0,0 +1,119 @@
|
||||
# Contributing to Tauri Plugins
|
||||
|
||||
[← Back to Main Contributing Guide](../../CONTRIBUTING.md) | [← Back to Tauri Guide](../CONTRIBUTING.md)
|
||||
|
||||
Native Rust plugins for hardware access, process management, and system integration.
|
||||
|
||||
## Current Plugins
|
||||
|
||||
### `/tauri-plugin-hardware`
|
||||
- Hardware detection (CPU, GPU, memory)
|
||||
|
||||
### `/tauri-plugin-llamacpp`
|
||||
- llama.cpp process management and model inference
|
||||
|
||||
## Plugin Structure
|
||||
|
||||
```
|
||||
tauri-plugin-name/
|
||||
├── Cargo.toml
|
||||
├── src/lib.rs # Plugin entry point
|
||||
├── src/commands.rs # Tauri commands
|
||||
├── guest-js/index.ts # JavaScript API
|
||||
└── permissions/default.toml
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Creating Plugins
|
||||
|
||||
Assuming that your new plugin name is `my-plugin`
|
||||
|
||||
```bash
|
||||
# with npx
|
||||
npx @tauri-apps/cli plugin new my-plugin
|
||||
|
||||
# with cargo
|
||||
cargo tauri plugin new my-plugin
|
||||
|
||||
cd tauri-plugin-my-plugin
|
||||
```
|
||||
|
||||
### Plugin Registration
|
||||
|
||||
```rust
|
||||
use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("my-plugin")
|
||||
.invoke_handler(tauri::generate_handler![commands::my_command])
|
||||
.build()
|
||||
}
|
||||
```
|
||||
|
||||
### Commands & JavaScript API
|
||||
|
||||
```rust
|
||||
#[tauri::command]
|
||||
pub async fn my_command(param: String) -> Result<String, Error> {
|
||||
Ok(format!("Result: {}", param))
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
export async function myCommand(param: string): Promise<string> {
|
||||
return await invoke('plugin:my-plugin|my_command', { param })
|
||||
}
|
||||
```
|
||||
|
||||
### Building & Testing
|
||||
|
||||
```bash
|
||||
cargo build # Build plugin
|
||||
yarn build # Build JavaScript
|
||||
cargo test # Run tests
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
```toml
|
||||
# permissions/default.toml - Be specific
|
||||
[[permission]]
|
||||
identifier = "allow-hardware-info"
|
||||
description = "Read system hardware information"
|
||||
|
||||
# Never use wildcards in production
|
||||
# ❌ identifier = "allow-*"
|
||||
# ✅ identifier = "allow-specific-action"
|
||||
```
|
||||
|
||||
## Testing Plugins
|
||||
|
||||
```bash
|
||||
# Test plugin in isolation
|
||||
cd tauri-plugin-my-plugin
|
||||
cargo test
|
||||
|
||||
# Test with main app
|
||||
cd ../../
|
||||
yarn tauri dev
|
||||
|
||||
# Test JavaScript API
|
||||
yarn build && node -e "const plugin = require('./dist-js'); console.log(plugin)"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use secure permission configurations
|
||||
- Validate all command inputs
|
||||
- Handle platform differences properly
|
||||
- Clean up resources in Drop implementations
|
||||
- Test on all target platforms
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Tauri** - Plugin framework
|
||||
- **Serde** - JSON serialization
|
||||
- **Tokio** - Async runtime (if needed)
|
||||
128
web-app/CONTRIBUTING.md
Normal file
128
web-app/CONTRIBUTING.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Contributing to Jan Web App
|
||||
|
||||
[← Back to Main Contributing Guide](../CONTRIBUTING.md)
|
||||
|
||||
React frontend using TypeScript, TanStack Router, Radix UI, and Tailwind CSS. State is managed by React State and Zustand.
|
||||
|
||||
## Key Directories
|
||||
|
||||
- **`/src/components/ui`** - UI components (buttons, dialogs, inputs)
|
||||
- **`/src/containers`** - Complex feature components (ChatInput, ThreadContent)
|
||||
- **`/src/hooks`** - Custom React hooks (useChat, useThreads, useAppState)
|
||||
- **`/src/routes`** - TanStack Router pages
|
||||
- **`/src/services`** - API layer for backend communication
|
||||
- **`/src/types`** - TypeScript definitions
|
||||
|
||||
## Development
|
||||
|
||||
### Component Example
|
||||
|
||||
```tsx
|
||||
interface Props {
|
||||
title: string
|
||||
onAction?: () => void
|
||||
}
|
||||
|
||||
export const MyComponent: React.FC<Props> = ({ title, onAction }) => {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<h2>{title}</h2>
|
||||
<Button onClick={onAction}>Action</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Routing
|
||||
|
||||
```tsx
|
||||
export const Route = createFileRoute('/settings/general')({
|
||||
component: GeneralSettings
|
||||
})
|
||||
```
|
||||
|
||||
### Building & Testing
|
||||
|
||||
```bash
|
||||
# Development
|
||||
yarn dev
|
||||
yarn build
|
||||
yarn test
|
||||
```
|
||||
|
||||
### State Management
|
||||
|
||||
```tsx
|
||||
// Local state
|
||||
const [value, setValue] = useState<string>('')
|
||||
|
||||
// Global state (Zustand)
|
||||
export const useAppState = create<AppState>((set) => ({
|
||||
data: null,
|
||||
setData: (data) => set({ data })
|
||||
}))
|
||||
```
|
||||
|
||||
### Tauri Integration
|
||||
|
||||
```tsx
|
||||
import { invoke } from '@tauri-apps/api/tauri'
|
||||
|
||||
const result = await invoke('command_name', { param: 'value' })
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
```tsx
|
||||
// Use React.memo for expensive components
|
||||
const ExpensiveComponent = React.memo(({ data }) => {
|
||||
return <div>{processData(data)}</div>
|
||||
})
|
||||
|
||||
// Debounce frequent updates
|
||||
const debouncedValue = useDebounce(searchTerm, 300)
|
||||
|
||||
// Virtual scrolling for large lists
|
||||
import { VariableSizeList } from 'react-window'
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
```bash
|
||||
# React DevTools
|
||||
# Install browser extension, then:
|
||||
# - Inspect component tree
|
||||
# - Debug hooks and state
|
||||
# - Profile performance
|
||||
|
||||
# Debug Tauri commands
|
||||
console.log(await window.__TAURI__.invoke('command_name'))
|
||||
|
||||
# Check for console errors
|
||||
# Press F12 → Console tab
|
||||
```
|
||||
|
||||
## Accessibility Guidelines
|
||||
|
||||
- Use semantic HTML (`<button>`, `<nav>`, `<main>`)
|
||||
- Add ARIA labels: `aria-label`, `aria-describedby`
|
||||
- Ensure keyboard navigation works
|
||||
- Test with screen readers
|
||||
- Maintain color contrast ratios
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep components small and focused
|
||||
- Use TypeScript fully (no `any`)
|
||||
- Handle loading and error states
|
||||
- Follow accessibility guidelines
|
||||
- Extract business logic into hooks
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **React** - UI framework
|
||||
- **TypeScript** - Type safety
|
||||
- **TanStack Router** - Type-safe routing
|
||||
- **Radix UI** - Accessible components
|
||||
- **Tailwind CSS** - Utility-first styling
|
||||
- **Zustand** - State management
|
||||
Loading…
x
Reference in New Issue
Block a user