Agent skill
core-theme-responsibilities
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.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/core-theme-responsibilities
SKILL.md
Core/Theme/Plugin Responsibilities Skill
Patterns for correctly assigning responsibilities between Core, Theme, and Plugin components.
The Fundamental Principle
"CORE ORCHESTRATES, EXTENSIONS REGISTER"
- Core: Provides mechanisms, initialization, processing, orchestration
- Theme/Plugin: Provides configuration, data, UI customization
Architecture Overview
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!)
When to Use This Skill
- Planning new features that span core and theme/plugin
- Reviewing architectural plans for responsibility assignment errors
- Debugging import loops caused by wrong responsibility placement
- Creating extension systems (scheduled actions, hooks, handlers)
Development Context Awareness
CRITICAL: Before applying patterns from this skill, check .claude/config/context.json to understand the development environment.
Context Detection
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
}
Two Development Contexts
┌─────────────────────────────────────────────────────────────────┐
│ 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/ │
└─────────────────────────────────────────────────────────────────┘
Path Translation Rules
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/ |
Consumer Context Rules
In consumer context (context.context === "consumer"):
- Core is READ-ONLY - Never attempt to create/modify in
core/ - Use existing core services - Import and use, don't duplicate
- Extend, don't replace - Create theme-specific extensions
- Theme migrations run after core - Use sequence numbers 1001+
When Consumer Needs Core Functionality
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:
- Implement a workaround in theme
- Request the enhancement upstream to NextSpark
Responsibility Assignment Rules
Quick Decision Table
| 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) |
Detailed Responsibility Matrix
| 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 |
Common Anti-Patterns
Anti-Pattern 1: Initialization in Theme
// ❌ 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
Anti-Pattern 2: Functions in Registry
// ❌ 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)
}
}
Anti-Pattern 3: Core Importing from Theme
// ❌ 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
Anti-Pattern 4: Theme Processing Data
// ❌ 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 }
}
Correct Patterns
Pattern 1: Extension Points
// 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 2: Feature Configuration
// 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 3: Handler Registration
// 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 })
}
Triple-Check Validation
Before Creating Any Plan
## 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? ✅
Red Flags (Warning Signs)
If the plan contains any of these, STOP AND REDESIGN:
- "Theme will initialize..." → Core must initialize
- "Core will import from theme..." → Prohibited
- "Registry will contain handler functions..." → Data-only
- "Theme will process the data..." → Core processes
- "Plugin will orchestrate..." → Core orchestrates (unless self-contained)
Checklist
Before finalizing any architectural plan:
- Core does not import from Theme or Plugin
- Theme does not import from another Theme
- Plugin does not import from another Plugin
- Initialization is in Core
- Processing is in Core
- Orchestration is in Core
- Registries are DATA-ONLY
- Theme/Plugin only provide configuration and registered handlers
- Build script is the only one that imports from contents/
Related Skills
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 patterns
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?