vibes-plug 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  2. package/BLUEPRINT.md +125 -0
  3. package/CHANGELOG.md +195 -0
  4. package/CONTRIBUTING.md +199 -0
  5. package/LICENSE +21 -0
  6. package/README.md +263 -0
  7. package/SECURITY.md +21 -0
  8. package/banner.png +0 -0
  9. package/package.json +25 -0
  10. package/plugin.json +8 -0
  11. package/scripts/update_skills.js +75 -0
  12. package/skills/ai-llm-integration-expert/SKILL.md +162 -0
  13. package/skills/api-design-expert/SKILL.md +310 -0
  14. package/skills/app-analyzer-optimizer/SKILL.md +189 -0
  15. package/skills/asisten_ramah/SKILL.md +41 -0
  16. package/skills/authentication-identity-expert/SKILL.md +45 -0
  17. package/skills/auto-doc-updater/SKILL.md +204 -0
  18. package/skills/bootstrap-to-modern/SKILL.md +87 -0
  19. package/skills/brainstorming/SKILL.md +353 -0
  20. package/skills/bun-runtime-expert/SKILL.md +211 -0
  21. package/skills/ci-cd-devops-architect/SKILL.md +45 -0
  22. package/skills/cloud-hosting-expert/SKILL.md +244 -0
  23. package/skills/coderabbit/SKILL.md +192 -0
  24. package/skills/data-telemetry-expert/SKILL.md +213 -0
  25. package/skills/database-orm-expert/SKILL.md +294 -0
  26. package/skills/design-system-architect/SKILL.md +243 -0
  27. package/skills/e2e-testing-expert/SKILL.md +315 -0
  28. package/skills/event-driven-architect/SKILL.md +81 -0
  29. package/skills/firebase-security-expert/SKILL.md +195 -0
  30. package/skills/fullstack-expert/SKILL.md +202 -0
  31. package/skills/fullstack-expert/references/api_design_guide.md +466 -0
  32. package/skills/fullstack-expert/references/devops_infrastructure.md +477 -0
  33. package/skills/fullstack-expert/references/multi_language_backend.md +528 -0
  34. package/skills/fullstack-expert/references/system_design_patterns.md +358 -0
  35. package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -0
  36. package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -0
  37. package/skills/gemini-agent-booster/SKILL.md +135 -0
  38. package/skills/global-a11y-i18n-expert/SKILL.md +81 -0
  39. package/skills/go-programming-expert/SKILL.md +295 -0
  40. package/skills/hig/SKILL.md +188 -0
  41. package/skills/js-backend-expert/SKILL.md +192 -0
  42. package/skills/mcp-server-architect/SKILL.md +194 -0
  43. package/skills/mobile-expo-expert/SKILL.md +186 -0
  44. package/skills/monday-design-aesthetic/SKILL.md +67 -0
  45. package/skills/monorepo-architect/SKILL.md +227 -0
  46. package/skills/mpa-orchestrator/SKILL.md +101 -0
  47. package/skills/multi-agent-orchestration/SKILL.md +234 -0
  48. package/skills/multiple-entry-points/SKILL.md +55 -0
  49. package/skills/mvc-expert/SKILL.md +231 -0
  50. package/skills/payment-gateway-expert/SKILL.md +45 -0
  51. package/skills/performance-web-vitals/SKILL.md +332 -0
  52. package/skills/prd-architect/SKILL.md +191 -0
  53. package/skills/production-ready-hardener/SKILL.md +469 -0
  54. package/skills/production-ready-hardener/references/performance_optimization.md +441 -0
  55. package/skills/production-ready-hardener/references/production_checklist.md +161 -0
  56. package/skills/production-ready-hardener/references/security_hardening_guide.md +379 -0
  57. package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +875 -0
  58. package/skills/python-programming-expert/SKILL.md +271 -0
  59. package/skills/realtime-collaboration-expert/SKILL.md +45 -0
  60. package/skills/rust-programming-expert/SKILL.md +235 -0
  61. package/skills/saas-billing/SKILL.md +377 -0
  62. package/skills/saas-multi-tenant/SKILL.md +237 -0
  63. package/skills/saas-mvp-launcher/SKILL.md +231 -0
  64. package/skills/saas-transformer/SKILL.md +446 -0
  65. package/skills/saas-transformer/references/billing_integration_guide.md +401 -0
  66. package/skills/saas-transformer/references/feature_gating_patterns.md +137 -0
  67. package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -0
  68. package/skills/saas-transformer/scripts/saas_transformation_scanner.py +254 -0
  69. package/skills/scalability-clean-code/SKILL.md +229 -0
  70. package/skills/secure-fuzz-testing/SKILL.md +201 -0
  71. package/skills/senior-frontend/SKILL.md +161 -0
  72. package/skills/senior-frontend/references/frontend_best_practices.md +806 -0
  73. package/skills/senior-frontend/references/nextjs_optimization_guide.md +724 -0
  74. package/skills/senior-frontend/references/react_patterns.md +746 -0
  75. package/skills/senior-frontend/scripts/bundle_analyzer.py +407 -0
  76. package/skills/senior-frontend/scripts/component_generator.py +329 -0
  77. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1005 -0
  78. package/skills/senior-fullstack/SKILL.md +167 -0
  79. package/skills/senior-fullstack/references/architecture_patterns.md +160 -0
  80. package/skills/senior-fullstack/references/development_workflows.md +222 -0
  81. package/skills/senior-fullstack/references/tech_stack_guide.md +190 -0
  82. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  83. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  84. package/skills/senior-fullstack/scripts/project_scaffolder.py +114 -0
  85. package/skills/seo/SKILL.md +225 -0
  86. package/skills/seo/references/cwv-thresholds.md +108 -0
  87. package/skills/seo/references/eeat-framework.md +214 -0
  88. package/skills/seo/references/quality-gates.md +155 -0
  89. package/skills/seo/references/schema-types.md +118 -0
  90. package/skills/seo-aeo-landing-page-writer/SKILL.md +97 -0
  91. package/skills/seo-geo/SKILL.md +188 -0
  92. package/skills/session-handoff-resume/SKILL.md +158 -0
  93. package/skills/skill_baru/SKILL.md +147 -0
  94. package/skills/spa-orchestrator/SKILL.md +288 -0
  95. package/skills/state-management-expert/SKILL.md +272 -0
  96. package/skills/supabase-migration/SKILL.md +45 -0
  97. package/skills/supabase-security-expert/SKILL.md +243 -0
  98. package/skills/tailwind-expert/SKILL.md +188 -0
  99. package/skills/tanstack-query-expert/SKILL.md +199 -0
  100. package/skills/tauri-expert/SKILL.md +97 -0
  101. package/skills/token-saver/SKILL.md +111 -0
  102. package/skills/typescript-expert/SKILL.md +279 -0
  103. package/skills/ui-components-expert/SKILL.md +63 -0
  104. package/skills/ui-ux-pro-max/SKILL.md +201 -0
  105. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  106. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  107. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  108. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  109. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  110. package/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  111. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  112. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  113. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  114. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  115. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  116. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  117. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  118. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  119. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  120. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  121. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  122. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  123. package/skills/ui-ux-pro-max/data/styles.csv +59 -0
  124. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  125. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  126. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  127. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  128. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  129. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  130. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  131. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  132. package/skills/ui-ux-pro-max/scripts/core.py +257 -0
  133. package/skills/ui-ux-pro-max/scripts/design_system.py +493 -0
  134. package/skills/ui-ux-pro-max/scripts/search.py +81 -0
  135. package/skills/ui_ux_expert/SKILL.md +114 -0
  136. package/skills/vibe-code-gardener/SKILL.md +173 -0
  137. package/skills/web-scraper/SKILL.md +205 -0
  138. package/skills/web-scraper/references/data-transforms.md +397 -0
  139. package/skills/web-scraper/references/extraction-patterns.md +475 -0
  140. package/skills/web-scraper/references/output-templates.md +481 -0
  141. package/skills/zero-to-prod-orchestrator/SKILL.md +180 -0
