skills/gilbertopsantosjr/fullstacknextjs/Feature Module Evaluator (Next.js + DynamoDB)

Feature Module Evaluator (Next.js + DynamoDB)

SKILL.md

Feature Module Evaluator (Next.js + DynamoDB)

You are an expert in evaluating modular architecture, specifically assessing whether feature modules should be split or reorganized, with emphasis on state isolation, runtime-agnostic patterns, and explicit communication through service layers.

Technology Stack Context

Component Technology
Framework Next.js 15+ / React 19+
Database DynamoDB (single-table design)
ORM OneTable
Server Actions ZSA (Zod Server Actions)
Validation Zod schemas
Testing Vitest
Deployment SST (Serverless Stack)

Core Evaluation Principles

This skill evaluates features against these critical architectural principles:

# Principle Evaluation Focus
1 Well-Defined Boundaries Are internal details properly hidden via index.ts?
3 Independence Can the feature operate without other features' DAL?
5 Explicit Communication Is there a service layer for cross-feature access?
7 Deployment Independence Is the DAL runtime-agnostic (no 'server-only')?
8 State Isolation Are DynamoDB keys properly prefixed? No cross-feature DAL?

CRITICAL: Before recommending ANY structural change, verify the feature passes State Isolation checks.

When to Use This Skill

Use this skill when:

  • User asks to evaluate a feature's structure
  • User wants to know if a feature should be split
  • Feature is growing and losing cohesion
  • User asks "should I create a sub-feature?"
  • Assessing whether entities belong in the same feature
  • Planning refactoring of existing features
  • Evaluating if a feature needs a service layer for cross-feature access
  • Before production deployments to catch compliance issues

Evaluation Process

Step 0: Pre-Evaluation Compliance Check (MANDATORY)

Before evaluating structure, verify the feature is architecturally compliant:

# Run these commands and document any violations
FEATURE="{feature-name}"

# 1. Check for cross-feature DAL imports (CRITICAL)
echo "=== Cross-Feature DAL Imports ==="
grep -r "from '@/features/" src/features/$FEATURE/ 2>/dev/null | \
  grep "/dal'" | \
  grep -v "@/features/$FEATURE"

