← Back to list

migestion-web
by eduardbar
Multi-tenant SaaS CRM for local businesses
⭐ 0🍴 0📅 Jan 22, 2026
SKILL.md
name: migestion-web description: > Frontend patterns for MiGestion Web - React, Vite, Zustand, design system. Trigger: When working on Web code (components, pages, stores, services). license: MIT metadata: author: migestion version: '1.0' scope: [web] auto_invoke: 'Creating new React components/pages' allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
File Structure
src/
├── components/
│ └── ui/ # Reusable UI components (Button, Input, etc.)
├── pages/ # Feature pages (ClientsPage, DashboardPage, etc.)
│ └── example/
│ ├── ExamplePage.tsx
│ └── index.ts # Barrel export
├── services/ # API service functions
├── stores/ # Zustand state stores
├── contexts/ # React contexts (Socket, etc.)
├── hooks/ # Custom hooks (useAuth, etc.)
├── lib/ # Utilities (cn, constants)
└── types/ # Shared TypeScript types
Component Pattern
// ✅ ALWAYS: Named exports
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = 'primary', size = 'md', children, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(baseStyles, variantStyles[variant], sizeStyles[size])}
{...props}
>
{children}
</button>
);
}
);
Button.displayName = 'Button';
// ❌ NEVER: Default export (except pages)
export default function Page() { } // OK for pages only
Page Pattern
Pages are default exports in feature folders.
// pages/example/ExamplePage.tsx
export default function ExamplePage() {
return <div>Example Page</div>;
}
// pages/example/index.ts
export { default } from './ExamplePage';
Zustand Store Pattern
import { create } from 'zustand';
interface ExampleState {
// State
items: Item[];
isLoading: boolean;
error: string | null;
// Actions
fetchItems: () => Promise<void>;
addItem: (item: Item) => Promise<void>;
}
export const useExampleStore = create<ExampleState>((set, get) => ({
// Initial state
items: [],
isLoading: false,
error: null,
// Actions
fetchItems: async () => {
try {
set({ isLoading: true, error: null });
const items = await exampleService.getItems();
set({ items, isLoading: false });
} catch (error) {
set({ error: error.message, isLoading: false });
}
},
addItem: async item => {
const newItem = await exampleService.createItem(item);
set(state => ({ items: [...state.items, newItem] }));
},
}));
Service Pattern
Services handle API calls using TanStack Query pattern (or direct fetch).
import api from './api';
export const exampleService = {
async getItems(): Promise<Item[]> {
const response = await api.get('/examples');
return response.data;
},
async getItem(id: string): Promise<Item> {
const response = await api.get(`/examples/${id}`);
return response.data;
},
async createItem(data: CreateItemInput): Promise<Item> {
const response = await api.post('/examples', data);
return response.data;
},
};
Design System
Color Palette: Neutral scale (white, black, grays)
// ✅ ALWAYS: Use neutral colors
className = 'bg-neutral-900 text-white'; // Primary
className = 'bg-white border-neutral-300'; // Secondary
className = 'bg-error-600 text-white'; // Danger
// ❌ NEVER: No gradients in UI
className = 'bg-gradient-to-r from-blue-500 to-purple-500'; // NO!
Typography: Clean, readable, enterprise-focused
Border-based: No heavy shadows
// ✅ ALWAYS: Border-based design
className = 'border border-neutral-200 rounded';
// ❌ NEVER: Heavy shadows
className = 'shadow-lg shadow-xl'; // NO!
Import Pattern
Use absolute imports with @/ alias.
// ✅ ALWAYS: Absolute imports
import { Button } from '@/components/ui/Button';
import { useExampleStore } from '@/stores/example.store';
import * as exampleService from '@/services/example.service';
// ❌ NEVER: Relative imports (except within same folder)
import { Button } from '../../../components/ui/Button';
Loading States
const { isLoading, items, fetchItems } = useExampleStore();
useEffect(() => {
fetchItems();
}, []);
if (isLoading) {
return <Spinner />;
}
Error Handling
const { error, clearError } = useExampleStore();
if (error) {
return (
<Alert variant="error">
{error}
<button onClick={clearError}>Dismiss</button>
</Alert>
);
}
Hooks Pattern
export function useAuth() {
const { user, token } = useAuthStore();
return {
isAuthenticated: !!token,
user,
logout: useAuthStore.getState().logout,
};
}
Context Pattern (Socket.IO)
const SocketContext = createContext<Socket | null>(null);
export function SocketProvider({ children }: { children: ReactNode }) {
const [socket, setSocket] = useState<Socket | null>(null);
useEffect(() => {
const newSocket = io(SOCKET_URL);
setSocket(newSocket);
return () => {
newSocket.disconnect();
};
}, []);
return <SocketContext.Provider value={socket}>{children}</SocketContext.Provider>;
}
Commands
npm run dev:web # Start dev server
npm run build:web # Build
npm run test:web # Run tests
npm run test:e2e # Run E2E tests
npm run lint --workspace=@migestion/web # Lint
npm run typecheck # Type check
Related Skills
react-18- React component patternszustand-4- Zustand store patternstailwind- Tailwind CSS utilitiesvite- Vite build patternsmigestion-test-web- E2E testing patterns
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon