|
1 | 1 | # Repository Guidelines |
2 | 2 |
|
3 | 3 | ## Project Structure & Module Organization |
4 | | -- Source: `src/` (Vue 3 + TypeScript). Key areas: `components/`, `views/`, `stores/` (Pinia), `composables/`, `services/`, `utils/`, `assets/`, `locales/`. |
5 | | -- Routing/i18n/entry: `src/router.ts`, `src/i18n.ts`, `src/main.ts`. |
6 | | -- Tests: unit/component in `tests-ui/` and `src/components/**/*.{test,spec}.ts`; E2E in `browser_tests/`. |
7 | | -- Public assets: `public/`. Build output: `dist/`. |
8 | | -- Config: `vite.config.mts`, `vitest.config.ts`, `playwright.config.ts`, `eslint.config.ts`, `.prettierrc`. |
| 4 | + |
| 5 | +- Source: `src/` |
| 6 | + - Vue 3.5+ |
| 7 | + - TypeScript |
| 8 | + - Tailwind 4 |
| 9 | + - Key areas: |
| 10 | + - `components/` |
| 11 | + - `views/` |
| 12 | + - `stores/` (Pinia) |
| 13 | + - `composables/` |
| 14 | + - `services/` |
| 15 | + - `utils/` |
| 16 | + - `assets/` |
| 17 | + - `locales/` |
| 18 | +- Routing: `src/router.ts`, |
| 19 | +- i18n: `src/i18n.ts`, |
| 20 | +- Entry Point: `src/main.ts`. |
| 21 | +- Tests: |
| 22 | + - unit/component in `tests-ui/` and `src/**/*.test.ts` |
| 23 | + - E2E (Playwright) in `browser_tests/**/*.spec.ts` |
| 24 | +- Public assets: `public/` |
| 25 | +- Build output: `dist/` |
| 26 | +- Configs |
| 27 | + - `vite.config.mts` |
| 28 | + - `vitest.config.ts` |
| 29 | + - `playwright.config.ts` |
| 30 | + - `eslint.config.ts` |
| 31 | + - `.prettierrc` |
| 32 | + - etc. |
| 33 | + |
| 34 | +## Monorepo Architecture |
| 35 | + |
| 36 | +The project now uses **Nx** for build orchestration and task management: |
| 37 | + |
| 38 | +- **Task Orchestration**: Commands like `dev`, `build`, `lint`, and `test:browser` run via Nx |
| 39 | +- **Caching**: Nx provides intelligent caching for faster rebuilds |
| 40 | +- **Configuration**: Managed through `nx.json` with plugins for ESLint, Storybook, Vite, and Playwright |
| 41 | +- **Dependencies**: Nx handles dependency graph analysis and parallel execution |
| 42 | + |
| 43 | +Key Nx features: |
| 44 | + |
| 45 | +- Build target caching and incremental builds |
| 46 | +- Parallel task execution across the monorepo |
| 47 | +- Plugin-based architecture for different tools |
9 | 48 |
|
10 | 49 | ## Build, Test, and Development Commands |
| 50 | + |
11 | 51 | - `pnpm dev`: Start Vite dev server. |
12 | | -- `pnpm dev:electron`: Dev server with Electron API mocks. |
13 | | -- `pnpm build`: Type-check then production build to `dist/`. |
14 | | -- `pnpm preview`: Preview the production build locally. |
15 | | -- `pnpm test:unit`: Run Vitest unit tests. |
16 | | -- `pnpm test:browser`: Run Playwright E2E tests (`browser_tests/`). |
17 | | -- `pnpm lint` / `pnpm lint:fix`: Lint (ESLint). `pnpm format` / `format:check`: Prettier. |
18 | | -- `pnpm typecheck`: Vue TSC type checking. |
| 52 | +- `pnpm dev:electron`: Dev server with Electron API mocks |
| 53 | +- `pnpm build`: Type-check then production build to `dist/` |
| 54 | +- `pnpm preview`: Preview the production build locally |
| 55 | +- `pnpm test:unit`: Run Vitest unit tests |
| 56 | +- `pnpm test:browser`: Run Playwright E2E tests (`browser_tests/`) |
| 57 | +- `pnpm lint` / `pnpm lint:fix`: Lint (ESLint) |
| 58 | +- `pnpm format` / `pnpm format:check`: Prettier |
| 59 | +- `pnpm typecheck`: Vue TSC type checking |
19 | 60 |
|
20 | 61 | ## Coding Style & Naming Conventions |
21 | | -- Language: TypeScript, Vue SFCs (`.vue`). Indent 2 spaces; single quotes; no semicolons; width 80 (see `.prettierrc`). |
22 | | -- Imports: sorted/grouped by plugin; run `pnpm format` before committing. |
23 | | -- ESLint: Vue + TS rules; no floating promises; unused imports disallowed; i18n raw text restrictions in templates. |
24 | | -- Naming: Vue components in PascalCase (e.g., `MenuHamburger.vue`); composables `useXyz.ts`; Pinia stores `*Store.ts`. |
| 62 | + |
| 63 | +- Language: |
| 64 | + - TypeScript (exclusive, no new JavaScript) |
| 65 | + - Vue 3 SFCs (`.vue`) |
| 66 | + - Composition API only |
| 67 | + - Tailwind 4 styling |
| 68 | + - Avoid `<style>` blocks |
| 69 | +- Style: (see `.prettierrc`) |
| 70 | + - Indent 2 spaces |
| 71 | + - single quotes |
| 72 | + - no trailing semicolons |
| 73 | + - width 80 |
| 74 | +- Imports: |
| 75 | + - sorted/grouped by plugin |
| 76 | + - run `pnpm format` before committing |
| 77 | +- ESLint: |
| 78 | + - Vue + TS rules |
| 79 | + - no floating promises |
| 80 | + - unused imports disallowed |
| 81 | + - i18n raw text restrictions in templates |
| 82 | +- Naming: |
| 83 | + - Vue components in PascalCase (e.g., `MenuHamburger.vue`) |
| 84 | + - composables `useXyz.ts` |
| 85 | + - Pinia stores `*Store.ts` |
25 | 86 |
|
26 | 87 | ## Testing Guidelines |
27 | | -- Frameworks: Vitest (unit/component, happy-dom) and Playwright (E2E). |
28 | | -- Test files: `**/*.{test,spec}.{ts,tsx,js}` under `tests-ui/`, `src/components/`, and `src/lib/litegraph/test/`. |
29 | | -- Coverage: text/json/html reporters enabled; aim to cover critical logic and new features. |
30 | | -- Playwright: place tests in `browser_tests/`; optional tags like `@mobile`, `@2x` are respected by config. |
| 88 | + |
| 89 | +- Frameworks: |
| 90 | + - Vitest (unit/component, happy-dom) |
| 91 | + - Playwright (E2E) |
| 92 | +- Test files: |
| 93 | + - Unit/Component: `**/*.test.ts` |
| 94 | + - E2E: `browser_tests/**/*.spec.ts` |
| 95 | + - Litegraph Specific: `src/lib/litegraph/test/` |
| 96 | +- Coverage: text/json/html reporters enabled |
| 97 | + - aim to cover critical logic and new features |
| 98 | +- Playwright: |
| 99 | + - optional tags like `@mobile`, `@2x` are respected by config |
31 | 100 |
|
32 | 101 | ## Commit & Pull Request Guidelines |
33 | | -- Commits: Use `[skip ci]` for locale-only updates when appropriate. |
34 | | -- PRs: Include clear description, linked issues (`- Fixes #123`), and screenshots/GIFs for UI changes. |
35 | | -- Quality gates: `pnpm lint`, `pnpm typecheck`, and relevant tests must pass. Keep PRs focused and small. |
| 102 | + |
| 103 | +- Commits: Use `[skip ci]` for locale-only updates when appropriate |
| 104 | +- PRs: Include clear description, linked issues (`- Fixes #123`), and screenshots/GIFs for UI changes |
| 105 | +- Quality gates: `pnpm lint`, `pnpm typecheck`, and relevant tests must pass |
| 106 | +- Keep PRs focused and small |
36 | 107 |
|
37 | 108 | ## Security & Configuration Tips |
| 109 | + |
38 | 110 | - Secrets: Use `.env` (see `.env_example`); do not commit secrets. |
| 111 | + |
| 112 | +## Vue 3 Composition API Best Practices |
| 113 | + |
| 114 | +- Use `<script setup lang="ts">` for component logic |
| 115 | +- Utilize `ref` for reactive state |
| 116 | +- Implement computed properties with computed() |
| 117 | +- Use watch and watchEffect for side effects |
| 118 | + - Avoid using a `ref` and a `watch` if a `computed` would work instead |
| 119 | +- Implement lifecycle hooks with onMounted, onUpdated, etc. |
| 120 | +- Utilize provide/inject for dependency injection |
| 121 | + - Do not use dependency injection if a Store or a shared composable would be simpler |
| 122 | +- Use Vue 3.5 TypeScript style of default prop declaration |
| 123 | + - Example: |
| 124 | + |
| 125 | + ```typescript |
| 126 | + const { nodes, showTotal = true } = defineProps<{ |
| 127 | + nodes: ApiNodeCost[] |
| 128 | + showTotal?: boolean |
| 129 | + }>() |
| 130 | + ``` |
| 131 | + |
| 132 | + - Do not use `withDefaults` or runtime props declaration |
| 133 | + - Do not import Vue macros unnecessarily |
| 134 | + - Prefer `useModel` to separately defining a prop and emit |
| 135 | + - Be judicious with addition of new refs or other state |
| 136 | + - If it's possible to accomplish the design goals with just a prop, don't add a `ref` |
| 137 | + - If it's possible to use the `ref` or prop directly, don't add a `computed` |
| 138 | + - If it's possible to use a `computed` to name and reuse a derived value, don't use a `watch` |
| 139 | + |
| 140 | +## Development Guidelines |
| 141 | + |
| 142 | +1. Leverage VueUse functions for performance-enhancing styles |
| 143 | +2. Use es-toolkit for utility functions |
| 144 | +3. Use TypeScript for type safety |
| 145 | +4. Implement proper props and emits definitions |
| 146 | +5. Utilize Vue 3's Teleport component when needed |
| 147 | +6. Use Suspense for async components |
| 148 | +7. Implement proper error handling |
| 149 | +8. Follow Vue 3 style guide and naming conventions |
| 150 | +9. Use Vite for fast development and building |
| 151 | +10. Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json |
| 152 | +11. Avoid new usage of PrimeVue components |
| 153 | + |
| 154 | +## External Resources |
| 155 | + |
| 156 | +- Vue: <https://vuejs.org/api/> |
| 157 | +- Tailwind: <https://tailwindcss.com/docs/styling-with-utility-classes> |
| 158 | +- shadcn/vue: <https://www.shadcn-vue.com/> |
| 159 | +- Reka UI: <https://reka-ui.com/> |
| 160 | +- PrimeVue: <https://primevue.org> |
| 161 | +- ComfyUI: <https://docs.comfy.org> |
| 162 | +- Electron: <https://www.electronjs.org/docs/latest/> |
| 163 | +- Wiki: <https://deepwiki.com/Comfy-Org/ComfyUI_frontend/1-overview> |
| 164 | + |
| 165 | +## Project Philosophy |
| 166 | + |
| 167 | +- Follow good software engineering principles |
| 168 | + - YAGNI |
| 169 | + - AHA |
| 170 | + - DRY |
| 171 | + - SOLID |
| 172 | +- Clean, stable public APIs |
| 173 | +- Domain-driven design |
| 174 | +- Thousands of users and extensions |
| 175 | +- Prioritize clean interfaces that restrict extension access |
| 176 | + |
| 177 | +## Repository Navigation |
| 178 | + |
| 179 | +- Check README files in key folders (tests-ui, browser_tests, composables, etc.) |
| 180 | +- Prefer running single tests for performance |
| 181 | +- Use --help for unfamiliar CLI tools |
| 182 | + |
| 183 | +## GitHub Integration |
| 184 | + |
| 185 | +When referencing Comfy-Org repos: |
| 186 | + |
| 187 | +1. Check for local copy |
| 188 | +2. Use GitHub API for branches/PRs/metadata |
| 189 | +3. Curl GitHub website if needed |
| 190 | + |
| 191 | +## Settings and Feature Flags Quick Reference |
| 192 | + |
| 193 | +### Settings Usage |
| 194 | + |
| 195 | +```typescript |
| 196 | +const settingStore = useSettingStore() |
| 197 | +const value = settingStore.get('Comfy.SomeSetting') // Get setting |
| 198 | +await settingStore.set('Comfy.SomeSetting', newValue) // Update setting |
| 199 | +``` |
| 200 | + |
| 201 | +### Dynamic Defaults |
| 202 | + |
| 203 | +```typescript |
| 204 | +{ |
| 205 | + id: 'Comfy.Example.Setting', |
| 206 | + defaultValue: () => window.innerWidth < 1024 ? 'small' : 'large' // Runtime context |
| 207 | +} |
| 208 | +``` |
| 209 | + |
| 210 | +### Version-Based Defaults |
| 211 | + |
| 212 | +```typescript |
| 213 | +{ |
| 214 | + id: 'Comfy.Example.Feature', |
| 215 | + defaultValue: 'legacy', |
| 216 | + defaultsByInstallVersion: { '1.25.0': 'enhanced' } // Gradual rollout |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +### Feature Flags |
| 221 | + |
| 222 | +```typescript |
| 223 | +if (api.serverSupportsFeature('feature_name')) { // Check capability |
| 224 | + // Use enhanced feature |
| 225 | +} |
| 226 | +const value = api.getServerFeature('config_name', defaultValue) // Get config |
| 227 | +``` |
| 228 | + |
| 229 | +**Documentation:** |
| 230 | + |
| 231 | +- Settings system: `docs/SETTINGS.md` |
| 232 | +- Feature flags system: `docs/FEATURE_FLAGS.md` |
| 233 | + |
| 234 | +## Common Pitfalls |
| 235 | + |
| 236 | +- NEVER use `any` type - use proper TypeScript types |
| 237 | +- NEVER use `as any` type assertions - fix the underlying type issue |
| 238 | +- NEVER use `--no-verify` flag when committing |
| 239 | +- NEVER delete or disable tests to make them pass |
| 240 | +- NEVER circumvent quality checks |
| 241 | +- NEVER use `dark:` or `dark-theme:` tailwind variants. Instead use a semantic value from the `style.css` theme, e.g. `bg-node-component-surface` |
| 242 | +- NEVER use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'`, for example: `<div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />` |
0 commit comments