ワンクリックで
project-architecture
Guide for project structure and architectural decisions. Use when setting up new projects or organizing code structure.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Guide for project structure and architectural decisions. Use when setting up new projects or organizing code structure.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Checklist for auditing and fixing accessibility issues (WCAG 2.1 AA compliance). Use when reviewing components or pages for accessibility.
Guide for creating RESTful API endpoints with validation and error handling. Use when implementing backend API routes.
Guide for implementing secure authentication with JWT and session management. Use when adding authentication to an application.
Guide for creating responsive layouts with CSS. Use when implementing responsive design or fixing layout issues.
Guide for designing database schemas with Prisma ORM. Use when creating or modifying database models.
Guide for consistent error handling across frontend and backend. Use when implementing error handling logic.
| name | project-architecture |
| description | Guide for project structure and architectural decisions. Use when setting up new projects or organizing code structure. |
Follow this guide for consistent project structure and architectural decisions:
src/
├── components/ # Reusable UI components
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx
│ │ └── Button.module.css
│ └── Card/
│ └── ...
├── features/ # Feature-based modules
│ ├── auth/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── services/
│ │ └── types.ts
│ └── dashboard/
│ └── ...
├── pages/ # Page-level components (routes)
│ ├── HomePage.tsx
│ ├── DashboardPage.tsx
│ └── ...
├── layouts/ # Layout components
│ ├── MainLayout.tsx
│ └── AuthLayout.tsx
├── hooks/ # Shared custom hooks
│ ├── useAuth.ts
│ └── useFetch.ts
├── services/ # API calls and external services
│ ├── api.ts
│ └── authService.ts
├── utils/ # Helper functions
│ ├── formatDate.ts
│ └── validation.ts
├── types/ # Shared TypeScript types
│ ├── user.ts
│ └── api.ts
├── constants/ # App-wide constants
│ └── config.ts
├── styles/ # Global styles
│ ├── globals.css
│ └── variables.css
└── assets/ # Static assets
├── images/
└── icons/
Button/
├── Button.tsx # Component logic
├── Button.test.tsx # Tests
├── Button.module.css # Styles
├── Button.stories.tsx # Storybook (optional)
└── index.ts # Re-export
components/
├── Button.tsx
├── ButtonStyles.css
├── ButtonTest.tsx # Inconsistent naming
└── Card.tsx
// CSP Violation! Allows XSS attacks
<div style={{ color: userInput }}>Content</div>
// Button.module.css
import styles from './Button.module.css';
<button className={styles.primary}>Click</button>
Why CSS Modules:
<button className="px-4 py-2 bg-blue-500 text-white rounded">
Click
</button>
Why Tailwind:
import styled from 'styled-components';
const Button = styled.button`
padding: 0.5rem 1rem;
background: blue;
`;
Only if: You configure CSP nonce correctly!
// OK: Truly dynamic value that can't be in CSS
<div style={{ width: `${percent}%` }}>Progress</div>
// Better: Use CSS variables
<div
className={styles.progress}
style={{ '--progress': `${percent}%` } as React.CSSProperties}
/>
Group by feature, not by file type:
features/
└── user-profile/
├── components/
│ ├── ProfileCard.tsx
│ └── EditProfileForm.tsx
├── hooks/
│ └── useUserProfile.ts
├── services/
│ └── profileApi.ts
└── types.ts
src/
├── components/ # 100+ files mixed together
├── hooks/ # Hard to find related code
└── services/
// 1. External dependencies
import React, { useState } from 'react';
import { useRouter } from 'next/router';
// 2. Internal absolute imports
import { Button } from '@/components/Button';
import { useAuth } from '@/hooks/useAuth';
// 3. Relative imports (same feature)
import { ProfileCard } from './ProfileCard';
import type { UserProfile } from './types';
// 4. Styles (last)
import styles from './Profile.module.css';
❌ DON'T: API calls in components
function UserProfile() {
const [user, setUser] = useState();
useEffect(() => {
fetch('/api/users/123').then(/* ... */); // ❌ Bad
}, []);
}
✅ DO: Separate service layer
// services/userService.ts
export async function getUserProfile(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
}
// Component
function UserProfile() {
const { data, isLoading } = useQuery({
queryKey: ['user', id],
queryFn: () => getUserProfile(id),
});
}
// config/env.ts
export const config = {
apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000',
isDev: import.meta.env.DEV,
isProd: import.meta.env.PROD,
} as const;
// ❌ DON'T: Hardcode URLs everywhere
// ✅ DO: Single source of truth
// types/user.ts - Domain types
export interface User {
id: string;
email: string;
}
// types/api.ts - API types
export interface ApiResponse<T> {
data: T;
error?: string;
}
// Component-specific types: Co-located
// Button/Button.tsx
interface ButtonProps { /* ... */ }
contexts/
├── AuthContext.tsx
└── ThemeContext.tsx
stores/
├── authStore.ts
└── cartStore.ts
store/
├── slices/
│ ├── authSlice.ts
│ └── userSlice.ts
└── store.ts
| Type | Convention | Example |
|---|---|---|
| Components | PascalCase | UserProfile.tsx |
| Hooks | camelCase + "use" | useAuth.ts |
| Utils | camelCase | formatDate.ts |
| Constants | UPPER_SNAKE_CASE | API_BASE_URL |
| Types | PascalCase | User, ApiResponse |
| CSS Modules | camelCase | styles.primaryButton |
| Files | kebab-case or PascalCase | user-profile.tsx |
// components/Button/index.ts
export { Button } from './Button';
export type { ButtonProps } from './Button';
// Now import like:
import { Button } from '@/components/Button';
When adding new code, ask: