Files
windmill/CLAUDE.md
claude[bot] 2f0b224437 docs: ban $bindable(default_value) on optional props in CLAUDE.md (#8267)
Add a "Banned Patterns" section documenting that $bindable(default_value)
on props that can be undefined is banned. The correct alternatives are
using $derived(my_prop ?? default_value) or creating a useMyPropState()
helper higher in the component tree.

Closes #8266

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-03-07 18:55:40 +00:00

2.4 KiB

Windmill

Open-source platform for internal tools, workflows, API integrations, background jobs, and UIs. Rust backend + Svelte 5 frontend.

Workflow

  1. Understand: Before coding, read relevant docs from docs/ to understand the area you're changing
  2. Plan: For non-trivial changes, use plan mode. For large features, break into reviewable stages
  3. Execute: Follow coding patterns from skills (rust-backend, svelte-frontend)
  4. Validate: After every change, run the appropriate checks per docs/validation.md

Documentation

  • Validation: docs/validation.md — what checks to run based on what you changed
  • Enterprise: docs/enterprise.md — EE file conventions and PR workflow
  • Backend patterns: use the rust-backend skill when writing Rust code
  • Frontend patterns: use the svelte-frontend skill when writing Svelte code
  • Domain guides: .claude/skills/native-trigger/ and frontend/tutorial-system-guide.mdc
  • Brand/UI guidelines: frontend/brand-guidelines.md

Dev Environment

  • Backend: cargo run from backend/ (API at http://localhost:8000)
  • Frontend: REMOTE=http://localhost:8000 npm run dev from frontend/ (port 3000+)
  • DB: psql postgres://postgres:changeme@localhost:5432/windmill
  • Login: admin@windmill.dev / changeme
  • Instance settings: navigate to /#superadmin-settings

Banned Patterns

$bindable(default_value) on optional props

Using $bindable(default_value) on props that can be undefined is banned. This pattern causes subtle bugs because the default value masks the undefined state.

Bad:

let { my_prop = $bindable(default_value) }: { my_prop?: string } = $props()

Correct alternatives:

  1. Use $derived with nullish coalescing — handle the potential undefined at the usage site:

    let { my_prop = $bindable() }: { my_prop?: string } = $props()
    let effective_value = $derived(my_prop ?? default_value)
    
  2. Create a useMyPropState() helper — encapsulate the undefined-handling logic in a reusable function and call it higher in the component tree, so the child component always receives a defined value.

Core Principles

  • Search for existing code to reuse before writing new code
  • Follow established patterns in the codebase
  • Keep changes focused — don't refactor beyond what's asked