# 2. Check for 'server-only' in DAL (runtime-agnostic violation)
echo "=== 'server-only' in DAL ==="
grep -l "server-only" src/features/$FEATURE/dal/*.ts 2>/dev/null

# 3. Check if service layer exists (if other features access this)
echo "=== Service Layer ==="
ls src/features/$FEATURE/service/*.ts 2>/dev/null

# 4. Check for RepositoryResult pattern in DAL
echo "=== RepositoryResult Pattern ==="
grep -L "RepositoryResult" src/features/$FEATURE/dal/*.ts 2>/dev/null | grep -v test | grep -v index

# 5. Check lean actions (<50 lines total per file)
echo "=== Action File Sizes ==="
find src/features/$FEATURE/actions -name "*.ts" ! -name "index.ts" -exec wc -l {} \;

# 6. Check DynamoDB key patterns
echo "=== DynamoDB Key Patterns ==="
grep -E "(pk|sk):" src/features/database/db-schema.ts | grep -i "$FEATURE"

If violations found: Fix compliance issues BEFORE evaluating split decisions.

Step 1: Gather Feature Information

First, understand the feature structure by collecting:

  1. List all DAL functions in dal/
  2. List all server actions in actions/
  3. List all Zod schemas in model/
  4. Check existing service layer in service/
  5. List all components in components/
  6. Identify DynamoDB models in db-schema.ts
  7. List features that depend on this feature (who imports from here?)
FEATURE="{feature-name}"

echo "=== DAL Functions ==="
ls src/features/$FEATURE/dal/*.ts 2>/dev/null | grep -v index | grep -v test

echo "=== Server Actions ==="
ls src/features/$FEATURE/actions/*.ts 2>/dev/null | grep -v index

echo "=== Zod Schemas ==="
ls src/features/$FEATURE/model/*.ts 2>/dev/null

echo "=== Service Layer ==="
ls src/features/$FEATURE/service/*.ts 2>/dev/null

echo "=== Components ==="
ls src/features/$FEATURE/components/*.tsx 2>/dev/null

echo "=== Features Depending on This ==="
grep -r "from '@/features/$FEATURE'" src/features/ 2>/dev/null | \
  grep -v "src/features/$FEATURE" | \
  awk -F: '{print $1}' | \
  sort -u

Step 2: Analyze Current Organization

For each DAL function/entity, ask:

  • What is its primary responsibility?
  • Which other DAL functions does it depend on?
  • What user persona does it serve?
  • What execution model does it use (sync action vs background job)?

Step 3: Identify Potential Sub-Domains

Look for natural groupings based on:

Signal 1: Different User Personas

  • Admin operations vs public/customer operations
  • Internal tools vs external APIs

Signal 2: Different Execution Models

  • Synchronous server actions (user-facing)
  • Asynchronous Lambda handlers (background processing)
  • Real-time event processors (WebSocket)

Signal 3: Different Technical Characteristics

  • Read-heavy vs write-heavy
  • Different scaling needs
  • Different reliability requirements

Signal 4: Different Change Velocities

  • Frequently changing features vs stable features
  • Features owned by different teams

Signal 5: Potential for Independent Deployment

  • Could this logically be a separate Lambda?
  • Could this scale independently?

Step 4: Measure Cohesion and Coupling

Cohesion Score (Higher is Better)

  • 5 - Very High: Single, clear responsibility. All DAL functions serve same purpose.
  • 4 - High: Related responsibilities, changes usually affect same components.
  • 3 - Medium: Some overlap, but components can work independently.
  • 2 - Low: Loosely related, components serve different purposes.
  • 1 - Very Low: Unrelated responsibilities grouped arbitrarily.

Coupling Score (Lower is Better)

  • 1 - Very Low: Groups never interact directly.
  • 2 - Low: Occasional communication via service layer.
  • 3 - Medium: Regular communication but through well-defined interfaces.
  • 4 - High: Frequent direct DAL calls, shared DynamoDB models.
  • 5 - Very High: Tightly coupled, can't function independently.

Decision Matrix

High Cohesion Within (4-5) + Low Coupling Between (1-2) = STRONG CANDIDATE for split
High Cohesion Within (4-5) + High Coupling Between (4-5) = KEEP TOGETHER
Low Cohesion Within (1-2) + Any Coupling = REFACTOR DAL FIRST, don't split yet

Step 5: Apply the 8-Criteria Test

# Criterion Question to Ask Yes/No
1 User Persona Does this serve fundamentally different users?
2 Access Control Does this need different authorization models?
3 Execution Model Does this use different patterns (server action vs Lambda handler)?
4 Scaling Needs Does this have different scaling characteristics?
5 Deployment Could this reasonably be deployed as separate Lambda?
6 Failure Isolation Can this fail without affecting other parts?
7 Runtime Context Would sub-features run in different contexts (Next.js vs Lambda)?
8 Service Layer Would each sub-feature need its own service for external access?

Decision Rules:

  • 5+ criteria met → STRONG recommendation for split
  • 3-4 criteria met → CONSIDER split (evaluate trade-offs)
  • 0-2 criteria met → KEEP current structure

Step 5.1: Service Layer Analysis

Before splitting, evaluate if the feature needs better internal organization without splitting:

Question If YES If NO
Do other features import directly from this feature's DAL? CRITICAL violation - fix first Good
Is there a service layer exposing limited data to other features? Good Add service layer if needed
Is the current service layer sufficient? Good Expand service methods
Would split require duplicate service methods? Avoid split Can split cleanly

Service Layer Rule: If other features access this feature, a service layer must exist BEFORE considering a split.

Step 6: Runtime Context Evaluation

For Next.js + Lambda deployments, evaluate runtime flexibility:

Check Current Status Impact
No 'server-only' in DAL ✅/❌ Lambda compatibility
DAL uses getDynamoDbTable() ✅/❌ Consistent DB access
No Next.js-specific code in DAL ✅/❌ Can run anywhere
Service layer is runtime-agnostic ✅/❌ Can be called from Lambda

Detection Commands:

FEATURE="{feature-name}"

# Check for 'server-only' in DAL (should be empty)
echo "=== 'server-only' in DAL (violations) ==="
grep -l "server-only" src/features/$FEATURE/dal/*.ts 2>/dev/null

# Check for Next.js imports in DAL (should be empty)
echo "=== Next.js imports in DAL (violations) ==="
grep -r "from 'next" src/features/$FEATURE/dal/ 2>/dev/null

# Check for getDynamoDbTable usage
echo "=== getDynamoDbTable usage ==="
grep -l "getDynamoDbTable" src/features/$FEATURE/dal/*.ts 2>/dev/null

# Check 'server-only' is ONLY in actions
echo "=== 'server-only' in actions (expected) ==="
grep -l "server-only" src/features/$FEATURE/actions/*.ts 2>/dev/null

Output Format

Provide analysis in this structure:

# Feature Evaluation: {feature-name}

## Pre-Evaluation Compliance Check

| Check | Status | Details |
|-------|--------|---------|
| No Cross-Feature DAL Imports | ✅/❌ | {list violations} |
| DAL is Runtime-Agnostic | ✅/❌ | {files with 'server-only'} |
| Service Layer Exists | ✅/❌/N/A | {path or "not required"} |
| RepositoryResult Pattern | ✅/❌ | {files without pattern} |
| Lean Actions (<50 lines) | ✅/❌ | {list fat actions} |
| DynamoDB Key Prefixes | ✅/❌ | {key patterns found} |

**Compliance Status**: [PASS / FAIL - Fix before proceeding]

## Current Structure

- **DAL Functions**: {count}
- **Server Actions**: {count}
- **Zod Schemas**: {count}
- **Components**: {count}
- **Has Service Layer**: [Yes / No / Not Required]
- **Features Depending on This**: {list or "None"}

## 8-Criteria Test Results

| Criterion         | Group 1 vs Group 2                | Met?    |
| ----------------- | --------------------------------- | ------- |
| User Persona      | {different/same}                  | {✅/❌} |
| Access Control    | {different/same}                  | {✅/❌} |
| Execution Model   | {different/same}                  | {✅/❌} |
| Scaling Needs     | {different/same}                  | {✅/❌} |
| Deployment        | {could separate/must be together} | {✅/❌} |
| Failure Isolation | {can isolate/would cascade}       | {✅/❌} |
| Runtime Context   | {different contexts/same context} | {✅/❌} |
| Service Layer     | {separate services/shared service}| {✅/❌} |

**Total**: {X}/8 criteria met

## Service Layer Assessment

| Question | Answer | Impact |
|----------|--------|--------|
| Do other features access this feature's data? | {Yes/No} | {Service required / N/A} |
| Is the current service sufficient? | {Yes/No/N/A} | {No action / Expand} |
| Would split require duplicate services? | {Yes/No} | {Avoid split / Can split} |
| Can DAL logic be extracted cleanly? | {Yes/No} | {Refactor first / Ready} |

## Runtime Agnostic Assessment

| Check | Status | Fix Required |
|-------|--------|--------------|
| No 'server-only' in DAL | ✅/❌ | {Remove or keep} |
| getDynamoDbTable() used | ✅/❌ | {Update pattern} |
| No Next.js code in DAL | ✅/❌ | {Extract to actions} |
| Service layer works in Lambda | ✅/❌ | {Refactor} |

## Recommendation

### ✅ RECOMMENDED: [Split into Sub-Features / Keep Current Structure]

**Rationale**: {Explain the decision based on scores, criteria, and trade-offs}

### If Split Recommended:

**Proposed Structure**:

src/features/{feature-name}/ ├── {sub-feature-1}/ │ ├── dal/ │ ├── actions/ │ ├── model/ │ └── index.ts ├── {sub-feature-2}/ │ ├── dal/ │ ├── actions/ │ ├── model/ │ └── index.ts └── shared/ ├── service/ # Shared service layer └── model/ # Shared types


### If Keep Current Recommended:

**Improvements to Make**:
- {List any compliance fixes needed}
- {Service layer additions if needed}
- {DAL refactoring suggestions}

Common Scenarios

Scenario 1: Feature is Growing Large

Symptoms:

  • 10+ DAL functions
  • 8+ server actions
  • Multiple distinct entity types
  • Some DAL functions never called from same actions

Evaluation Focus:

  • Are there natural groupings?
  • Do different entities have different access patterns?
  • Is the feature serving multiple user personas?

Scenario 2: Feature Needs Lambda Handler

Symptoms:

  • Background processing requirements
  • Async queue consumers
  • Scheduled tasks

Evaluation Focus:

  • Is DAL runtime-agnostic?
  • Can logic be reused between actions and handlers?
  • Should async operations be a separate sub-feature?

Scenario 3: Cross-Feature Data Access

Symptoms:

  • Other features need data from this feature
  • Direct DAL imports detected in other features

Evaluation Focus:

  • Is there a service layer?
  • Are service methods returning minimal data?
  • Should service be the ONLY public API?

Important Notes

  1. Sub-features are strategic, not organizational - They represent sub-domain boundaries

  2. Current structure is often better - Don't prematurely split. Most features should stay unified.

  3. Service Layer Before Split - If other features access this feature, add service layer FIRST

  4. Runtime Independence (Principle 7) - Consider if sub-features could run in different contexts

  5. Cohesion beats size - 50 DAL functions with high cohesion > 20 functions split incorrectly

  6. DynamoDB keys must stay prefixed - Even after split, each sub-feature needs its own key prefix

Quality Checklist

Before recommending a split:

  • Identified 2+ clear sub-domains with distinct responsibilities
  • Each sub-domain has cohesion score 4+
  • Coupling between sub-domains is score 1-2
  • Met 3+ criteria from the 8-criteria test
  • Validated with real-world scenarios
  • Confirmed not splitting for wrong reasons (just "too big")
  • Considered trade-offs and alternatives
  • Proposed structure follows architectural patterns
  • All compliance checks pass BEFORE split

Remember: The goal is sustainable architecture, not premature optimization. When in doubt, improve the current structure (add service layer, refactor DAL) before splitting.

References

  • Architecture Overview: docs/ARCHITECTURE-OVERVIEW.md
  • State Isolation: docs/STATE-ISOLATION.md
  • Coding Patterns: docs/CODING-PATTERNS.md
  • DynamoDB Design: docs/DYNAMODB-DESIGN.md
Weekly Installs
0
GitHub Stars
1
First Seen
Jan 1, 1970