mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-08 18:33:28 +08:00
feat: add web frontend rules and design quality hook
This commit is contained in:
96
rules/web/coding-style.md
Normal file
96
rules/web/coding-style.md
Normal file
@@ -0,0 +1,96 @@
|
||||
> This file extends [common/coding-style.md](../common/coding-style.md) with web-specific frontend content.
|
||||
|
||||
# Web Coding Style
|
||||
|
||||
## File Organization
|
||||
|
||||
Organize by feature or surface area, not by file type:
|
||||
|
||||
```text
|
||||
src/
|
||||
├── components/
|
||||
│ ├── hero/
|
||||
│ │ ├── Hero.tsx
|
||||
│ │ ├── HeroVisual.tsx
|
||||
│ │ └── hero.css
|
||||
│ ├── scrolly-section/
|
||||
│ │ ├── ScrollySection.tsx
|
||||
│ │ ├── StickyVisual.tsx
|
||||
│ │ └── scrolly.css
|
||||
│ └── ui/
|
||||
│ ├── Button.tsx
|
||||
│ ├── SurfaceCard.tsx
|
||||
│ └── AnimatedText.tsx
|
||||
├── hooks/
|
||||
│ ├── useReducedMotion.ts
|
||||
│ └── useScrollProgress.ts
|
||||
├── lib/
|
||||
│ ├── animation.ts
|
||||
│ └── color.ts
|
||||
└── styles/
|
||||
├── tokens.css
|
||||
├── typography.css
|
||||
└── global.css
|
||||
```
|
||||
|
||||
## CSS Custom Properties
|
||||
|
||||
Define design tokens as variables. Do not hardcode palette, typography, or spacing repeatedly:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-surface: oklch(98% 0 0);
|
||||
--color-text: oklch(18% 0 0);
|
||||
--color-accent: oklch(68% 0.21 250);
|
||||
|
||||
--text-base: clamp(1rem, 0.92rem + 0.4vw, 1.125rem);
|
||||
--text-hero: clamp(3rem, 1rem + 7vw, 8rem);
|
||||
|
||||
--space-section: clamp(4rem, 3rem + 5vw, 10rem);
|
||||
|
||||
--duration-fast: 150ms;
|
||||
--duration-normal: 300ms;
|
||||
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
```
|
||||
|
||||
## Animation-Only Properties
|
||||
|
||||
Prefer compositor-friendly motion:
|
||||
- `transform`
|
||||
- `opacity`
|
||||
- `clip-path`
|
||||
- `filter` (sparingly)
|
||||
|
||||
Avoid animating layout-bound properties:
|
||||
- `width`
|
||||
- `height`
|
||||
- `top`
|
||||
- `left`
|
||||
- `margin`
|
||||
- `padding`
|
||||
- `border`
|
||||
- `font-size`
|
||||
|
||||
## Semantic HTML First
|
||||
|
||||
```html
|
||||
<header>
|
||||
<nav aria-label="Main navigation">...</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section aria-labelledby="hero-heading">
|
||||
<h1 id="hero-heading">...</h1>
|
||||
</section>
|
||||
</main>
|
||||
<footer>...</footer>
|
||||
```
|
||||
|
||||
Do not reach for generic wrapper `div` stacks when a semantic element exists.
|
||||
|
||||
## Naming
|
||||
|
||||
- Components: PascalCase (`ScrollySection`, `SurfaceCard`)
|
||||
- Hooks: `use` prefix (`useReducedMotion`)
|
||||
- CSS classes: kebab-case or utility classes
|
||||
- Animation timelines: camelCase with intent (`heroRevealTl`)
|
||||
63
rules/web/design-quality.md
Normal file
63
rules/web/design-quality.md
Normal file
@@ -0,0 +1,63 @@
|
||||
> This file extends [common/patterns.md](../common/patterns.md) with web-specific design-quality guidance.
|
||||
|
||||
# Web Design Quality Standards
|
||||
|
||||
## Anti-Template Policy
|
||||
|
||||
Do not ship generic template-looking UI. Frontend output should look intentional, opinionated, and specific to the product.
|
||||
|
||||
### Banned Patterns
|
||||
|
||||
- Default card grids with uniform spacing and no hierarchy
|
||||
- Stock hero section with centered headline, gradient blob, and generic CTA
|
||||
- Unmodified library defaults passed off as finished design
|
||||
- Flat layouts with no layering, depth, or motion
|
||||
- Uniform radius, spacing, and shadows across every component
|
||||
- Safe gray-on-white styling with one decorative accent color
|
||||
- Dashboard-by-numbers layouts with sidebar + cards + charts and no point of view
|
||||
- Default font stacks used without a deliberate reason
|
||||
|
||||
### Required Qualities
|
||||
|
||||
Every meaningful frontend surface should demonstrate at least four of these:
|
||||
|
||||
1. Clear hierarchy through scale contrast
|
||||
2. Intentional rhythm in spacing, not uniform padding everywhere
|
||||
3. Depth or layering through overlap, shadows, surfaces, or motion
|
||||
4. Typography with character and a real pairing strategy
|
||||
5. Color used semantically, not just decoratively
|
||||
6. Hover, focus, and active states that feel designed
|
||||
7. Grid-breaking editorial or bento composition where appropriate
|
||||
8. Texture, grain, or atmosphere when it fits the visual direction
|
||||
9. Motion that clarifies flow instead of distracting from it
|
||||
10. Data visualization treated as part of the design system, not an afterthought
|
||||
|
||||
## Before Writing Frontend Code
|
||||
|
||||
1. Pick a specific style direction. Avoid vague defaults like "clean minimal".
|
||||
2. Define a palette intentionally.
|
||||
3. Choose typography deliberately.
|
||||
4. Gather at least a small set of real references.
|
||||
5. Use ECC design/frontend skills where relevant.
|
||||
|
||||
## Worthwhile Style Directions
|
||||
|
||||
- Editorial / magazine
|
||||
- Neo-brutalism
|
||||
- Glassmorphism with real depth
|
||||
- Dark luxury or light luxury with disciplined contrast
|
||||
- Bento layouts
|
||||
- Scrollytelling
|
||||
- 3D integration
|
||||
- Swiss / International
|
||||
- Retro-futurism
|
||||
|
||||
Do not default to dark mode automatically. Choose the visual direction the product actually wants.
|
||||
|
||||
## Component Checklist
|
||||
|
||||
- [ ] Does it avoid looking like a default Tailwind or shadcn template?
|
||||
- [ ] Does it have intentional hover/focus/active states?
|
||||
- [ ] Does it use hierarchy rather than uniform emphasis?
|
||||
- [ ] Would this look believable in a real product screenshot?
|
||||
- [ ] If it supports both themes, do both light and dark feel intentional?
|
||||
120
rules/web/hooks.md
Normal file
120
rules/web/hooks.md
Normal file
@@ -0,0 +1,120 @@
|
||||
> This file extends [common/hooks.md](../common/hooks.md) with web-specific hook recommendations.
|
||||
|
||||
# Web Hooks
|
||||
|
||||
## Recommended PostToolUse Hooks
|
||||
|
||||
Prefer project-local tooling. Do not wire hooks to remote one-off package execution.
|
||||
|
||||
### Format on Save
|
||||
|
||||
Use the project's existing formatter entrypoint after edits:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"command": "pnpm prettier --write \"$FILE_PATH\"",
|
||||
"description": "Format edited frontend files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Equivalent local commands via `yarn prettier` or `npm exec prettier --` are fine when they use repo-owned dependencies.
|
||||
|
||||
### Lint Check
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"command": "pnpm eslint --fix \"$FILE_PATH\"",
|
||||
"description": "Run ESLint on edited frontend files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Type Check
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"command": "pnpm tsc --noEmit --pretty false",
|
||||
"description": "Type-check after frontend edits"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CSS Lint
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"command": "pnpm stylelint --fix \"$FILE_PATH\"",
|
||||
"description": "Lint edited stylesheets"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## PreToolUse Hooks
|
||||
|
||||
### Guard File Size
|
||||
|
||||
Block oversized writes from tool input content, not from a file that may not exist yet:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Write",
|
||||
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const c=i.tool_input?.content||'';const lines=c.split('\\n').length;if(lines>800){console.error('[Hook] BLOCKED: File exceeds 800 lines ('+lines+' lines)');console.error('[Hook] Split into smaller modules');process.exit(2)}console.log(d)})\"",
|
||||
"description": "Block writes that exceed 800 lines"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Stop Hooks
|
||||
|
||||
### Final Build Verification
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
"command": "pnpm build",
|
||||
"description": "Verify the production build at session end"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Ordering
|
||||
|
||||
Recommended order:
|
||||
1. format
|
||||
2. lint
|
||||
3. type check
|
||||
4. build verification
|
||||
79
rules/web/patterns.md
Normal file
79
rules/web/patterns.md
Normal file
@@ -0,0 +1,79 @@
|
||||
> This file extends [common/patterns.md](../common/patterns.md) with web-specific patterns.
|
||||
|
||||
# Web Patterns
|
||||
|
||||
## Component Composition
|
||||
|
||||
### Compound Components
|
||||
|
||||
Use compound components when related UI shares state and interaction semantics:
|
||||
|
||||
```tsx
|
||||
<Tabs defaultValue="overview">
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
|
||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
<Tabs.Content value="overview">...</Tabs.Content>
|
||||
<Tabs.Content value="settings">...</Tabs.Content>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
- Parent owns state
|
||||
- Children consume via context
|
||||
- Prefer this over prop drilling for complex widgets
|
||||
|
||||
### Render Props / Slots
|
||||
|
||||
- Use render props or slot patterns when behavior is shared but markup must vary
|
||||
- Keep keyboard handling, ARIA, and focus logic in the headless layer
|
||||
|
||||
### Container / Presentational Split
|
||||
|
||||
- Container components own data loading and side effects
|
||||
- Presentational components receive props and render UI
|
||||
- Presentational components should stay pure
|
||||
|
||||
## State Management
|
||||
|
||||
Treat these separately:
|
||||
|
||||
| Concern | Tooling |
|
||||
|---------|---------|
|
||||
| Server state | TanStack Query, SWR, tRPC |
|
||||
| Client state | Zustand, Jotai, signals |
|
||||
| URL state | search params, route segments |
|
||||
| Form state | React Hook Form or equivalent |
|
||||
|
||||
- Do not duplicate server state into client stores
|
||||
- Derive values instead of storing redundant computed state
|
||||
|
||||
## URL As State
|
||||
|
||||
Persist shareable state in the URL:
|
||||
- filters
|
||||
- sort order
|
||||
- pagination
|
||||
- active tab
|
||||
- search query
|
||||
|
||||
## Data Fetching
|
||||
|
||||
### Stale-While-Revalidate
|
||||
|
||||
- Return cached data immediately
|
||||
- Revalidate in the background
|
||||
- Prefer existing libraries instead of rolling this by hand
|
||||
|
||||
### Optimistic Updates
|
||||
|
||||
- Snapshot current state
|
||||
- Apply optimistic update
|
||||
- Roll back on failure
|
||||
- Emit visible error feedback when rolling back
|
||||
|
||||
### Parallel Loading
|
||||
|
||||
- Fetch independent data in parallel
|
||||
- Avoid parent-child request waterfalls
|
||||
- Prefetch likely next routes or states when justified
|
||||
64
rules/web/performance.md
Normal file
64
rules/web/performance.md
Normal file
@@ -0,0 +1,64 @@
|
||||
> This file extends [common/performance.md](../common/performance.md) with web-specific performance content.
|
||||
|
||||
# Web Performance Rules
|
||||
|
||||
## Core Web Vitals Targets
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| LCP | < 2.5s |
|
||||
| INP | < 200ms |
|
||||
| CLS | < 0.1 |
|
||||
| FCP | < 1.5s |
|
||||
| TBT | < 200ms |
|
||||
|
||||
## Bundle Budget
|
||||
|
||||
| Page Type | JS Budget (gzipped) | CSS Budget |
|
||||
|-----------|---------------------|------------|
|
||||
| Landing page | < 150kb | < 30kb |
|
||||
| App page | < 300kb | < 50kb |
|
||||
| Microsite | < 80kb | < 15kb |
|
||||
|
||||
## Loading Strategy
|
||||
|
||||
1. Inline critical above-the-fold CSS where justified
|
||||
2. Preload the hero image and primary font only
|
||||
3. Defer non-critical CSS or JS
|
||||
4. Dynamically import heavy libraries
|
||||
|
||||
```js
|
||||
const gsapModule = await import('gsap');
|
||||
const { ScrollTrigger } = await import('gsap/ScrollTrigger');
|
||||
```
|
||||
|
||||
## Image Optimization
|
||||
|
||||
- Explicit `width` and `height`
|
||||
- `loading="eager"` plus `fetchpriority="high"` for hero media only
|
||||
- `loading="lazy"` for below-the-fold assets
|
||||
- Prefer AVIF or WebP with fallbacks
|
||||
- Never ship source images far beyond rendered size
|
||||
|
||||
## Font Loading
|
||||
|
||||
- Max two font families unless there is a clear exception
|
||||
- `font-display: swap`
|
||||
- Subset where possible
|
||||
- Preload only the truly critical weight/style
|
||||
|
||||
## Animation Performance
|
||||
|
||||
- Animate compositor-friendly properties only
|
||||
- Use `will-change` narrowly and remove it when done
|
||||
- Prefer CSS for simple transitions
|
||||
- Use `requestAnimationFrame` or established animation libraries for JS motion
|
||||
- Avoid scroll handler churn; use IntersectionObserver or well-behaved libraries
|
||||
|
||||
## Performance Checklist
|
||||
|
||||
- [ ] All images have explicit dimensions
|
||||
- [ ] No accidental render-blocking resources
|
||||
- [ ] No layout shifts from dynamic content
|
||||
- [ ] Motion stays on compositor-friendly properties
|
||||
- [ ] Third-party scripts load async/defer and only when needed
|
||||
57
rules/web/security.md
Normal file
57
rules/web/security.md
Normal file
@@ -0,0 +1,57 @@
|
||||
> This file extends [common/security.md](../common/security.md) with web-specific security content.
|
||||
|
||||
# Web Security Rules
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Always configure a production CSP.
|
||||
|
||||
### Nonce-Based CSP
|
||||
|
||||
Use a per-request nonce for scripts instead of `'unsafe-inline'`.
|
||||
|
||||
```text
|
||||
Content-Security-Policy:
|
||||
default-src 'self';
|
||||
script-src 'self' 'nonce-{RANDOM}' https://cdn.jsdelivr.net;
|
||||
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: https:;
|
||||
font-src 'self' https://fonts.gstatic.com;
|
||||
connect-src 'self' https://*.example.com;
|
||||
frame-src 'none';
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
```
|
||||
|
||||
Adjust origins to the project. Do not cargo-cult this block unchanged.
|
||||
|
||||
## XSS Prevention
|
||||
|
||||
- Never inject unsanitized HTML
|
||||
- Avoid `innerHTML` / `dangerouslySetInnerHTML` unless sanitized first
|
||||
- Escape dynamic template values
|
||||
- Sanitize user HTML with a vetted local sanitizer when absolutely necessary
|
||||
|
||||
## Third-Party Scripts
|
||||
|
||||
- Load asynchronously
|
||||
- Use SRI when serving from a CDN
|
||||
- Audit quarterly
|
||||
- Prefer self-hosting for critical dependencies when practical
|
||||
|
||||
## HTTPS and Headers
|
||||
|
||||
```text
|
||||
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Frame-Options: DENY
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Permissions-Policy: camera=(), microphone=(), geolocation=()
|
||||
```
|
||||
|
||||
## Forms
|
||||
|
||||
- CSRF protection on state-changing forms
|
||||
- Rate limiting on submission endpoints
|
||||
- Validate client and server side
|
||||
- Prefer honeypots or light anti-abuse controls over heavy-handed CAPTCHA defaults
|
||||
55
rules/web/testing.md
Normal file
55
rules/web/testing.md
Normal file
@@ -0,0 +1,55 @@
|
||||
> This file extends [common/testing.md](../common/testing.md) with web-specific testing content.
|
||||
|
||||
# Web Testing Rules
|
||||
|
||||
## Priority Order
|
||||
|
||||
### 1. Visual Regression
|
||||
|
||||
- Screenshot key breakpoints: 320, 768, 1024, 1440
|
||||
- Test hero sections, scrollytelling sections, and meaningful states
|
||||
- Use Playwright screenshots for visual-heavy work
|
||||
- If both themes exist, test both
|
||||
|
||||
### 2. Accessibility
|
||||
|
||||
- Run automated accessibility checks
|
||||
- Test keyboard navigation
|
||||
- Verify reduced-motion behavior
|
||||
- Verify color contrast
|
||||
|
||||
### 3. Performance
|
||||
|
||||
- Run Lighthouse or equivalent against meaningful pages
|
||||
- Keep CWV targets from [performance.md](performance.md)
|
||||
|
||||
### 4. Cross-Browser
|
||||
|
||||
- Minimum: Chrome, Firefox, Safari
|
||||
- Test scrolling, motion, and fallback behavior
|
||||
|
||||
### 5. Responsive
|
||||
|
||||
- Test 320, 375, 768, 1024, 1440, 1920
|
||||
- Verify no overflow
|
||||
- Verify touch interactions
|
||||
|
||||
## E2E Shape
|
||||
|
||||
```ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('landing hero loads', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.locator('h1')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
- Avoid flaky timeout-based assertions
|
||||
- Prefer deterministic waits
|
||||
|
||||
## Unit Tests
|
||||
|
||||
- Test utilities, data transforms, and custom hooks
|
||||
- For highly visual components, visual regression often carries more signal than brittle markup assertions
|
||||
- Visual regression supplements coverage targets; it does not replace them
|
||||
Reference in New Issue
Block a user