TeamIDE-methodology/templates/TauriStarter/CLAUDE.md

18 KiB

Project Guidelines

Protecting This File

IMPORTANT: This file (CLAUDE.md) can be lost during branch operations!

Git doesn't protect untracked/ignored files during git checkout or branch switches. Before major git operations:

cp CLAUDE.md CLAUDE.md.backup

Project Structure

This project follows a standardized structure for Tauri desktop apps.

ProjectRoot/
├── CLAUDE.md             # AI assistant guidelines
├── README.md             # Project documentation
├── build_spec.md         # Full project specification
├── build_plan.md         # Phased task checklist
├── .gitignore
├── docs/                 # Technical documentation
│   ├── README.md         # Docs index with table of contents
│   ├── getting-started.md
│   ├── architecture.md
│   ├── development.md
│   ├── deployment.md
│   └── feature-*.md      # Feature docs (added per phase)
└── app/                  # ALL project code lives here
    ├── build.sh          # Build script
    ├── package.json
    ├── vite.config.ts
    ├── tsconfig.json
    ├── index.html
    ├── src/
    │   ├── main.ts
    │   ├── App.vue
    │   ├── boot/
    │   │   └── console-logger.ts
    │   ├── components/
    │   ├── composables/
    │   ├── css/
    │   ├── layouts/
    │   ├── pages/
    │   ├── router/
    │   ├── stores/
    │   ├── services/
    │   └── types/
    └── src-tauri/
        ├── Cargo.toml
        ├── tauri.conf.json
        ├── icons/
        └── src/
            └── main.rs

TeamIDE Project Management

If this project was scaffolded from Ideation, .teamide/ PM files (plans, tasks, project.yml) should already exist — generated from build_plan.md during scaffolding. See the Ideation workspace's claude.md for the PM generation workflow and format details.

Terminology

  • "build spec" or "spec" refers to build_spec.md - the full project description
  • "build plan" or "plan" refers to build_plan.md - the phased task checklist

Onboarding Questions (Ask at Project Start)

At the start of every new project conversation, gather these details before writing any code:

  1. Brand colors & fonts - Primary, secondary, accent colors. Typography preferences. Any existing brand guidelines or color palette?
  2. App personality & tone - Formal or casual? Dark or light default theme? Dense or spacious layout? Any design inspiration or reference apps?
  3. Target platform - Desktop-first, mobile-first, or responsive? Specific OS targets (macOS, Windows, Linux)? Minimum screen sizes?
  4. Auth requirements - Login method (email/password, OAuth, magic link)? User roles and permissions? Public or private app?

Don't assume defaults for any of these. Ask, get answers, then document them in the Project-Specific Configuration section at the bottom of this file.

Tech Stack

  • Frontend: Quasar Framework (Vue 3) + Vite
  • Desktop: Tauri (Rust) - Cross-platform builds (macOS, Windows, Linux)
  • State: Pinia
  • Routing: Vue Router
  • Backend (optional): Nhost (self-hosted or cloud)
    • PostgreSQL - Database
    • Hasura - GraphQL API
    • Auth - Authentication service
    • Storage - File storage
    • Functions - Serverless functions (Node.js)

Testing Changes (CRITICAL)

After every code editing session, you MUST rebuild the app so the user can test your changes.

cd app
./build.sh -dev -open

Why This Matters

  • This uses a build-and-run approach, not hot reload
  • Your code changes are NOT visible until you rebuild
  • Always rebuild before asking the user to test
  • If the user reports issues, check the logs first: ./build.sh logs

Build Script

Always use build.sh for building the app. This ensures consistent builds and logging for collaborative debugging.

cd app

./build.sh -dev -open    # Build dev and open app
./build.sh -prod         # Build prod to build/prod/
./build.sh -install      # Build prod and open Finder for drag-to-Applications
./build.sh logs          # View latest console output (last 100 lines)
./build.sh clean         # Clean build artifacts (preserves logs)
./build.sh clean-logs    # Remove all logs

Commands