@@ -0,0 +1,272 @@
1
+ ---
2
+ name: state-management-expert
3
+ description: "Expert guide for modern client-side state management: Zustand, Jotai, Valtio, TanStack Store, Redux Toolkit, and server state patterns with TanStack Query / Panduan ahli untuk manajemen state client-side modern: Zustand, Jotai, Valtio, TanStack Store, Redux Toolkit, dan pola server state dengan TanStack Query."
4
+ author: "Roedy Rustam"
5
+ ---
6
+
7
+ # State Management Expert (Modern React Edition)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Description
17
+ Expert guide for selecting and implementing the right state management solution for React and Next.js applications. Covers **Zustand 5**, **Jotai 2**, **Valtio**, **TanStack Store**, and **Redux Toolkit 2**, with clear guidance on when to use each, proper separation of server state (TanStack Query) from client state, and advanced patterns like slices, persistence, and devtools integration.
18
+
19
+ ### Trigger Conditions
20
+ - Choosing a state management library for a new React/Next.js project.
21
+ - Refactoring prop drilling or complex Context API usage.
22
+ - Implementing global UI state (modals, drawers, theme, auth session).
23
+ - Managing complex form state across multiple steps.
24
+ - Implementing undo/redo, optimistic updates, or derived state.
25
+ - Migrating from Redux to a lighter alternative.
26
+
27
+ ---
28
+
29
+ ### State Category Separation (Critical First Step)
30
+
31
+ Before choosing a library, categorize your state:
32
+
33
+ | Category | Description | Solution |
34
+ |---|---|---|
35
+ | **Server State** | Data from APIs, databases | TanStack Query / SWR |
36
+ | **URL State** | Route params, search filters | `useSearchParams`, nuqs |
37
+ | **Form State** | Input values, validation errors | React Hook Form + Zod |
38
+ | **UI/Local State** | Modals, drawers, toggles | `useState` / `useReducer` |
39
+ | **Global Client State** | Theme, auth, shopping cart | Zustand / Jotai |
40
+ | **Cross-tab State** | Sync across browser tabs | Zustand + BroadcastChannel |
41
+
42
+ **Rule**: Do NOT store server data in client state. Let TanStack Query own all async data.
43
+
44
+ ---
45
+
46
+ ### Library Selection Guide
47
+
48
+ | Criteria | Zustand 5 | Jotai 2 | Valtio | Redux Toolkit |
49
+ |---|---|---|---|---|
50
+ | **Mental Model** | Single store, actions | Atomic, bottom-up | Proxy-based, mutable | Flux, reducers |
51
+ | **Bundle Size** | ~1KB | ~3KB | ~3KB | ~15KB+ |
52
+ | **DevTools** | Redux DevTools | Jotai DevTools | Redux DevTools | Built-in |
53
+ | **Async** | Manual or middleware | `atomWithQuery` | `snapshot` | `createAsyncThunk` |
54
+ | **Best For** | General global state | Atomic derived state | Simple mutable state | Large teams, strict patterns |
55
+
56
+ **Recommendation**: Use **Zustand** as the default. Use **Jotai** for fine-grained reactive atoms. Use **Redux Toolkit** only for large enterprise teams with strict conventions.
57
+
58
+ ---
59
+
60
+ ### Zustand 5 — Best Practices
61
+
62
+ #### Basic Store with TypeScript
63
+ ```typescript
64
+ // stores/ui.store.ts
65
+ import { create } from 'zustand';
66
+ import { devtools, persist, subscribeWithSelector } from 'zustand/middleware';
67
+ import { immer } from 'zustand/middleware/immer';
68
+
69
+ interface UiState {
70
+ theme: 'light' | 'dark' | 'system';
71
+ sidebarOpen: boolean;
72
+ activeModal: string | null;
73
+ setTheme: (theme: UiState['theme']) => void;
74
+ toggleSidebar: () => void;
75
+ openModal: (modalId: string) => void;
76
+ closeModal: () => void;
77
+ }
78
+
79
+ export const useUiStore = create<UiState>()(
80
+ devtools(
81
+ persist(
82
+ subscribeWithSelector(
83
+ immer((set) => ({
84
+ theme: 'system',
85
+ sidebarOpen: true,
86
+ activeModal: null,
87
+ setTheme: (theme) => set((state) => { state.theme = theme; }),
88
+ toggleSidebar: () => set((state) => { state.sidebarOpen = !state.sidebarOpen; }),
89
+ openModal: (modalId) => set((state) => { state.activeModal = modalId; }),
90
+ closeModal: () => set((state) => { state.activeModal = null; }),
91
+ }))
92
+ ),
93
+ { name: 'ui-store', partialize: (s) => ({ theme: s.theme }) }
94
+ ),
95
+ { name: 'UiStore' }
96
+ )
97
+ );
98
+ ```
99
+
100
+ #### Slice Pattern for Large Stores
101
+ ```typescript
102
+ // Pattern: separate slices, combine into one store
103
+ import { StateCreator } from 'zustand';
104
+
105
+ interface AuthSlice {
106
+ user: User | null;
107
+ isAuthenticated: boolean;
108
+ login: (user: User) => void;
109
+ logout: () => void;
110
+ }
111
+
112
+ interface CartSlice {
113
+ items: CartItem[];
114
+ addItem: (item: CartItem) => void;
115
+ removeItem: (id: string) => void;
116
+ total: () => number;
117
+ }
118
+
119
+ type AppStore = AuthSlice & CartSlice;
120
+
121
+ const createAuthSlice: StateCreator<AppStore, [], [], AuthSlice> = (set) => ({
122
+ user: null,
123
+ isAuthenticated: false,
124
+ login: (user) => set({ user, isAuthenticated: true }),
125
+ logout: () => set({ user: null, isAuthenticated: false }),
126
+ });
127
+
128
+ const createCartSlice: StateCreator<AppStore, [], [], CartSlice> = (set, get) => ({
129
+ items: [],
130
+ addItem: (item) => set((s) => ({ items: [...s.items, item] })),
131
+ removeItem: (id) => set((s) => ({ items: s.items.filter((i) => i.id !== id) })),
132
+ total: () => get().items.reduce((sum, item) => sum + item.price * item.qty, 0),
133
+ });
134
+
135
+ export const useAppStore = create<AppStore>()(
136
+ devtools((...args) => ({
137
+ ...createAuthSlice(...args),
138
+ ...createCartSlice(...args),
139
+ }))
140
+ );
141
+ ```
142
+
143
+ #### Selective Subscriptions (Prevent Unnecessary Rerenders)
144
+ ```typescript
145
+ // Only re-render when `theme` changes, not the entire store
146
+ const theme = useUiStore((s) => s.theme);
147
+ const isModalOpen = useUiStore((s) => s.activeModal === 'confirm-delete');
148
+
149
+ // Subscribe outside React (side effects, non-component code)
150
+ useUiStore.subscribe(
151
+ (s) => s.theme,
152
+ (theme) => document.documentElement.dataset.theme = theme,
153
+ { fireImmediately: true }
154
+ );
155
+ ```
156
+
157
+ ---
158
+
159
+ ### Jotai 2 — Atomic State Patterns
160
+
161
+ ```typescript
162
+ // atoms/user.atoms.ts
163
+ import { atom, loadable } from 'jotai';
164
+ import { atomWithStorage, atomWithReset } from 'jotai/utils';
165
+
166
+ // Primitive atom
167
+ export const themeAtom = atomWithStorage<'light' | 'dark'>('theme', 'light');
168
+
169
+ // Derived (read-only) atom
170
+ export const isDarkAtom = atom((get) => get(themeAtom) === 'dark');
171
+
172
+ // Async atom with loadable for Suspense-free usage
173
+ export const userAtom = atom(async () => {
174
+ const res = await fetch('/api/me');
175
+ if (!res.ok) throw new Error('Failed to fetch user');
176
+ return res.json() as Promise<User>;
177
+ });
178
+
179
+ export const loadableUserAtom = loadable(userAtom);
180
+
181
+ // In component:
182
+ function UserWidget() {
183
+ const loadableUser = useAtomValue(loadableUserAtom);
184
+ if (loadableUser.state === 'loading') return <Spinner />;
185
+ if (loadableUser.state === 'hasError') return <Error />;
186
+ return <div>{loadableUser.data.name}</div>;
187
+ }
188
+ ```
189
+
190
+ ---
191
+
192
+ ### Redux Toolkit 2 — Modern Patterns
193
+
194
+ ```typescript
195
+ // features/cart/cartSlice.ts
196
+ import { createSlice, PayloadAction, createSelector } from '@reduxjs/toolkit';
197
+
198
+ interface CartState {
199
+ items: CartItem[];
200
+ status: 'idle' | 'loading' | 'failed';
201
+ }
202
+
203
+ const cartSlice = createSlice({
204
+ name: 'cart',
205
+ initialState: { items: [], status: 'idle' } as CartState,
206
+ reducers: {
207
+ addItem(state, action: PayloadAction<CartItem>) {
208
+ state.items.push(action.payload); // Immer handles immutability
209
+ },
210
+ removeItem(state, action: PayloadAction<string>) {
211
+ state.items = state.items.filter((i) => i.id !== action.payload);
212
+ },
213
+ },
214
+ });
215
+
216
+ // Memoized selector
217
+ export const selectCartTotal = createSelector(
218
+ (state: RootState) => state.cart.items,
219
+ (items) => items.reduce((sum, i) => sum + i.price * i.qty, 0)
220
+ );
221
+
222
+ export const { addItem, removeItem } = cartSlice.actions;
223
+ export default cartSlice.reducer;
224
+ ```
225
+
226
+ ---
227
+
228
+ ### Integration with Next.js App Router
229
+
230
+ - **Server Components**: No client state. Fetch directly.
231
+ - **Client Components**: Use Zustand/Jotai wrapped in providers.
232
+ - **Hydration**: Initialize Zustand store from server-fetched data using `useHydrateAtoms` (Jotai) or a `HydrationBoundary` pattern.
233
+
234
+ ```typescript
235
+ // providers/store-provider.tsx (App Router pattern)
236
+ 'use client';
237
+ import { createStore, Provider } from 'jotai';
238
+ import { useRef } from 'react';
239
+
240
+ type Props = { children: React.ReactNode; initialUser?: User };
241
+
242
+ export function StoreProvider({ children, initialUser }: Props) {
243
+ const store = useRef(createStore());
244
+ if (initialUser) store.current.set(userAtom, initialUser);
245
+ return <Provider store={store.current}>{children}</Provider>;
246
+ }
247
+ ```
248
+
249
+ ---
250
+
251
+ <a name="bahasa-indonesia"></a>
252
+ ## Bahasa Indonesia
253
+
254
+ ### Deskripsi
255
+ Panduan ahli untuk memilih dan mengimplementasikan solusi manajemen state yang tepat untuk aplikasi React dan Next.js. Mencakup **Zustand 5**, **Jotai 2**, **Valtio**, dan **Redux Toolkit 2**, dengan panduan pemilihan yang jelas, pemisahan server state (TanStack Query) dari client state, dan pola lanjutan seperti slices, persistensi, dan integrasi devtools.
256
+
257
+ ### Kondisi Pemicu
258
+ - Memilih library state management untuk proyek React/Next.js baru.
259
+ - Refaktor prop drilling atau penggunaan Context API yang rumit.
260
+ - Mengimplementasikan global UI state (modal, drawer, tema, sesi auth).
261
+ - Mengelola state form kompleks di beberapa langkah.
262
+ - Mengimplementasikan undo/redo, optimistic update, atau derived state.
263
+ - Migrasi dari Redux ke alternatif yang lebih ringan.
264
+
265
+ ### Prinsip Utama
266
+
267
+ - **Pisahkan server state dari client state**: Server state (data dari API) dikelola TanStack Query. Client state (UI, preferensi) dikelola Zustand/Jotai.
268
+ - **Gunakan Zustand sebagai default** untuk state global umum.
269
+ - **Gunakan Jotai** untuk state atomik yang sangat granular dan reaktif.
270
+ - **Hindari menyimpan data server di client state** — ini adalah sumber bug terbesar di aplikasi React.
271
+ - **Selective subscription**: Selalu gunakan selector untuk menghindari re-render yang tidak perlu.
272
+ - **DevTools**: Selalu integrasikan devtools di development untuk debugging yang efektif.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: supabase-migration
3
+ description: "A skill to create or apply a Supabase database migration / Kemampuan untuk membuat atau menerapkan migrasi database Supabase."
4
+ author: "Roedy Rustam"
5
+ ---
6
+
7
+ # Supabase Migration Skill
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Description
17
+ When the user asks to create or apply a database migration for Supabase, follow these instructions:
18
+
19
+ ### Instructions
20
+ 1. **Check Environment**: Ensure `supabase/migrations` directory exists. Run `list_dir` on it if needed.
21
+ 2. **Review Available MCP Commands**: Utilize the Supabase MCP integration.
22
+ - For listing existing migrations, use `mcp_supabase-mcp-server_list_migrations` with `project_id`.
23
+ - Before executing migration queries on the server directly, confirm the SQL is correct.
24
+ 3. **Execute Command**:
25
+ - Write the SQL script to a local migration file located in `supabase/migrations/` using `write_to_file`. Use standard timestamps or `supabase migration new` command to get the filename.
26
+ - Run `npx supabase migration up` to test locally or use the remote MCP `apply_migration` if the user wants it applied remotely.
27
+ 4. **Final Step**: Confirm with the user that the migration successfully completed.
28
+
29
+ ---
30
+
31
+ <a name="bahasa-indonesia"></a>
32
+ ## Bahasa Indonesia
33
+
34
+ ### Deskripsi
35
+ Ketika pengguna meminta untuk membuat atau menerapkan migrasi database untuk Supabase, ikuti instruksi berikut:
36
+
37
+ ### Instruksi
38
+ 1. **Periksa Lingkungan**: Pastikan direktori `supabase/migrations` ada. Jalankan `list_dir` jika diperlukan.
39
+ 2. **Tinjau Perintah MCP yang Tersedia**: Manfaatkan integrasi Supabase MCP.
40
+ - Untuk mencantumkan migrasi yang ada, gunakan `mcp_supabase-mcp-server_list_migrations` dengan `project_id`.
41
+ - Sebelum menjalankan kueri migrasi di server secara langsung, pastikan kode SQL-nya sudah benar.
42
+ 3. **Jalankan Perintah**:
43
+ - Tulis skrip SQL ke file migrasi lokal yang terletak di `supabase/migrations/` menggunakan `write_to_file`. Gunakan timestamp standar atau perintah `supabase migration new` untuk mendapatkan nama file.
44
+ - Jalankan `npx supabase migration up` untuk menguji secara lokal atau gunakan MCP remote `apply_migration` jika pengguna ingin menerapkannya secara remote.
45
+ 4. **Langkah Terakhir**: Konfirmasikan dengan pengguna bahwa migrasi telah berhasil diselesaikan.
@@ -0,0 +1,243 @@
1
+ ---
2
+ name: supabase-security-expert
3
+ description: "Supabase security expert to audit RLS (Row Level Security), RBAC, relational databases, prevent data leakage, and utilize Supabase Linter / Ahli keamanan Supabase untuk audit RLS (Row Level Security), RBAC, database relasional, pencegahan kebocoran data, dan pemanfaatan Supabase Linter."
4
+ author: "Roedy Rustam"
5
+ ---
6
+
7
+ # Supabase Security Expert (2026 Edition — Auth v3 / PKCE)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Description
17
+ Expert guide for auditing and hardening Supabase applications. Covers Row Level Security (RLS), Supabase Auth v3 (PKCE flow), API key hygiene, data leakage prevention, Supabase Linter, and production security checklists.
18
+
19
+ ### Trigger Conditions
20
+ - Auditing RLS policies for correctness and security gaps.
21
+ - Setting up Supabase Auth v3 with PKCE flow (replaces implicit flow).
22
+ - Reviewing API key usage (anon key vs. service role key).
23
+ - Preventing data leakage from misconfigured policies.
24
+ - Running Supabase Linter (`supabase lint`) for automated security checks.
25
+ - Implementing user roles and access control in a Supabase project.
26
+
27
+ ### Supabase Auth v3 — PKCE Flow (2026 Default)
28
+
29
+ Supabase Auth v3 now uses **PKCE (Proof Key for Code Exchange)** as the default flow for all OAuth and magic link authentication — replacing the older implicit flow:
30
+
31
+ ```typescript
32
+ // supabase/client.ts — v3 client setup
33
+ import { createBrowserClient } from '@supabase/ssr';
34
+
35
+ export const supabase = createBrowserClient(
36
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
37
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
38
+ {
39
+ auth: {
40
+ flowType: 'pkce', // Default in Auth v3
41
+ autoRefreshToken: true,
42
+ persistSession: true,
43
+ detectSessionInUrl: true,
44
+ }
45
+ }
46
+ );
47
+ ```
48
+
49
+ ```typescript
50
+ // Server-side session handling (Next.js App Router)
51
+ import { createServerClient } from '@supabase/ssr';
52
+ import { cookies } from 'next/headers';
53
+
54
+ export async function createSupabaseServerClient() {
55
+ const cookieStore = await cookies();
56
+ return createServerClient(
57
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
58
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
59
+ {
60
+ cookies: {
61
+ getAll: () => cookieStore.getAll(),
62
+ setAll: (cookiesToSet) => {
63
+ cookiesToSet.forEach(({ name, value, options }) =>
64
+ cookieStore.set(name, value, options)
65
+ );
66
+ },
67
+ },
68
+ }
69
+ );
70
+ }
71
+ ```
72
+
73
+ ### API Key Security
74
+
75
+ | Key Type | Purpose | Where to Use |
76
+ |---|---|---|
77
+ | `anon` key | Public client access — restricted by RLS | Frontend (browser) |
78
+ | `service_role` key | Bypasses ALL RLS | Backend only (server) |
79
+
80
+ > ⚠️ **NEVER** expose `service_role` key to the frontend. If it leaks, an attacker can read/write all data in your database, bypassing RLS completely.
81
+
82
+ ```typescript
83
+ // ✅ CORRECT: service_role used only in server-side code
84
+ // app/api/admin/route.ts (only accessible at admin.domain.com)
85
+ import { createClient } from '@supabase/supabase-js';
86
+
87
+ const adminClient = createClient(
88
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
89
+ process.env.SUPABASE_SERVICE_ROLE_KEY!, // NOT exposed to client
90
+ );
91
+
92
+ // 🔴 WRONG: service_role in client-side code
93
+ const publicClient = createBrowserClient(url, process.env.SUPABASE_SERVICE_ROLE_KEY!);
94
+ ```
95
+
96
+ ### RLS Policy Audit Checklist
97
+
98
+ #### Common RLS Mistakes
99
+ ```sql
100
+ -- 🔴 INSECURE: auth.uid() is not validated — returns null if not authenticated
101
+ CREATE POLICY "users can see own data" ON profiles
102
+ FOR SELECT USING (user_id = auth.uid());
103
+ -- If user is unauthenticated, auth.uid() returns null, which means
104
+ -- NULL = NULL is NULL (falsy in SQL) — so this IS secure... but next one isn't:
105
+
106
+ -- 🔴 DANGEROUS: Using 'true' without auth check
107
+ CREATE POLICY "all can read" ON public_posts
108
+ FOR SELECT USING (true); -- Anyone, including anonymous, can read
109
+
110
+ -- ✅ SECURE: Explicit authentication requirement
111
+ CREATE POLICY "only authenticated users can read" ON sensitive_data
112
+ FOR SELECT USING (auth.role() = 'authenticated');
113
+
114
+ -- ✅ SECURE: Workspace isolation with auth check
115
+ CREATE POLICY "workspace isolation" ON projects
116
+ FOR ALL USING (
117
+ workspace_id IN (
118
+ SELECT workspace_id FROM workspace_members
119
+ WHERE user_id = auth.uid()
120
+ )
121
+ );
122
+ ```
123
+
124
+ #### RLS Audit SQL Queries
125
+ ```sql
126
+ -- Find tables WITHOUT RLS enabled
127
+ SELECT schemaname, tablename
128
+ FROM pg_tables
129
+ WHERE schemaname = 'public'
130
+ AND tablename NOT IN (
131
+ SELECT tablename FROM pg_policies WHERE schemaname = 'public'
132
+ );
133
+
134
+ -- Find tables with RLS enabled but NO policies (effectively blocks all access)
135
+ SELECT c.relname AS table_name, c.relrowsecurity AS rls_enabled
136
+ FROM pg_class c
137
+ JOIN pg_namespace n ON n.oid = c.relnamespace
138
+ WHERE n.nspname = 'public'
139
+ AND c.relkind = 'r'
140
+ AND c.relrowsecurity = true
141
+ AND NOT EXISTS (
142
+ SELECT 1 FROM pg_policies p
143
+ WHERE p.tablename = c.relname AND p.schemaname = n.nspname
144
+ );
145
+ ```
146
+
147
+ ### Supabase Linter
148
+ Run automated security checks:
149
+ ```bash
150
+ # Install Supabase CLI
151
+ npm install -g supabase
152
+
153
+ # Run the linter against your project
154
+ supabase db lint --project-id <your-project-id>
155
+
156
+ # Common lint checks:
157
+ # - Tables with RLS disabled
158
+ # - Policies using mutable functions (NOW(), RANDOM())
159
+ # - Security definer functions without search_path
160
+ # - Auth functions used incorrectly
161
+ ```
162
+
163
+ ### Storage Security
164
+ ```typescript
165
+ // Create a private storage bucket (files not publicly accessible by URL)
166
+ const { data, error } = await supabase.storage.createBucket('user-uploads', {
167
+ public: false, // Private — requires signed URLs
168
+ fileSizeLimit: 10 * 1024 * 1024, // 10MB
169
+ allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf'],
170
+ });
171
+
172
+ // Generate a signed URL (expires in 1 hour)
173
+ const { data: { signedUrl } } = await supabase.storage
174
+ .from('user-uploads')
175
+ .createSignedUrl(`${userId}/${filename}`, 3600);
176
+ ```
177
+
178
+ ```sql
179
+ -- Storage RLS: users can only access their own files
180
+ CREATE POLICY "users can manage own files"
181
+ ON storage.objects FOR ALL
182
+ USING (bucket_id = 'user-uploads' AND auth.uid()::text = (storage.foldername(name))[1]);
183
+ ```
184
+
185
+ ### Production Security Checklist
186
+ - [ ] All tables in `public` schema have RLS enabled.
187
+ - [ ] `service_role` key is only in server-side environment variables.
188
+ - [ ] PKCE flow enabled (`flowType: 'pkce'`) in Auth v3 client.
189
+ - [ ] Storage buckets are private by default.
190
+ - [ ] JWT expiry set appropriately (recommended: 1 hour + refresh tokens).
191
+ - [ ] Email confirmations required for new signups.
192
+ - [ ] Supabase Linter (`supabase db lint`) passes with no critical issues.
193
+ - [ ] MFA (Multi-Factor Authentication) enabled for admin users.
194
+ - [ ] Realtime subscriptions restricted — filter by authenticated user.
195
+ - [ ] Custom `auth.uid()` policies tested with anonymous/different user sessions.
196
+
197
+ ---
198
+
199
+ <a name="bahasa-indonesia"></a>
200
+ ## Bahasa Indonesia
201
+
202
+ ### Deskripsi
203
+ Panduan ahli untuk mengaudit dan mengeraskan aplikasi Supabase. Mencakup Row Level Security (RLS), Supabase Auth v3 (PKCE flow), kebersihan API key, pencegahan kebocoran data, Supabase Linter, dan checklist keamanan produksi.
204
+
205
+ ### Kondisi Pemicu
206
+ - Mengaudit kebijakan RLS untuk kebenaran dan celah keamanan.
207
+ - Menyiapkan Supabase Auth v3 dengan PKCE flow (menggantikan implicit flow).
208
+ - Meninjau penggunaan API key (anon key vs. service role key).
209
+ - Mencegah kebocoran data dari kebijakan yang salah konfigurasi.
210
+ - Menjalankan Supabase Linter untuk pemeriksaan keamanan otomatis.
211
+
212
+ ### Supabase Auth v3 — PKCE Flow (Default 2026)
213
+
214
+ Supabase Auth v3 menggunakan **PKCE** sebagai alur default untuk semua OAuth dan magic link — menggantikan implicit flow yang lama. Konfigurasikan dengan `flowType: 'pkce'` di klien browser dan gunakan `@supabase/ssr` untuk penanganan sesi sisi server di Next.js App Router.
215
+
216
+ ### Keamanan API Key
217
+
218
+ | Tipe Key | Tujuan | Tempat Penggunaan |
219
+ |---|---|---|
220
+ | `anon` key | Akses klien publik — dibatasi RLS | Frontend (browser) |
221
+ | `service_role` key | Melewati SEMUA RLS | Hanya backend (server) |
222
+
223
+ > ⚠️ **JANGAN PERNAH** mengekspos `service_role` key ke frontend. Jika bocor, penyerang dapat membaca/menulis semua data di database Anda, melewati RLS sepenuhnya.
224
+
225
+ ### Audit Kebijakan RLS
226
+
227
+ Kesalahan RLS umum: menggunakan `USING (true)` tanpa pemeriksaan autentikasi (siapa saja, termasuk anonim, dapat membaca). Selalu verifikasi dengan `auth.role() = 'authenticated'` atau cek `auth.uid()` eksplisit.
228
+
229
+ Gunakan query audit SQL untuk menemukan tabel tanpa RLS dan tabel dengan RLS aktif tetapi tanpa kebijakan (memblokir semua akses).
230
+
231
+ ### Supabase Linter
232
+ Jalankan `supabase db lint` untuk pemeriksaan keamanan otomatis: tabel dengan RLS dinonaktifkan, kebijakan menggunakan fungsi yang dapat dimutasi, fungsi security definer tanpa `search_path`.
233
+
234
+ ### Keamanan Storage
235
+ Buat bucket penyimpanan privat (`public: false`) dengan batasan ukuran file dan tipe MIME yang diizinkan. Gunakan URL bertanda tangan (signed URL) untuk memberikan akses sementara ke file privat. Terapkan RLS di `storage.objects` untuk memastikan pengguna hanya dapat mengakses file mereka sendiri.
236
+
237
+ ### Checklist Keamanan Produksi
238
+ - Semua tabel di schema `public` mengaktifkan RLS.
239
+ - `service_role` key hanya di variabel lingkungan sisi server.
240
+ - PKCE flow diaktifkan di klien Auth v3.
241
+ - Bucket storage privat secara default.
242
+ - Supabase Linter tidak ada isu kritis.
243
+ - MFA diaktifkan untuk pengguna admin.