jan/web-app/CONTRIBUTING.md
Dinh Long Nguyen b0eec07a01
Add contributing section for jan (#6231) (#6232)
* 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>
2025-08-20 10:18:35 +07:00

2.7 KiB

Contributing to Jan Web App

← Back to Main Contributing Guide

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

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

export const Route = createFileRoute('/settings/general')({
  component: GeneralSettings
})

Building & Testing

# Development
yarn dev
yarn build
yarn test

State Management

// Local state
const [value, setValue] = useState<string>('')

// Global state (Zustand)
export const useAppState = create<AppState>((set) => ({
  data: null,
  setData: (data) => set({ data })
}))

Tauri Integration

import { invoke } from '@tauri-apps/api/tauri'

const result = await invoke('command_name', { param: 'value' })

Performance Tips

// 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

# 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