|
| 1 | +# massCode AI Coding Guidelines |
| 2 | + |
| 3 | +You are an expert Senior Frontend Developer specializing in Electron, Vue 3, and TypeScript. |
| 4 | +Follow these rules strictly when generating code for massCode. |
| 5 | + |
| 6 | +## 1. Core Stack |
| 7 | + |
| 8 | +- **Framework:** Vue 3 (Composition API, `<script setup lang="ts">`) |
| 9 | +- **Styling:** TailwindCSS v4 (`@tailwindcss/vite`), `tailwind-merge`, `cva` |
| 10 | +- **UI:** Custom components (`src/renderer/components/ui`), Shadcn (based on `radix-vue`), `lucide-vue-next` icons |
| 11 | +- **State:** Vue Composables (No Vuex/Pinia) |
| 12 | +- **Backend:** Electron (Main), `better-sqlite3` (DB), Elysia.js (API) |
| 13 | +- **Utilities:** `@vueuse/core`, `vue-sonner` (Notifications) |
| 14 | + |
| 15 | +## 2. Architecture & Communication |
| 16 | + |
| 17 | +**Strict Separation of Concerns:** |
| 18 | + |
| 19 | +| Layer | Process | Access | Communication | |
| 20 | +|:-------------|:---------|:--------------------------------------------|:------------------------------------------| |
| 21 | +| **Renderer** | Frontend | **NO** Node.js/DB access. Only via API/IPC. | Calls API (`api.*`) or IPC (`ipc.invoke`) | |
| 22 | +| **API** | Main | Full DB/System access. | Receives requests from Renderer | |
| 23 | +| **Main** | Backend | Full System access. | Handles IPC & Lifecycle | |
| 24 | + |
| 25 | +**Data Flow:** Renderer → REST API (Elysia) → Service/DB Layer → Response |
| 26 | + |
| 27 | +## 3. Critical Rules & Conventions |
| 28 | + |
| 29 | +### A. Imports (STRICT) |
| 30 | + |
| 31 | +**❌ DO NOT IMPORT:** |
| 32 | + |
| 33 | +- Vue core (`ref`, `computed`, `watch`, `onMounted`) → *Auto-imported* |
| 34 | +- Project components (`src/renderer/components/`) → *Auto-imported* (e.g., `<SidebarFolders />` for `components/sidebar/Folders.vue`) |
| 35 | + |
| 36 | +**✅ ALWAYS IMPORT MANUALLY:** |
| 37 | + |
| 38 | +- Shadcn UI: `import * as Select from '@/components/ui/shadcn/select'` |
| 39 | +- Composables: `import { useApp } from '@/composables'` |
| 40 | +- Utils: `import { cn } from '@/utils'` |
| 41 | +- VueUse: `import { useClipboard } from '@vueuse/core'` |
| 42 | +- Electron IPC/Store: `import { ipc, store } from '@/electron'` |
| 43 | + |
| 44 | +### B. State & Settings |
| 45 | + |
| 46 | +- **Global State:** Composables in `@/composables` (e.g., `useApp`, `useSnippets`) maintain shared state by defining reactive variables **outside** the exported function (module level). This ensures all components access the same state. **No Pinia/Vuex.** |
| 47 | +- **Persistent Settings:** Use `store` from '@/electron'. |
| 48 | + - `store.app`: UI state (sizes, visibility) |
| 49 | + - `store.preferences`: User prefs (theme, language) |
| 50 | + |
| 51 | +### C. Database & API |
| 52 | + |
| 53 | +- **Renderer:** **NEVER** import `better-sqlite3`. Use `import { api } from '~/renderer/services/api'` |
| 54 | +- **New Endpoints:** |
| 55 | + 1. Define DTO in `src/main/api/dto/` |
| 56 | + 2. Add route in `src/main/api/routes/` |
| 57 | + 3. **Run `pnpm api:generate`** to update client. |
| 58 | + |
| 59 | +### D. System & IPC |
| 60 | + |
| 61 | +- **File System/System Ops:** Use `ipc.invoke('channel:action', data)`. |
| 62 | +- **Channels:** `fs:*`, `system:*`, `db:*`, `main-menu:*`, `prettier:*`. |
| 63 | +- **Renderer:** Access Electron only via `src/renderer/electron.ts`. |
| 64 | + |
| 65 | +### E. Localization |
| 66 | + |
| 67 | +- **Primary Language:** English (EN) is the base language. All new keys **MUST** be added to `src/main/i18n/locales/en_US/` first. |
| 68 | +- **Strictly No Hardcoding:** Never use hardcoded strings in templates or logic. Always use the localization system. |
| 69 | +- **Usage:** Use `i18n.t('namespace:key.path')` in both templates and scripts. |
| 70 | +- **Default Namespace:** The `ui` namespace is the default. You can use `i18n.t('key.path')` instead of `i18n.t('ui:key.path')`. |
| 71 | +- **Imports:** `import { i18n } from '@/electron'` |
| 72 | + |
| 73 | +## 4. UI/UX Guidelines |
| 74 | + |
| 75 | +- **Variants:** Use `cva` for component variants. |
| 76 | +- **Classes:** Use `cn()` to merge Tailwind classes. |
| 77 | +- **Notifications:** Use `useSonner()` composable. |
| 78 | +- **Utilities / Composables:** |
| 79 | + - **Check `@vueuse/core` first.** Most common logic (clipboard, events, sensors) is already implemented. |
| 80 | + - **Only** create custom composables if no suitable VueUse utility exists. |
| 81 | + - Remember to **manually import** them (e.g., `import { useClipboard } from '@vueuse/core'`). |
| 82 | +- **Component Usage (STRICT):** |
| 83 | + - **NEVER** reimplement basic UI elements (buttons, inputs, checkboxes, etc.). |
| 84 | + - **ALWAYS** use existing components from `src/renderer/components/ui/`. |
| 85 | + - **Missing Elements:** If a required UI element does not exist, create it in `src/renderer/components/ui/` first, following established patterns (Tailwind, cva, cn), then use it. |
| 86 | + - **Naming:** They are auto-imported with a `Ui` prefix (e.g., `<UiButton />`, `<UiInput />`, `<UiCheckbox />`). |
| 87 | + |
| 88 | +## 5. Development Workflow & Commands |
| 89 | + |
| 90 | +**Linting (CRITICAL):** |
| 91 | + |
| 92 | +- **ALWAYS** scope lint commands to specific files/dirs. |
| 93 | +- **NEVER** run lint on the whole project during a task. |
| 94 | +- Usage: `pnpm lint <path>` or `pnpm lint:fix <path>` |
| 95 | + |
| 96 | +**Other Commands:** |
| 97 | + |
| 98 | +- `pnpm dev`: Start dev server |
| 99 | +- `pnpm api:generate`: Regenerate API client (required after API changes) |
| 100 | +- `pnpm build`: Build for production |
| 101 | + |
| 102 | +## 6. Code Examples |
| 103 | + |
| 104 | +**Component Setup:** |
| 105 | + |
| 106 | +```html |
| 107 | +<script setup lang="ts"> |
| 108 | +import * as Dialog from '@/components/ui/shadcn/dialog' // Manual import |
| 109 | +import { useSnippets } from '@/composables' // Manual import |
| 110 | +
|
| 111 | +const { snippets } = useSnippets() |
| 112 | +// ref, computed are auto-imported (Vue core) |
| 113 | +</script> |
| 114 | + |
| 115 | +<template> |
| 116 | + <div> |
| 117 | + <!-- Use auto-imported UI component --> |
| 118 | + <UiButton>Click me</UiButton> |
| 119 | + |
| 120 | + <!-- Use Shadcn components with namespace --> |
| 121 | + <Dialog.Dialog> |
| 122 | + <Dialog.DialogTrigger as-child> |
| 123 | + <UiButton variant="outline">Open</UiButton> |
| 124 | + </Dialog.DialogTrigger> |
| 125 | + <Dialog.DialogContent> |
| 126 | + Snippet count: {{ snippets.length }} |
| 127 | + </Dialog.DialogContent> |
| 128 | + </Dialog.Dialog> |
| 129 | + </div> |
| 130 | +</template> |
| 131 | +``` |
| 132 | + |
| 133 | +**Data Fetching (Renderer):** |
| 134 | + |
| 135 | +```typescript |
| 136 | +import { api } from '~/renderer/services/api' |
| 137 | +const { data } = await api.snippets.getSnippets({ folderId: 1 }) |
| 138 | +``` |
| 139 | + |
| 140 | +**IPC Call:** |
| 141 | + |
| 142 | +```typescript |
| 143 | +import { ipc } from '@/electron' |
| 144 | +await ipc.invoke('fs:assets', { buffer, fileName }) |
| 145 | +``` |
| 146 | + |
| 147 | +**Localization:** |
| 148 | + |
| 149 | +```html |
| 150 | +<script setup lang="ts"> |
| 151 | +import { i18n } from '@/electron' |
| 152 | +</script> |
| 153 | + |
| 154 | +<template> |
| 155 | + <div> |
| 156 | + <!-- Using default 'ui' namespace --> |
| 157 | + <p>{{ i18n.t('common.save') }}</p> |
| 158 | + |
| 159 | + <!-- Using specific namespace --> |
| 160 | + <p>{{ i18n.t('messages:snippets.count', { count: 10 }) }}</p> |
| 161 | + </div> |
| 162 | +</template> |
| 163 | +``` |
| 164 | + |
| 165 | +**Creating New API Endpoint (DTO & Route):** |
| 166 | + |
| 167 | +1. **Define DTO** (`src/main/api/dto/snippets.ts`): |
| 168 | + |
| 169 | + ```typescript |
| 170 | + import { t } from 'elysia' |
| 171 | + |
| 172 | + // Define validation schema |
| 173 | + const snippetsDuplicate = t.Object({ |
| 174 | + id: t.Number() |
| 175 | + }) |
| 176 | + |
| 177 | + // Register in main DTO model |
| 178 | + export const snippetsDTO = new Elysia().model({ |
| 179 | + // ... other DTOs |
| 180 | + snippetsDuplicate |
| 181 | + }) |
| 182 | + ``` |
| 183 | + |
| 184 | +2. **Add Route** (`src/main/api/routes/snippets.ts`): |
| 185 | + |
| 186 | + ```typescript |
| 187 | + import { useDB } from '../../db' |
| 188 | + |
| 189 | + app.post('/duplicate', ({ body }) => { |
| 190 | + const db = useDB() |
| 191 | + // Database logic here... |
| 192 | + return { id: newId } |
| 193 | + }, { |
| 194 | + body: 'snippetsDuplicate', // Use registered DTO name |
| 195 | + detail: { tags: ['Snippets'] } |
| 196 | + }) |
| 197 | + ``` |
| 198 | + |
| 199 | +3. **Generate Client:** Run `pnpm api:generate` |
0 commit comments