Command Description
-dev Development build. Bundle ID: com.[app].dev
-prod Production build. Builds to build/prod/.
-install Build prod and open Finder for drag-to-Applications.
-open Open the app after building (use with -dev or -prod)
-secure Build without automation (no HTTP server on port 9876)
logs Show last 100 lines of console output
clean Remove build artifacts (preserves logs)
clean-logs Remove all log files

Why Build-and-Run (No Hot Reload)

This project uses a build-and-run approach instead of hot reload:

Aspect Hot Reload Build-and-Run
Speed Instant updates Full rebuild required
Dev/Prod parity Different environments Identical to production
Debugging Dev-only issues possible What you test = what ships
Logging Console only Full logs to files

The tradeoff is slower iteration, but you always test exactly what will ship.

What the Build Does

  1. Build with Tauri - npx tauri build does all of the following:
    • Build frontend (npm run build → dist/)
    • Build Rust binary with embedded frontend
    • Create .app bundle in src-tauri/target/release/bundle/macos/
  2. Copy to build folder - Copies bundle to build/dev/ or build/prod/
  3. Update Info.plist - Sets correct bundle ID for dev/prod
  4. Install (prod only) - Copies to ~/Applications

Important: Using npx tauri build ensures the frontend is properly embedded in the binary. Manual cargo build --release does NOT embed the frontend.

Build Output

Builds are organized in separate folders:

app/build/
├── dev/
│   └── AppName.app      # Dev build (bundle ID: .dev)
├── prod/
│   └── AppName.app      # Prod build
├── logs/
│   ├── build_dev_*.log  # Build output logs
│   └── build_latest.log # Symlink to latest
└── console/
    ├── console_*.log    # App runtime console output
    └── console_latest.log # Symlink to latest

Dev and prod have different bundle IDs, so both can run simultaneously.

Logging

All build output and app console output is logged:

  • Build logs: build/logs/build_latest.log - compilation output, errors
  • Console logs: build/console/console_latest.log - runtime console.log(), errors

When debugging, run ./build.sh logs to see the latest console output.

Console Logging (Already Configured)

This template includes console logging out of the box. Frontend console.log() calls are forwarded to Rust and captured in log files.

How it works:

console.log() → console-logger.ts → invoke('log_to_stdout') → Rust println!() → stdout → build.sh logs

Automation Plugin (Already Configured)

This template includes an automation HTTP server for external testing and AI-assisted development.

How it works:

External Tool (curl) → HTTP Server (port 9876) → Rust → JavaScript → DOM

Automation API

When the app is running, these endpoints are available:

# Health check
curl http://localhost:9876/automation/health

# Execute a command
curl -X POST http://localhost:9876/automation/execute \
  -H "Content-Type: application/json" \
  -d '{"command": "click", "args": {"selector": "#my-button"}}'

# Take a screenshot
curl http://localhost:9876/automation/screenshot --output screenshot.png

Available Commands

Command Args Description
navigate {path} Navigate to route
click {selector} Click element
type {selector, text} Type into input
getText {selector} Get element text
getValue {selector} Get input value
exists {selector} Check if element exists
waitFor {selector, timeout?} Wait for element
getUrl {} Get current URL
screenshot - Capture page (via endpoint)

Full command list in src/automation/README.md.

Disabling Automation

Option 1: Build flag (recommended)

Use the -secure flag to build without automation:

./build.sh -prod -secure    # Production build without automation

Option 2: Permanently disable

Remove automation from the default features in Cargo.toml:

[features]
default = ["custom-protocol"]  # Remove "automation"

When to Clean

Run ./build.sh clean when:

  • Switching between major dependency versions
  • Build errors reference stale/cached files
  • Rust compilation issues after Tauri config changes
  • Before creating a fresh production build

Node.js Environment

Node.js version: Always match Debian stable (currently Node.js 18.x for Debian 12 Bookworm)

Check current Debian stable Node version: https://packages.debian.org/stable/nodejs

Package manager: Use npm. Commit lock files for reproducible builds.

