.claude/skills/core-theme-responsibilities/SKILL.md
Core/Theme/Plugin responsibility assignment system for this application. Covers dependency direction, responsibility assignment rules, common anti-patterns, and validation. **CRITICAL SKILL** - Read before creating any technical plan involving core and theme/plugin interaction. See also: `monorepo-architecture` skill for package distribution and dependency management.
npx skillsauth add NextSpark-js/nextspark core-theme-responsibilitiesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Patterns for correctly assigning responsibilities between Core, Theme, and Plugin components.
"CORE ORCHESTRATES, EXTENSIONS REGISTER"
RESPONSIBILITY FLOW:
┌─────────────────────────────────────────────────────────────────────────────┐
│ DEPENDENCY DIRECTION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ │
│ │ CORE │ │
│ │ (Orchestration) │ │
│ │ - Initialization │ │
│ │ - Processing │ │
│ │ - Services │ │
│ │ - Types/Interfaces │ │
│ └──────────▲──────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ THEME │ │ PLUGIN │ │ PLUGIN │ │
│ │ (Data) │◄──│ (Data) │ │ (Data) │ │
│ │ - Config │ │ - Config │ │ - Config │ │
│ │ - Handlers │ │ - Handlers │ │ - Handlers │ │
│ │ - UI │ │ - Logic* │ │ - Logic* │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ * Plugins can have self-contained logic that doesn't require Core import │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
IMPORT RULES:
✅ ALLOWED: ❌ PROHIBITED:
───────────────────────────────────── ─────────────────────────────────
• Core → Core • Core → Theme
• Theme → Core • Core → Plugin
• Plugin → Core • Theme → other Theme
• Theme → Plugin
• Theme → same Theme
• Plugin → same Plugin
• Plugin → other Plugin (allowed!)
CRITICAL: Before applying patterns from this skill, check .claude/config/context.json to understand the development environment.
const context = await Read('.claude/config/context.json')
if (context.context === 'monorepo') {
// Full access to core/, themes/, plugins/
// You ARE developing the NextSpark framework
} else if (context.context === 'consumer') {
// Core is READ-ONLY (installed via npm)
// You are developing an APPLICATION using NextSpark
}
┌─────────────────────────────────────────────────────────────────┐
│ MONOREPO CONTEXT │
│ (Developing NextSpark Framework) │
├─────────────────────────────────────────────────────────────────┤
│ • context.json: { "context": "monorepo" } │
│ • CAN create/modify in core/ │
│ • CAN create/modify in any theme │
│ • Focus: Abstract, reusable patterns for the platform │
│ • Examples: core/services/, core/migrations/, core/entities/ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ CONSUMER CONTEXT │
│ (Building App with NextSpark) │
├─────────────────────────────────────────────────────────────────┤
│ • context.json: { "context": "consumer" } │
│ • Core is READ-ONLY (in node_modules/) │
│ • CAN ONLY create in active theme and plugins │
│ • Focus: Project-specific features │
│ • Examples: contents/themes/{theme}/services/ │
└─────────────────────────────────────────────────────────────────┘
When a skill or pattern shows a core/ path, translate based on context:
| Pattern Shows | Monorepo Creates In | Consumer Creates In |
|---------------|--------------------|--------------------|
| core/lib/services/ | core/lib/services/ | contents/themes/{theme}/services/ |
| core/migrations/ | core/migrations/ | contents/themes/{theme}/migrations/ |
| core/entities/ | core/entities/ | contents/themes/{theme}/entities/ |
| core/components/ | core/components/ | contents/themes/{theme}/components/ |
| core/hooks/ | core/hooks/ | contents/themes/{theme}/hooks/ |
| core/lib/ | core/lib/ | contents/themes/{theme}/lib/ |
In consumer context (context.context === "consumer"):
core/If you discover that a feature truly requires core changes:
## Core Enhancement Request
**Feature:** [What you need]
**Why Core:** [Why it can't be in theme]
**Proposed Solution:** [How core could support this]
**Workaround (if possible):**
[Temporary theme-based solution]
Document this and either:
| Question | Answer | Responsibility | |----------|--------|----------------| | Does Core need to call this function? | YES | CORE | | Is it system initialization? | YES | CORE | | Does it process data from multiple sources? | YES | CORE | | Does it orchestrate a workflow? | YES | CORE | | Does it define shared interfaces/types? | YES | CORE | | Is it theme-specific configuration? | YES | THEME | | Is it data for a registry? | YES | THEME/PLUGIN | | Is it UI or visual components? | YES | THEME (or CORE base) |
| Functionality Type | Core | Theme | Plugin | Notes | |--------------------|:----:|:-----:|:------:|-------| | Feature initialization | ✅ | ❌ | ❌ | Core ALWAYS initializes | | Data processing | ✅ | ❌ | ❌ | Core processes, extensions provide data | | Workflow orchestration | ✅ | ❌ | ❌ | Core controls the flow | | Type/interface definitions | ✅ | ❌ | ❌ | Contracts live in Core | | Services with business logic | ✅ | ❌ | ⚠️ | Plugin only if self-contained | | Build scripts | ✅ | ❌ | ❌ | Only Core generates registries | | Feature configuration | ❌ | ✅ | ✅ | Data-only configs | | Registry data | ❌ | ✅ | ✅ | Imported only by build script | | Handlers/Callbacks | ❌ | ✅ | ✅ | Registered, not executed directly | | UI components | Base | ✅ | ✅ | Core provides base, extensions extend | | Styles/CSS | Base | ✅ | ❌ | Theme controls presentation | | Functionality extensions | ❌ | ✅ | ✅ | Register via registry |
// ❌ INCORRECT - Initialization in Theme
// contents/themes/default/scheduled-actions/init.ts
export function initializeScheduledActions() {
const actions = loadThemeActions()
actions.forEach(action => schedule(action))
}
// core/lib/startup.ts
import { initializeScheduledActions } from '@/contents/themes/default/...'
// ^^^ PROHIBITED - Core cannot import from Theme
// ✅ CORRECT - Initialization in Core
// core/lib/scheduled-actions/init.ts
import { SCHEDULED_ACTIONS_REGISTRY } from '@/core/lib/registries'
export function initializeScheduledActions() {
// Core reads from registry (data-only)
const actions = Object.values(SCHEDULED_ACTIONS_REGISTRY)
actions.forEach(action => scheduleAction(action))
}
// contents/themes/default/config/scheduled-actions.ts
export const THEME_SCHEDULED_ACTIONS = [
{ slug: 'daily-report', cron: '0 9 * * *' }
]
// ^^^ This is DATA, imported only by build script
// ❌ INCORRECT - Functions in Registry
export const HANDLERS_REGISTRY = {
'process-payment': async (data) => {
// Processing logic
await chargeCard(data.cardId, data.amount)
}
}
// ✅ CORRECT - References in Registry, logic in Services
// Registry (data-only)
export const HANDLERS_REGISTRY = {
'process-payment': {
slug: 'process-payment',
handlerPath: 'billing/process-payment',
description: 'Process a payment'
}
}
// Service (logic)
// core/lib/services/handler.service.ts
import { HANDLER_IMPLEMENTATIONS } from '@/core/lib/registries/handler-implementations'
export class HandlerService {
static async execute(slug: string, data: unknown) {
const handler = HANDLER_IMPLEMENTATIONS[slug]
return handler(data)
}
}
// ❌ INCORRECT - Core importing from Theme
// core/lib/billing/plans.ts
import { CUSTOM_PLANS } from '@/contents/themes/default/config/plans'
export function getPlan(slug: string) {
return PLANS[slug] || CUSTOM_PLANS[slug]
}
// ✅ CORRECT - Core reads from unified registry
// core/lib/billing/plans.ts
import { BILLING_REGISTRY } from '@/core/lib/registries/billing-registry'
export function getPlan(slug: string) {
return BILLING_REGISTRY.plans[slug]
}
// The build script combines core plans + theme plans into BILLING_REGISTRY
// ❌ INCORRECT - Theme processing data
// contents/themes/default/lib/scheduled-actions/processor.ts
export async function processScheduledActions() {
const actions = await db.query.scheduledActions.findMany()
for (const action of actions) {
await executeAction(action)
}
}
// ✅ CORRECT - Core processes, Theme configures
// core/lib/scheduled-actions/processor.ts (CORE)
export async function processScheduledActions() {
const actions = await db.query.scheduledActions.findMany()
for (const action of actions) {
await executeAction(action)
}
}
// contents/themes/default/config/scheduled-actions.ts (THEME - data only)
export const themeScheduledActions = {
'cleanup-expired': { cron: '0 0 * * *', enabled: true }
}
// PATTERN: Core defines extension points, Theme/Plugin register
// 1. Core defines types and mechanism
// core/lib/hooks/types.ts
export interface HookDefinition {
slug: string
event: string
priority: number
}
// core/lib/hooks/service.ts
import { HOOKS_REGISTRY } from '@/core/lib/registries/hooks-registry'
export class HooksService {
static trigger(event: string, data: unknown) {
const hooks = Object.values(HOOKS_REGISTRY)
.filter(h => h.event === event)
.sort((a, b) => b.priority - a.priority)
for (const hook of hooks) {
const handler = this.getHandler(hook.slug)
handler(data)
}
}
}
// 2. Theme registers hooks (DATA)
// contents/themes/default/config/hooks.ts
export const THEME_HOOKS: HookDefinition[] = [
{ slug: 'log-user-login', event: 'user.login', priority: 10 }
]
// 3. Theme provides handlers (registered via registry)
// contents/themes/default/handlers/hooks/log-user-login.ts
export const logUserLoginHandler = async (data: UserLoginEvent) => {
console.log(`User logged in: ${data.userId}`)
}
// This handler is imported by build script → HANDLER_IMPLEMENTATIONS registry
// PATTERN: Core provides feature, Theme configures
// 1. Core defines the feature with defaults
// core/lib/features/notifications.ts
import { NOTIFICATIONS_CONFIG_REGISTRY } from '@/core/lib/registries'
const DEFAULT_CONFIG = {
emailEnabled: true,
pushEnabled: false,
channels: ['email']
}
export function getNotificationConfig() {
// Merge: defaults ← theme config
return {
...DEFAULT_CONFIG,
...NOTIFICATIONS_CONFIG_REGISTRY.themeConfig
}
}
// 2. Theme provides specific configuration
// contents/themes/default/config/notifications.ts
export const themeNotificationsConfig = {
pushEnabled: true,
channels: ['email', 'push', 'sms']
}
// PATTERN: Theme provides handlers, Core executes them
// 1. Theme defines handlers (functions, but registered)
// contents/themes/default/handlers/scheduled/send-daily-report.ts
import type { ScheduledHandler } from '@/core/lib/scheduled-actions/types'
export const sendDailyReportHandler: ScheduledHandler = async (context) => {
const users = await context.db.query.users.findMany()
for (const user of users) {
await sendEmail(user.email, 'Daily Report', generateReport())
}
}
// 2. Build script generates implementations registry
// core/lib/registries/scheduled-handler-implementations.ts (AUTO-GENERATED)
import { sendDailyReportHandler } from '@/contents/themes/default/handlers/scheduled/send-daily-report'
export const SCHEDULED_HANDLER_IMPLEMENTATIONS = {
'send-daily-report': sendDailyReportHandler
}
// 3. Core executes handlers from registry
// core/lib/scheduled-actions/executor.ts
import { SCHEDULED_HANDLER_IMPLEMENTATIONS } from '@/core/lib/registries'
export async function executeScheduledAction(action: ScheduledAction) {
const handler = SCHEDULED_HANDLER_IMPLEMENTATIONS[action.handlerSlug]
if (!handler) throw new Error(`Handler not found: ${action.handlerSlug}`)
await handler({ db, action })
}
## RESPONSIBILITIES CHECKLIST (MANDATORY)
### 1. Function Identification
For each function/component, answer:
| Function | Who calls it? | What does it do? | Location |
|----------|---------------|------------------|----------|
| `initFeature()` | Core startup | Initializes | CORE |
| `processData()` | Core service | Processes | CORE |
| `featureConfig` | Build script | Data | THEME |
### 2. Import Verification
- [ ] Does Core import from Theme? → ❌ REDESIGN
- [ ] Does Core import from Plugin? → ❌ REDESIGN
- [ ] Does Theme import from another Theme? → ❌ REDESIGN
- [ ] Does Plugin import from another Plugin? → ✅ ALLOWED (use peerDependencies)
### 3. Registry Verification
- [ ] Are registries DATA-ONLY? → ✅
- [ ] Are there functions in registries? → ❌ Extract to Services
### 4. Responsibility Verification
- [ ] Initialization → In Core? ✅
- [ ] Processing → In Core? ✅
- [ ] Orchestration → In Core? ✅
- [ ] Configuration → In Theme/Plugin? ✅
- [ ] UI → In Theme? ✅
If the plan contains any of these, STOP AND REDESIGN:
Before finalizing any architectural plan:
monorepo-architecture - CRITICAL: Package hierarchy, dependency rules, Model B distributionregistry-system - Data-only registry patternsscope-enforcement - Path-level scope validationservice-layer - Service patterns in Coreplugins - Plugin development patternsdevelopment
Zod validation patterns for this Next.js application. Covers schema definition, API validation, form integration, error formatting, and type inference. Use this skill when implementing validation for APIs, forms, or entity schemas.
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
testing
Test coverage metrics and registry system for this Next.js application. Covers FEATURE_REGISTRY, FLOW_REGISTRY, TAGS_REGISTRY, and coverage metrics interpretation. Use this skill when evaluating test coverage, identifying gaps, or planning testing priorities.
development
TanStack Query (React Query) patterns for data fetching in this Next.js application. Covers useQuery, useMutation, optimistic updates, cache invalidation, and anti-patterns. Use this skill when implementing data fetching or state management with server data.