{"id":"78ebc844-2120-48f0-abee-3fe34c28fb19","shortId":"XPaFq9","kind":"skill","title":"wednesday-dev","tagline":"Technical development guidelines for Wednesday Solutions projects. Enforces import ordering, complexity limits, naming conventions, TypeScript best practices, and code quality standards for React/Next.js applications.","description":"# Wednesday Technical Development Guidelines\n\n## Trigger\n\nLoad this skill when writing, reviewing, or refactoring **code logic**:\n- Writing a new function, hook, API route, or service\n- Reviewing TypeScript / JavaScript for quality issues\n- Refactoring for complexity, naming, or structure\n- \"Does this follow our coding standards?\"\n\n**Do NOT use this skill for:** choosing UI components or visual styling (use `wednesday-design`). This skill covers code structure, TypeScript, imports, and logic — not visual output.\n\n---\n\nThis skill enforces code quality standards for Wednesday Solutions projects. Follow these guidelines to maintain consistency, readability, and maintainability across the codebase.\n\n## 1. Import Order\n\nImports must follow a strict ordering pattern. The project uses `@trivago/prettier-plugin-sort-imports` to enforce this automatically.\n\n### Required Order\n\n```typescript\n// 1. React (always first)\nimport React, { useState, useEffect } from 'react'\n\n// 2. Next.js imports\nimport { useRouter } from 'next/navigation'\nimport Image from 'next/image'\n\n// 3. State management (Recoil, Redux)\nimport { useSelector } from 'react-redux'\n\n// 4. UI libraries (MUI, Radix)\nimport { Button } from '@mui/material'\n\n// 5. Path alias imports (@/)\nimport { useAuth } from '@/lib/hooks/useAuth'\nimport { API_ROUTES } from '@/lib/constants'\n\n// 6. External packages\nimport { z } from 'zod'\nimport { motion } from 'framer-motion'\n\n// 7. Internal components\nimport { Header } from 'components/Header'\n\n// 8. Relative imports (sibling/parent)\nimport { utils } from './utils'\nimport { types } from '../types'\n```\n\n### Rules\n\n- Each import group must be separated by a blank line\n- Imports within each group should be alphabetically sorted\n- Use type imports for TypeScript types: `import type { User } from '@/types'`\n- Avoid wildcard imports (`import * as`) unless necessary\n\n## 2. Code Complexity\n\n### Cyclomatic Complexity\n\n**Maximum allowed: 8** (stricter than industry standard of 10)\n\nFunctions exceeding this limit must be refactored. See [references/COMPLEXITY.md](references/COMPLEXITY.md) for detailed strategies.\n\n### Quick Remediation\n\n| Complexity | Action Required |\n|------------|-----------------|\n| 1-4        | Good - easy to test |\n| 5-7        | Acceptable - consider simplifying |\n| 8          | At limit - refactor if adding logic |\n| 9+         | Must refactor before merging |\n\n### How to Reduce Complexity\n\n1. **Extract helper functions** - Break large functions into smaller, focused ones\n2. **Use early returns** - Replace nested conditions with guard clauses\n3. **Replace conditionals with polymorphism** - Use strategy pattern for complex branching\n4. **Simplify boolean expressions** - Extract complex conditions into named variables\n5. **Use lookup tables** - Replace switch statements with object maps\n\n```typescript\n// BAD: High complexity\nfunction getDiscount(user: User, items: Item[]) {\n  let discount = 0\n  if (user.isPremium) {\n    if (items.length > 10) {\n      discount = 20\n    } else if (items.length > 5) {\n      discount = 10\n    } else {\n      discount = 5\n    }\n  } else {\n    if (items.length > 10) {\n      discount = 10\n    } else if (items.length > 5) {\n      discount = 5\n    }\n  }\n  return discount\n}\n\n// GOOD: Low complexity with lookup table\nconst DISCOUNT_TABLE = {\n  premium: { large: 20, medium: 10, small: 5 },\n  regular: { large: 10, medium: 5, small: 0 },\n} as const\n\nfunction getCartSize(count: number): 'large' | 'medium' | 'small' {\n  if (count > 10) return 'large'\n  if (count > 5) return 'medium'\n  return 'small'\n}\n\nfunction getDiscount(user: User, items: Item[]) {\n  const tier = user.isPremium ? 'premium' : 'regular'\n  const size = getCartSize(items.length)\n  return DISCOUNT_TABLE[tier][size]\n}\n```\n\n### File Size Limits\n\n- **Max file lines**: 250\n- **Max function lines**: 350\n- **Max line length**: 120 characters\n\n## 3. Naming Conventions\n\n### Components & Classes\n\nUse **PascalCase** for React components, classes, types, and interfaces.\n\n```typescript\n// Components\nfunction UserProfile() { }\nfunction PaymentCard() { }\n\n// Types & Interfaces\ninterface UserProfileProps { }\ntype PaymentMethod = 'card' | 'bank'\n\n// Classes\nclass AuthService { }\n```\n\n### Functions & Variables\n\nUse **camelCase** for functions, variables, hooks, and object properties.\n\n```typescript\n// Functions\nfunction fetchUserData() { }\nfunction calculateTotal() { }\n\n// Variables\nconst isLoading = true\nconst userProfile = { }\n\n// Hooks\nfunction useAuth() { }\nfunction useLocalStorage() { }\n```\n\n### Constants & Enums\n\nUse **UPPER_SNAKE_CASE** for constants and enum values.\n\n```typescript\n// Constants\nconst API_BASE_URL = 'https://api.example.com'\nconst MAX_RETRY_ATTEMPTS = 3\n\n// Enums\nenum UserRole {\n  ADMIN = 'ADMIN',\n  USER = 'USER',\n  GUEST = 'GUEST',\n}\n```\n\n### Boolean Variables\n\nPrefix with `is`, `has`, `should`, `can`, or `will` for clarity.\n\n```typescript\n// Good\nconst isAuthenticated = true\nconst hasPermission = false\nconst shouldRefetch = true\nconst canEdit = user.role === 'ADMIN'\n\n// Bad\nconst authenticated = true\nconst permission = false\nconst refetch = true\n```\n\n### Files & Folders\n\n| Type | Convention | Example |\n|------|------------|---------|\n| Component files | PascalCase | `UserProfile.tsx` |\n| Hook files | camelCase with `use` prefix | `useAuth.ts` |\n| Utility files | camelCase | `formatDate.ts` |\n| Constant files | camelCase | `apiRoutes.ts` |\n| Type files | camelCase | `user.types.ts` |\n| Test files | Match source + `.test` | `UserProfile.test.tsx` |\n| Folders | camelCase | `components/`, `hooks/` |\n\n### Descriptive Naming\n\nNames should be self-documenting:\n\n```typescript\n// Bad - unclear intent\nconst d = new Date()\nconst arr = users.filter(u => u.a)\nfunction proc(x: number) { }\n\n// Good - clear intent\nconst currentDate = new Date()\nconst activeUsers = users.filter(user => user.isActive)\nfunction processPayment(amount: number) { }\n```\n\n## 4. TypeScript Best Practices\n\n### Strict Type Safety\n\n- Enable strict mode in `tsconfig.json`\n- Avoid `any` type - use `unknown` and narrow types\n- Use explicit return types for public functions\n- Leverage discriminated unions for state\n\n```typescript\n// Use discriminated unions\ntype AsyncState<T> =\n  | { status: 'idle' }\n  | { status: 'loading' }\n  | { status: 'success'; data: T }\n  | { status: 'error'; error: Error }\n\n// Narrow types properly\nfunction processValue(value: unknown) {\n  if (typeof value === 'string') {\n    return value.toUpperCase()\n  }\n  if (typeof value === 'number') {\n    return value.toFixed(2)\n  }\n  throw new Error('Unsupported type')\n}\n```\n\n### Type Imports\n\nSeparate type imports from value imports:\n\n```typescript\nimport { useState } from 'react'\nimport type { FC, ReactNode } from 'react'\n\nimport { fetchUser } from '@/lib/api'\nimport type { User, UserRole } from '@/types'\n```\n\n## 5. React Patterns\n\n### Component Structure\n\nFollow this order within components:\n\n1. Type definitions (props interface)\n2. Component function declaration\n3. Hooks (useState, useEffect, custom hooks)\n4. Derived state / computations\n5. Event handlers\n6. Effects\n7. Return statement (JSX)\n\n```typescript\ninterface UserCardProps {\n  userId: string\n  onSelect?: (user: User) => void\n}\n\nexport function UserCard({ userId, onSelect }: UserCardProps) {\n  // 1. Hooks\n  const [isExpanded, setIsExpanded] = useState(false)\n  const { data: user, isLoading } = useUser(userId)\n\n  // 2. Derived state\n  const displayName = user ? `${user.firstName} ${user.lastName}` : 'Unknown'\n\n  // 3. Event handlers\n  const handleClick = () => {\n    setIsExpanded(!isExpanded)\n    onSelect?.(user)\n  }\n\n  // 4. Early returns for loading/error states\n  if (isLoading) return <Skeleton />\n  if (!user) return null\n\n  // 5. Main render\n  return (\n    <Card onClick={handleClick}>\n      <CardTitle>{displayName}</CardTitle>\n      {isExpanded && <CardContent>{user.bio}</CardContent>}\n    </Card>\n  )\n}\n```\n\n### Use Client Directive\n\nMark client components explicitly:\n\n```typescript\n'use client'\n\nimport { useState } from 'react'\n// ... client-side component\n```\n\n## 6. Forbidden Patterns\n\n### No Console Statements\n\nConsole statements are forbidden in production code. Use proper logging utilities.\n\n```typescript\n// Forbidden\nconsole.log('debug:', data)\nconsole.error('Error:', err)\n\n// Use structured logging or remove before commit\n```\n\n### No Magic Numbers/Strings\n\nExtract to named constants:\n\n```typescript\n// Bad\nif (retryCount > 3) { }\nif (status === 'active') { }\n\n// Good\nconst MAX_RETRIES = 3\nconst STATUS_ACTIVE = 'active'\n\nif (retryCount > MAX_RETRIES) { }\nif (status === STATUS_ACTIVE) { }\n```\n\n### No Unused Code\n\n- Remove unused imports (enforced by `eslint-plugin-unused-imports`)\n- Delete commented-out code\n- Remove unused variables (prefix with `_` only if intentionally unused)\n\n## 7. Testing Requirements\n\n### Unit Tests\n\n- Use Jest with React Testing Library\n- Test file naming: `ComponentName.test.tsx`\n- Focus on user behavior, not implementation details\n\n```typescript\nimport { render, screen, fireEvent } from '@testing-library/react'\nimport { UserCard } from './UserCard'\n\ndescribe('UserCard', () => {\n  it('displays user name correctly', () => {\n    render(<UserCard userId=\"123\" />)\n    expect(screen.getByText('John Doe')).toBeInTheDocument()\n  })\n\n  it('calls onSelect when clicked', () => {\n    const onSelect = jest.fn()\n    render(<UserCard userId=\"123\" onSelect={onSelect} />)\n    fireEvent.click(screen.getByRole('button'))\n    expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }))\n  })\n})\n```\n\n### E2E Tests\n\n- Use Playwright for end-to-end tests\n- Test file naming: `feature.spec.ts`\n- Test critical user flows\n\n## 8. Security Considerations\n\n- Sanitize HTML with DOMPurify before rendering\n- Validate all user inputs with Zod schemas\n- Never expose sensitive data in client-side code\n- Use environment variables for secrets\n- Implement CSRF protection for forms\n\n## 9. Performance Guidelines\n\n- Use `next/dynamic` for code splitting\n- Implement proper loading states\n- Memoize expensive computations with `useMemo`\n- Avoid unnecessary re-renders with `React.memo`\n- Use image optimization with `next/image`\n\n---\n\n## 10. Commenting Guidelines (brownfield-aware)\n\nThese conventions are read by the brownfield intelligence pipeline to build module purpose maps,\ndetect tech debt, and generate the reverse PRD. Well-placed comments make the map report\nsignificantly more useful — they surface intent that can't be inferred from code structure alone.\n\n### Substantive comments (captured as developer intent)\n\nWrite comments that explain **why**, not what. Comments of 8+ words that aren't noise are\ncollected as \"developer intent\" and used to infer module purpose.\n\n```typescript\n// BAD — too short or states the obvious (filtered out)\n// increment counter\ni++\n\n// BAD — noise (filtered out)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n// @param userId - the user id\n\n// GOOD — explains why, ≥8 words (captured)\n// We batch here because the payment provider rate-limits to 10 req/s per merchant\n// Using optimistic updates to avoid the 200ms API round-trip on every keystroke\n// This module owns all JWT lifecycle — issue, refresh, revoke. Nothing else should touch tokens.\n```\n\n### Tech debt tags\n\nUse these exact tags — the brownfield scanner recognises them and maps severity:\n\n| Tag | Severity | Use for |\n|-----|----------|---------|\n| `FIXME:` | 🔴 high | Broken or incorrect behaviour that needs fixing |\n| `BUG:` | 🔴 high | Known bug, not yet fixed |\n| `XXX:` | 🔴 high | Dangerous or wrong — must not ship |\n| `HACK:` | 🟡 medium | Works but is a deliberate shortcut |\n| `KLUDGE:` | 🟡 medium | Messy workaround, needs rethinking |\n| `SMELL:` | 🟡 medium | Design concern, not yet a bug |\n| `TODO:` | 🟡 medium | Planned work, not urgent |\n| `TEMP:` | 🟡 medium | Intentionally temporary, must be removed |\n| `OPTIMIZE:` | 🔵 low | Performance opportunity |\n| `PERF:` | 🔵 low | Performance opportunity |\n| `REVIEW:` | 🔵 low | Needs a second pair of eyes |\n| `IDEA:` | ⚪ info | Suggestion, not planned work |\n| `NOTE:` | ⚪ info | Important context for future readers |\n| `DEPRECATED:` | ⚪ info | Kept for backwards compat, do not use |\n\n```typescript\n// FIXME: token refresh fails silently when the network drops mid-request\n// TODO: extract this into a shared retry utility once the payments module is stable\n// HACK: Stripe webhook retries mean this handler can run twice — idempotency check is manual\n// DEPRECATED: use useAuthV2() instead — this will be removed in v3\n```\n\n### Module-level header comments\n\nAdd a short header at the top of barrel files (`index.ts`) or the primary file of a directory.\nThe brownfield pipeline uses this to infer the module's purpose without LLM calls.\n\n```typescript\n// src/auth/index.ts\n//\n// Auth module — owns all identity concerns: JWT issue/refresh/revoke, session management,\n// and permission checks. No other module should read or write tokens directly.\n// Business feature: yes (user-facing login, OAuth, SSO flows).\n```\n\n### Graph annotation comments\n\nWhen a file uses dynamic patterns that the static analyser cannot resolve, add explicit\nannotations so the dependency graph stays accurate:\n\n```typescript\n// @wednesday-skills:connects-to login → src/auth/session.ts\n// (dynamic require resolved manually)\nconst mod = require(`./handlers/${eventName}`)\n\n// @wednesday-skills:global db → src/lib/db/client.ts\n// (injected via app context, not imported directly)\napp.locals.db = createDbClient()\n```\n\n### What NOT to write (filtered as noise)\n\nThe following are intentionally ignored by the scanner — don't rely on them for documentation:\n\n```typescript\n// @param userId - the user id          ← JSDoc parameters\n// @returns Promise<User>               ← JSDoc return types\n// eslint-disable-next-line             ← linter directives\n// prettier-ignore                      ← formatter directives\n// Copyright 2024 Wednesday Solutions      ← copyright headers\n// Auto-generated by codegen            ← generated file markers\n// do not edit                          ← generated file markers\n```\n\nFor detailed examples and edge cases, see [references/COMPLEXITY.md](references/COMPLEXITY.md).","tags":["wednesday","dev","agent","skills","wednesday-solutions","agent-skills","ai-agent-skills","ai-skills","claude-code","copilot","cursor","frontend-skills"],"capabilities":["skill","source-wednesday-solutions","skill-wednesday-dev","topic-agent-skills","topic-ai-agent-skills","topic-ai-skills","topic-claude-code","topic-copilot","topic-cursor","topic-frontend-skills","topic-vibe-coding","topic-vibe-coding-skills"],"categories":["ai-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/wednesday-solutions/ai-agent-skills/wednesday-dev","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add wednesday-solutions/ai-agent-skills","source_repo":"https://github.com/wednesday-solutions/ai-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.524","qualityRationale":"deterministic score 0.52 from registry signals: · indexed on github topic:agent-skills · 148 github stars · SKILL.md body (14,245 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:54:45.574Z","embedding":null,"createdAt":"2026-04-18T22:09:45.569Z","updatedAt":"2026-05-02T12:54:45.574Z","lastSeenAt":"2026-05-02T12:54:45.574Z","tsv":"'-4':297 '-7':303 '/handlers':1620 '/lib/api':802 '/lib/constants':194 '/lib/hooks/useauth':189 '/no-explicit-any':1287 '/react':1056 '/types':226,256,808 '/usercard':1060 '/utils':222 '0':387,440 '1':120,141,296,323,819,862 '10':277,392,400,407,409,431,436,452,1179,1310 '120':496 '123':1085,1096 '2':151,264,334,774,824,875 '20':394,429 '200ms':1320 '2024':1685 '250':488 '3':162,344,498,579,828,884,977,985 '350':492 '4':173,355,705,834,893 '5':182,302,365,398,403,413,415,433,438,457,809,838,906 '6':195,841,934 '7':208,843,1025 '8':215,271,307,1115,1245,1296 '9':314,1150 'accept':304 'accur':1603 'across':117 'action':294 'activ':980,988,989,997 'activeus':697 'ad':312 'add':1514,1595 'admin':583,584,615 'alia':184 'allow':270 'alon':1229 'alphabet':244 'alway':143 'amount':703 'analys':1592 'annot':1581,1597 'api':48,191,571,1321 'api.example.com':574 'apiroutes.ts':649 'app':1630 'app.locals.db':1635 'applic':27 'aren':1248 'arr':681 'asyncst':742 'attempt':578 'auth':1548 'authent':618 'authservic':528 'auto':1691 'auto-gener':1690 'automat':137 'avoid':257,717,1167,1318 'awar':1184 'backward':1453 'bad':376,616,673,974,1263,1275 'bank':525 'barrel':1522 'base':572 'batch':1300 'behavior':1043 'behaviour':1366 'best':19,707 'blank':236 'boolean':357,589 'branch':354 'break':327 'broken':1363 'brownfield':1183,1191,1350,1533 'brownfield-awar':1182 'bug':1370,1373,1406 'build':1195 'busi':1570 'button':179,1090 'calculatetot':545 'call':1075,1545 'camelcas':532,637,644,648,652,661 'canedit':613 'cannot':1593 'captur':1232,1298 'card':524,910 'case':562,1709 'charact':497 'check':1496,1560 'choos':76 'clariti':600 'class':502,508,526,527 'claus':343 'clear':690 'click':1078 'client':917,920,925,931,1137 'client-sid':930,1136 'code':22,41,68,89,101,265,946,1000,1015,1139,1156,1227 'codebas':119 'codegen':1694 'collect':1252 'comment':1013,1180,1210,1231,1237,1243,1513,1582 'commented-out':1012 'commit':965 'compat':1454 'complex':14,60,266,268,293,322,353,360,378,420 'compon':78,210,501,507,513,631,662,812,818,825,921,933 'componentname.test.tsx':1039 'components/header':214 'comput':837,1164 'concern':1402,1553 'condit':340,346,361 'connect':1609 'connects-to':1608 'consid':305 'consider':1117 'consist':113 'consol':938,940 'console.error':956 'console.log':953 'const':424,442,468,473,547,550,570,575,603,606,609,612,617,620,623,676,680,692,696,864,869,878,887,982,986,1079,1617 'constant':557,564,569,646,972 'context':1445,1631 'convent':17,500,629,1186 'copyright':1684,1688 'correct':1067 'count':445,451,456 'counter':1273 'cover':88 'createdbcli':1636 'critic':1112 'csrf':1146 'currentd':693 'custom':832 'cyclomat':267 'd':677 'danger':1379 'data':749,870,955,1134 'date':679,695 'db':1626 'debt':1201,1343 'debug':954 'declar':827 'definit':821 'delet':1011 'deliber':1391 'depend':1600 'deprec':1449,1499 'deriv':835,876 'describ':1061 'descript':664 'design':85,1401 'detail':289,1046,1705 'detect':1199 'dev':3 'develop':5,30,1234,1254 'direct':918,1569,1634,1678,1683 'directori':1531 'disabl':1281,1674 'discount':386,393,399,402,408,414,417,425,478 'discrimin':733,739 'display':1064 'displaynam':879,913 'document':671,1658 'doe':1072 'dompurifi':1121 'drop':1467 'dynam':1587,1613 'e2e':1097 'earli':336,894 'easi':299 'edg':1708 'edit':1700 'effect':842 'els':395,401,404,410,1338 'enabl':712 'end':1103,1105 'end-to-end':1102 'enforc':11,100,135,1004 'enum':558,566,580,581 'environ':1141 'err':958 'error':752,753,754,777,957 'eslint':1007,1280,1286,1673 'eslint-disable-next-lin':1279,1672 'eslint-plugin-unused-import':1006 'event':839,885 'eventnam':1621 'everi':1326 'exact':1347 'exampl':630,1706 'exceed':279 'expect':1069,1091 'expect.objectcontaining':1094 'expens':1163 'explain':1239,1294 'explicit':726,922,1596 'export':856 'expos':1132 'express':358 'extern':196 'extract':324,359,969,1472 'eye':1435 'face':1575 'fail':1462 'fals':608,622,868 'fc':795 'featur':1571 'feature.spec.ts':1110 'fetchus':800 'fetchuserdata':543 'file':482,486,626,632,636,643,647,651,655,1037,1108,1523,1528,1585,1696,1702 'filter':1270,1277,1641 'fireev':1051 'fireevent.click':1088 'first':144 'fix':1369,1376 'fixm':1361,1459 'flow':1114,1579 'focus':332,1040 'folder':627,660 'follow':66,108,125,814,1645 'forbidden':935,943,952 'form':1149 'formatdate.ts':645 'formatt':1682 'framer':206 'framer-mot':205 'function':46,278,326,329,379,443,462,490,514,516,529,534,541,542,544,553,555,685,701,731,758,826,857 'futur':1447 'generat':1203,1692,1695,1701 'getcarts':444,475 'getdiscount':380,463 'global':1625 'good':298,418,602,689,981,1293 'graph':1580,1601 'group':230,241 'guard':342 'guest':587,588 'guidelin':6,31,110,1152,1181 'hack':1385,1485 'handleclick':888,912 'handler':840,886,1491 'haspermiss':607 'header':212,1512,1517,1689 'helper':325 'high':377,1362,1371,1378 'hook':47,536,552,635,663,829,833,863 'html':1119 'id':1095,1292,1664 'idea':1436 'idempot':1495 'ident':1552 'idl':744 'ignor':1648,1681 'imag':159,1175 'implement':1045,1145,1158 'import':12,92,121,123,145,153,154,158,167,178,185,186,190,198,202,211,217,219,223,229,238,248,252,259,260,781,784,787,789,793,799,803,926,1003,1010,1048,1057,1444,1633 'incorrect':1365 'increment':1272 'index.ts':1524 'industri':274 'infer':1225,1259,1538 'info':1437,1443,1450 'inject':1628 'input':1127 'instead':1502 'intellig':1192 'intent':675,691,1023,1220,1235,1255,1415,1647 'interfac':511,519,520,823,848 'intern':209 'isauthent':604 'isexpand':865,890,914 'isload':548,872,900 'issu':57,1334 'issue/refresh/revoke':1555 'item':383,384,466,467 'items.length':391,397,406,412,476 'javascript':54 'jest':1031 'jest.fn':1081 'john':1071 'jsdoc':1665,1669 'jsx':846 'jwt':1332,1554 'kept':1451 'keystrok':1327 'kludg':1393 'known':1372 'larg':328,428,435,447,454 'length':495 'let':385 'level':1511 'leverag':732 'librari':175,1035,1055 'lifecycl':1333 'limit':15,281,309,484,1308 'line':237,487,491,494,1283,1676 'linter':1677 'llm':1544 'load':33,746,1160 'loading/error':897 'log':949,961 'logic':42,94,313 'login':1576,1611 'lookup':367,422 'low':419,1421,1425,1429 'magic':967 'main':907 'maintain':112,116 'make':1211 'manag':164,1557 'manual':1498,1616 'map':374,1198,1213,1355 'mark':919 'marker':1697,1703 'match':656 'max':485,489,493,576,983,992 'maximum':269 'mean':1489 'medium':430,437,448,459,1386,1394,1400,1408,1414 'memoiz':1162 'merchant':1313 'merg':318 'messi':1395 'mid':1469 'mid-request':1468 'mod':1618 'mode':714 'modul':1196,1260,1329,1482,1510,1540,1549,1563 'module-level':1509 'motion':203,207 'mui':176 'mui/material':181 'must':124,231,282,315,1382,1417 'name':16,61,363,499,665,666,971,1038,1066,1109 'narrow':723,755 'necessari':263 'need':1368,1397,1430 'nest':339 'network':1466 'never':1131 'new':45,678,694,776 'next':1282,1675 'next.js':152 'next/dynamic':1154 'next/image':161,1178 'next/navigation':157 'nois':1250,1276,1643 'note':1442 'noth':1337 'null':905 'number':446,688,704,771 'numbers/strings':968 'oauth':1577 'object':373,538 'obvious':1269 'onclick':911 'one':333 'onselect':852,860,891,1076,1080,1086,1087,1092 'opportun':1423,1427 'optim':1176,1420 'optimist':1315 'order':13,122,128,139,816 'output':97 'own':1330,1550 'packag':197 'pair':1433 'param':1288,1660 'paramet':1666 'pascalcas':504,633 'path':183 'pattern':129,351,811,936,1588 'payment':1304,1481 'paymentcard':517 'paymentmethod':523 'per':1312 'perf':1424 'perform':1151,1422,1426 'permiss':621,1559 'pipelin':1193,1534 'place':1209 'plan':1409,1440 'playwright':1100 'plugin':1008 'polymorph':348 'practic':20,708 'prd':1206 'prefix':591,640,1019 'premium':427,471 'prettier':1680 'prettier-ignor':1679 'primari':1527 'proc':686 'processpay':702 'processvalu':759 'product':945 'project':10,107,131 'promis':1668 'prop':822 'proper':757,948,1159 'properti':539 'protect':1147 'provid':1305 'public':730 'purpos':1197,1261,1542 'qualiti':23,56,102 'quick':291 'radix':177 'rate':1307 'rate-limit':1306 're':1170 're-rend':1169 'react':142,146,150,171,506,792,798,810,929,1033 'react-redux':170 'react.memo':1173 'react/next.js':26 'reactnod':796 'read':1188,1565 'readabl':114 'reader':1448 'recognis':1352 'recoil':165 'reduc':321 'redux':166,172 'refactor':40,58,284,310,316 'references/complexity.md':286,287,1711,1712 'refetch':624 'refresh':1335,1461 'regular':434,472 'relat':216 'reli':1654 'remedi':292 'remov':963,1001,1016,1419,1506 'render':908,1049,1068,1082,1123,1171 'replac':338,345,369 'report':1214 'req/s':1311 'request':1470 'requir':138,295,1027,1614,1619 'resolv':1594,1615 'rethink':1398 'retri':577,984,993,1477,1488 'retrycount':976,991 'return':337,416,453,458,460,477,727,766,772,844,895,901,904,909,1667,1670 'revers':1205 'review':38,52,1428 'revok':1336 'round':1323 'round-trip':1322 'rout':49,192 'rule':227 'run':1493 'safeti':711 'sanit':1118 'scanner':1351,1651 'schema':1130 'screen':1050 'screen.getbyrole':1089 'screen.getbytext':1070 'second':1432 'secret':1144 'secur':1116 'see':285,1710 'self':670 'self-docu':669 'sensit':1133 'separ':233,782 'servic':51 'session':1556 'setisexpand':866,889 'sever':1356,1358 'share':1476 'ship':1384 'short':1265,1516 'shortcut':1392 'shouldrefetch':610 'sibling/parent':218 'side':932,1138 'signific':1215 'silent':1463 'simplifi':306,356 'size':474,481,483 'skill':35,74,87,99,1607,1624 'skill-wednesday-dev' 'small':432,439,449,461 'smaller':331 'smell':1399 'snake':561 'solut':9,106,1687 'sort':245 'sourc':657 'source-wednesday-solutions' 'split':1157 'src/auth/index.ts':1547 'src/auth/session.ts':1612 'src/lib/db/client.ts':1627 'sso':1578 'stabl':1484 'standard':24,69,103,275 'state':163,736,836,877,898,1161,1267 'statement':371,845,939,941 'static':1591 'status':743,745,747,751,979,987,995,996 'stay':1602 'strategi':290,350 'strict':127,709,713 'stricter':272 'string':765,851 'stripe':1486 'structur':63,90,813,960,1228 'style':81 'substant':1230 'success':748 'suggest':1438 'surfac':1219 'switch':370 'tabl':368,423,426,479 'tag':1344,1348,1357 'tech':1200,1342 'technic':4,29 'temp':1413 'temporari':1416 'test':301,654,658,1026,1029,1034,1036,1054,1098,1106,1107,1111 'testing-librari':1053 'throw':775 'tier':469,480 'tobeinthedocu':1073 'todo':1407,1471 'tohavebeencalledwith':1093 'token':1341,1460,1568 'top':1520 'topic-agent-skills' 'topic-ai-agent-skills' 'topic-ai-skills' 'topic-claude-code' 'topic-copilot' 'topic-cursor' 'topic-frontend-skills' 'topic-vibe-coding' 'topic-vibe-coding-skills' 'touch':1340 'trigger':32 'trip':1324 'trivago/prettier-plugin-sort-imports':133 'true':549,605,611,619,625 'tsconfig.json':716 'twice':1494 'type':224,247,251,253,509,518,522,628,650,710,719,724,728,741,756,779,780,783,794,804,820,1671 'typeof':763,769 'typescript':18,53,91,140,250,375,512,540,568,601,672,706,737,788,847,923,951,973,1047,1262,1285,1458,1546,1604,1659 'typescript-eslint':1284 'u':683 'u.a':684 'ui':77,174 'unclear':674 'union':734,740 'unit':1028 'unknown':721,761,883 'unless':262 'unnecessari':1168 'unsupport':778 'unus':999,1002,1009,1017,1024 'updat':1316 'upper':560 'urgent':1412 'url':573 'use':72,82,132,246,335,349,366,503,531,559,639,720,725,738,916,924,947,959,1030,1099,1140,1153,1174,1217,1257,1314,1345,1359,1457,1500,1535,1586 'useauth':187,554 'useauth.ts':641 'useauthv2':1501 'useeffect':148,831 'uselocalstorag':556 'usememo':1166 'user':254,381,382,464,465,585,586,699,805,853,854,871,880,892,903,1042,1065,1113,1126,1291,1574,1663 'user-fac':1573 'user.bio':915 'user.firstname':881 'user.isactive':700 'user.ispremium':389,470 'user.lastname':882 'user.role':614 'user.types.ts':653 'usercard':858,1058,1062,1083 'usercardprop':849,861 'userid':850,859,874,1084,1289,1661 'userout':155 'userprofil':515,551 'userprofile.test.tsx':659 'userprofile.tsx':634 'userprofileprop':521 'userrol':582,806 'users.filter':682,698 'useselector':168 'usest':147,790,830,867,927 'useus':873 'util':220,642,950,1478 'v3':1508 'valid':1124 'valu':567,760,764,770,786 'value.tofixed':773 'value.touppercase':767 'variabl':364,530,535,546,590,1018,1142 'via':1629 'visual':80,96 'void':855 'webhook':1487 'wednesday':2,8,28,84,105,1606,1623,1686 'wednesday-design':83 'wednesday-dev':1 'wednesday-skil':1605,1622 'well':1208 'well-plac':1207 'wildcard':258 'within':239,817 'without':1543 'word':1246,1297 'work':1387,1410,1441 'workaround':1396 'write':37,43,1236,1567,1640 'wrong':1381 'x':687 'xxx':1377 'yes':1572 'yet':1375,1404 'z':199 'zod':201,1129","prices":[{"id":"1f5e731c-45b2-4b1a-9aa6-04ed26fc1652","listingId":"78ebc844-2120-48f0-abee-3fe34c28fb19","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"wednesday-solutions","category":"ai-agent-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:09:45.569Z"}],"sources":[{"listingId":"78ebc844-2120-48f0-abee-3fe34c28fb19","source":"github","sourceId":"wednesday-solutions/ai-agent-skills/wednesday-dev","sourceUrl":"https://github.com/wednesday-solutions/ai-agent-skills/tree/main/skills/wednesday-dev","isPrimary":false,"firstSeenAt":"2026-04-18T22:09:45.569Z","lastSeenAt":"2026-05-02T12:54:45.574Z"}],"details":{"listingId":"78ebc844-2120-48f0-abee-3fe34c28fb19","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"wednesday-solutions","slug":"wednesday-dev","github":{"repo":"wednesday-solutions/ai-agent-skills","stars":148,"topics":["agent-skills","ai-agent-skills","ai-skills","claude-code","copilot","cursor","frontend-skills","product-engineering-skills","vibe-coding","vibe-coding-skills"],"license":"mit","html_url":"https://github.com/wednesday-solutions/ai-agent-skills","pushed_at":"2026-04-24T12:57:49Z","description":"Pre-configured agent skills for Vibe Coded projects. These skills provide AI coding assistants (Claude Code, Cursor, etc.) with specific guidelines for code quality and design standards.","skill_md_sha":"5ac58bbe49e7b746b412de3b11e37529ae88c4df","skill_md_path":"skills/wednesday-dev/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/wednesday-solutions/ai-agent-skills/tree/main/skills/wednesday-dev"},"layout":"multi","source":"github","category":"ai-agent-skills","frontmatter":{"name":"wednesday-dev","license":"MIT","description":"Technical development guidelines for Wednesday Solutions projects. Enforces import ordering, complexity limits, naming conventions, TypeScript best practices, and code quality standards for React/Next.js applications.","compatibility":"Next.js 14+, React 18+, TypeScript 5+"},"skills_sh_url":"https://skills.sh/wednesday-solutions/ai-agent-skills/wednesday-dev"},"updatedAt":"2026-05-02T12:54:45.574Z"}}