Rules:

  • Always commit package-lock.json - required for deterministic installs
  • Never ignore lock files (package-lock.json, yarn.lock, pnpm-lock.yaml)
  • Use npm install to install dependencies
  • Use npm run <script> to run package scripts

Communication Rules

Always explain before acting. Before running any command, SSH, database query, or making changes:

  • Give a short, concise explanation of WHAT you're about to do and WHY
  • Wait for approval on anything that modifies production data or server state
  • Don't chain multiple server commands without explaining each step

Database Rules (If Using Nhost Backend)

NEVER make direct database changes via Hasura MCP or Hasura Console.

All database changes MUST be done through migrations so they:

  1. Are tracked in version control
  2. Persist across restarts (nhost down / nhost up)
  3. Can be reproduced in production

Hasura MCP Usage

  • READ-ONLY: Use Hasura MCP only to inspect schema, check what tables exist, verify tracking status
  • NO MUTATIONS: Never use it to create tables, add columns, track tables, or modify permissions
  • MIGRATIONS ONLY: All schema changes go in app/nhost/migrations/default/
  • METADATA ONLY: All Hasura config (tracking, permissions, relationships) go in app/nhost/metadata/

How to Make Database Changes

  1. Write SQL migration in app/nhost/migrations/default/<N>_<name>/up.sql (N = next version number)
  2. Write rollback in app/nhost/migrations/default/<N>_<name>/down.sql
  3. Add Hasura metadata YAML in app/nhost/metadata/databases/default/tables/
  4. Restart dev environment to apply migrations
  5. Commit and push

Hasura Role Permissions (CRITICAL)

NEVER define permissions for the admin role in Hasura metadata.

Hasura reserves admin as a special role with full unrestricted access. Defining explicit permissions for admin causes metadata errors.

Define permissions only for user, public, and custom roles.

Development Approach

Integrate-as-you-go - Connect real backend services as you build. Don't build elaborate mock systems.

Persistence Rules (CRITICAL)

All persistence requires an explicit user action. No exceptions.

Never auto-save. Never sync state in the background. Never write to the database on a timer or watcher. Every single write to a database, file, or storage must be traceable to a deliberate user action.

The Rule

Data is only persisted when the user deliberately triggers it — clicking "Save", submitting a form, confirming a dialog, toggling a setting, etc.

WRONG — Never Do This

  • Auto-saving form fields as the user types
  • Syncing component state to the database on mount/unmount
  • Watchers that write to storage when reactive data changes
  • Debounced save on input change
  • Persisting UI state automatically (sidebar position, tab selection, scroll position)
  • Writing to the database during navigation or route changes
  • Background sync intervals or polling that writes data

RIGHT — Always Do This

  • User clicks "Save" → write to database
  • User submits a form → persist the data
  • User explicitly toggles a setting → save that setting
  • User clicks "Delete" → confirm, then remove from database
  • User drags an item to reorder → save on drop (explicit action)

Why This Matters

Auto-save creates unpredictable behavior, race conditions, and persists data the user didn't intend to save. Every write should be traceable to a conscious user decision. If you can't point to the button or action the user took to trigger the save, it shouldn't be saving.

Implementation Pattern

User Action → Service Call → Database Write → Confirm Success to User
  1. User triggers action (click, submit, confirm)
  2. Call the appropriate service/API
  3. Write to database
  4. Show success feedback (Quasar Notify or UI update)
  5. If it fails, show an error — don't silently retry

Code Quality

TypeScript

  • Use TypeScript strict mode
  • Define interfaces/types for all data structures in src/types/
  • No any types unless absolutely unavoidable — use unknown and narrow instead
  • Type all function parameters and return values

Vue / Quasar Conventions

  • Use Composition API with <script setup lang="ts"> for all components
  • One component per file, named in PascalCase (e.g., UserProfile.vue)
  • Composables go in src/composables/, prefixed with use (e.g., useAuth.ts)
  • Keep components focused — if it's doing too much, split it
  • Props down, events up — don't mutate props, emit events to parent

Naming

  • Files: PascalCase for components (UserCard.vue), camelCase for everything else (userService.ts)
  • Variables/functions: camelCase
  • Constants: UPPER_SNAKE_CASE for true constants, camelCase for derived/computed values
  • Types/Interfaces: PascalCase, no I prefix (use User not IUser)
  • CSS classes: kebab-case

General

  • No magic numbers or strings — use named constants
  • Keep functions short and single-purpose
  • Colocate related code — don't scatter logic across files unnecessarily
  • Delete dead code, don't comment it out

Error Handling

User-Facing Errors

  • Always show human-readable messages — never expose raw error objects, stack traces, or technical details to the user
  • Use Quasar's Notify plugin for transient feedback (success, warning, error)
  • Use inline error messages for form validation

Technical Errors

  • Log technical details to console for debugging (console.error with context)
  • Include the operation that failed and relevant IDs in log messages
  • Never swallow errors silently — if you catch it, either handle it or log it

Pattern

try {
  const result = await userService.updateProfile(data)
  Notify.create({ type: 'positive', message: 'Profile updated' })
} catch (error) {
  console.error('Failed to update profile:', error)
  Notify.create({ type: 'negative', message: 'Could not update profile. Try again.' })
}

Where to Catch

  • Catch at service boundaries (API calls, database operations), not deep in utility functions
  • Let errors propagate up to where they can be meaningfully handled
  • Don't wrap every line in try/catch — catch at the level where you can show the user feedback

Documentation

Every phase ends with documentation. After completing a feature or phase:

  1. Create feature docs - Copy docs/TEMPLATE-feature.md to docs/feature-[name].md
  2. Update the index - Add links to docs/README.md table of contents
  3. Update core docs - Keep architecture.md, development.md current

Docs Structure

File Purpose
docs/README.md Index with table of contents
docs/getting-started.md Installation & setup
docs/architecture.md Tech stack & design decisions
docs/development.md Development workflow
docs/deployment.md Build & deployment
docs/feature-*.md Feature-specific documentation

Naming Convention

  • feature-[name].md - Feature docs (e.g., feature-authentication.md)
  • component-[name].md - Component docs
  • integration-[name].md - Integration docs
  • guide-[topic].md - How-to guides

Commit Rules

  • Never mention Claude, AI, or "Generated with Claude Code" in commits
  • All commits are authored by the developer - no co-author tags
  • Write commit messages in first person as the developer
  • Keep commit messages concise and descriptive of the changes

Branch Strategy

  • main - Production branch
  • test - Staging/testing branch

Workflow:

  1. Develop and test locally
  2. Push to test branch for staging
  3. Verify on staging
  4. Merge test → main for production

Customization Checklist

When using this template for a new project:

  1. Update app/src-tauri/tauri.conf.json:

    • productName
    • identifier (e.g., com.yourapp.app)
    • title
  2. Update app/package.json:

    • name
    • description
  3. Update app/build.sh:

    • APP_NAME
    • BINARY_NAME (must match productName)
    • BUNDLE_ID_DEV
    • BUNDLE_ID_PROD
  4. Replace placeholder icons in app/src-tauri/icons/

  5. Update documentation:

    • Replace [Project Name] in all docs/*.md files
    • Update docs/architecture.md with project-specific tech decisions
    • Update docs/getting-started.md with project-specific setup
  6. Add your pages, components, and stores

  7. Add Tauri commands to src-tauri/src/main.rs


Project-Specific Configuration

Project Name

[PROJECT_NAME]

Description

[Brief description from build_spec.md]

Backend (If Applicable)

Service URL
GraphQL
Auth
Storage

Database Schema (If Applicable)

[Tables and relationships]

TeamIDE Hosting (If Applicable)

  • Workspace ID: your-workspace-id-here
  • Use teamide_deploy to deploy changes
  • Use teamide_set_env_vars to configure environment variables
  • Use teamide_get_logs to check build status