🎯

create-e2e-tests

🎯Skill

from gilbertopsantosjr/fullstacknextjs

VibeIndex|
What it does

Generates comprehensive e2e and integration tests with strict isolation, mocking cross-feature dependencies, and following modular testing principles for Next.js and DynamoDB projects.

πŸ“¦

Part of

gilbertopsantosjr/fullstacknextjs(14 items)

create-e2e-tests

Installation

1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Creates e2e and integration tests following project patterns and conventions with emphasis on test independence, state isolation verification, and proper cross-feature mocking. Adapted for Vitest, DynamoDB Local, and ZSA server actions.

Overview

# Create E2E Tests (Next.js + DynamoDB + Vitest)

Technology Stack

| Component | Technology |

|-----------|------------|

| Test Runner | Vitest |

| Database | DynamoDB Local |

| HTTP Testing | SuperTest (for API routes) |

| Mocking | Vitest mocks, MSW (for HTTP) |

| Test Data | @faker-js/faker |

| Assertions | Vitest expect |

Core Testing Principles

This skill enforces these critical testing principles aligned with modular architecture:

| Principle | How Applied in Tests |

|-----------|---------------------|

| Test Independence | Each feature's tests run in complete isolation |

| State Isolation | Never import from another feature's DAL in tests |

| Explicit Communication | Mock cross-feature interactions via service layer, not DAL |

| Replaceability | Tests don't depend on other features' internal implementations |

CRITICAL: Cross-feature DAL imports in test files are violations, even for test setup.

Quick Start

When creating tests, follow this workflow:

  1. Determine the feature and test type (unit/integration/e2e)
  2. Verify test isolation (no cross-feature DAL imports)
  3. Create test file co-located with source (.test.ts)
  4. Set up DynamoDB Local test helpers
  5. Configure lifecycle hooks (beforeAll, afterAll, beforeEach)
  6. Write tests following Arrange-Act-Assert pattern
  7. Mock cross-feature dependencies via service layer
  8. Use @faker-js/faker for test data
  9. Clean up DynamoDB tables after each test
  10. Run state isolation verification before committing

File Location Pattern

Tests are co-located with source files:

```

src/features//

β”œβ”€β”€ dal/

β”‚ β”œβ”€β”€ create_account.ts

β”‚ β”œβ”€β”€ create_account.test.ts # Co-located DAL test

β”‚ β”œβ”€β”€ find_account_by_id.ts

β”‚ └── find_account_by_id.test.ts # Co-located DAL test

β”œβ”€β”€ actions/

β”‚ β”œβ”€β”€ create-account.ts

β”‚ └── create-account.test.ts # Co-located action test

└── service/

β”œβ”€β”€ accounts-service.ts

└── accounts-service.test.ts # Co-located service test

```

Key Points:

  • Test files use .test.ts suffix
  • Tests live next to the code they test
  • NO separate __test__ folder pattern

Required Imports Template

DAL Tests (Integration with DynamoDB Local)

```typescript

import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { setupTestDb, cleanupTestDb, clearTestData } from '@/test/db-helpers'

import { createAccount } from './create_account'

import { findAccountById } from './find_account_by_id'

```

Action Tests

```typescript

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { createAccountAction } from './create-account'

```

Service Layer Tests

```typescript

import { describe, it, expect, vi, beforeEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { accountsService } from './accounts-service'

import * as dalModule from '../dal'

```

DynamoDB Local Setup

Test Database Helpers (`src/test/db-helpers.ts`)

```typescript

import { DynamoDBClient } from '@aws-sdk/client-dynamodb'

import { Table } from 'dynamodb-onetable'

import { schema } from '@/features/database/db-schema'

// Use DynamoDB Local for tests

const testClient = new DynamoDBClient({

endpoint: process.env.DYNAMODB_LOCAL_ENDPOINT || 'http://localhost:8000',

region: 'local',

credentials: {

accessKeyId: 'local',

secretAccessKey: 'local',

},

})

let testTable: Table

export const setupTestDb = async () => {

testTable = new Table({

client: testClient,

name: process.env.TEST_TABLE_NAME || 'test-table',

schema,

partial: true,

})

// Create table if it doesn't exist

try {

await testTable.createTable()

} catch (error: any) {

if (error.name !== 'ResourceInUseException') {

throw error

}

}

return testTable

}

export const cleanupTestDb = async () => {

// Table cleanup is handled per-test

}

export const clearTestData = async (modelName: string) => {

const Model = testTable.getModel(modelName)

const items = await Model.scan({})

for (const item of items) {

await Model.remove(item)

}

}

export const getTestTable = () => testTable

```

Vitest Config for DynamoDB Local (`vitest.config.ts`)

```typescript

import { defineConfig } from 'vitest/config'

import path from 'path'

export default defineConfig({

test: {

globals: true,

environment: 'node',

setupFiles: ['./src/test/setup.ts'],

include: ['*/.test.ts'],

exclude: ['node_modules', 'dist'],

coverage: {

provider: 'v8',

reporter: ['text', 'json', 'html'],

exclude: ['*/.test.ts', '/test/'],

},

},

resolve: {

alias: {

'@': path.resolve(__dirname, './src'),

},

},

})

```

Test Setup File (`src/test/setup.ts`)

```typescript

import { beforeAll, afterAll } from 'vitest'

import { setupTestDb, cleanupTestDb } from './db-helpers'

beforeAll(async () => {

await setupTestDb()

})

afterAll(async () => {

await cleanupTestDb()

})

```

DAL Test Pattern

```typescript

// dal/account.test.ts

import { describe, it, expect, beforeEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { clearTestData } from '@/test/db-helpers'

import { createAccount } from './create_account'

import { findAccountById } from './find_account_by_id'

import { findAccountsByUser } from './find_accounts_by_user'

import { updateAccount } from './update_account'

import { deleteAccount } from './delete_account'

describe('Account DAL', () => {

const testUserId = faker.string.ulid()

beforeEach(async () => {

await clearTestData('Account')

})

describe('createAccount', () => {

it('creates a new account successfully', async () => {

// Arrange

const input = {

userId: testUserId,

name: faker.company.name(),

description: faker.lorem.sentence(),

}

// Act

const result = await createAccount(input)

// Assert

expect(result.success).toBe(true)

expect(result.data).toMatchObject({

name: input.name,

description: input.description,

userId: testUserId,

status: 'active',

})

expect(result.data?.id).toBeDefined()

expect(result.data?.createdAt).toBeDefined()

})

it('returns validation error for invalid input', async () => {

// Arrange

const input = {

userId: testUserId,

name: '', // Invalid: empty name

}

// Act

const result = await createAccount(input)

// Assert

expect(result.success).toBe(false)

expect(result.code).toBe('VALIDATION_ERROR')

})

it('returns validation error for missing userId', async () => {

// Arrange

const input = {

name: faker.company.name(),

}

// Act

const result = await createAccount(input as any)

// Assert

expect(result.success).toBe(false)

expect(result.code).toBe('VALIDATION_ERROR')

})

})

describe('findAccountById', () => {

it('finds an existing account', async () => {

// Arrange

const createResult = await createAccount({

userId: testUserId,

name: faker.company.name(),

})

const accountId = createResult.data!.id

// Act

const result = await findAccountById(accountId, testUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data?.id).toBe(accountId)

expect(result.data?.userId).toBe(testUserId)

})

it('returns null for non-existent account', async () => {

// Act

const result = await findAccountById(faker.string.ulid(), testUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data).toBeNull()

})

it('returns null when userId does not match', async () => {

// Arrange

const createResult = await createAccount({

userId: testUserId,

name: faker.company.name(),

})

const accountId = createResult.data!.id

const differentUserId = faker.string.ulid()

// Act

const result = await findAccountById(accountId, differentUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data).toBeNull()

})

})

describe('findAccountsByUser', () => {

it('returns empty array when no accounts exist', async () => {

// Act

const result = await findAccountsByUser(testUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data?.items).toEqual([])

expect(result.data?.hasMore).toBe(false)

})

it('returns all accounts for user', async () => {

// Arrange

await createAccount({ userId: testUserId, name: 'Account 1' })

await createAccount({ userId: testUserId, name: 'Account 2' })

await createAccount({ userId: testUserId, name: 'Account 3' })

// Act

const result = await findAccountsByUser(testUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data?.items).toHaveLength(3)

})

it('returns paginated results', async () => {

// Arrange

await createAccount({ userId: testUserId, name: 'Account 1' })

await createAccount({ userId: testUserId, name: 'Account 2' })

await createAccount({ userId: testUserId, name: 'Account 3' })

// Act - First page

const page1 = await findAccountsByUser(testUserId, { limit: 2 })

// Assert

expect(page1.success).toBe(true)

expect(page1.data?.items).toHaveLength(2)

expect(page1.data?.hasMore).toBe(true)

expect(page1.data?.nextCursor).toBeDefined()

// Act - Second page

const page2 = await findAccountsByUser(testUserId, {

limit: 2,

cursor: page1.data!.nextCursor,

})

// Assert

expect(page2.success).toBe(true)

expect(page2.data?.items).toHaveLength(1)

expect(page2.data?.hasMore).toBe(false)

})

it('does not return accounts from other users', async () => {

// Arrange

const otherUserId = faker.string.ulid()

await createAccount({ userId: testUserId, name: 'My Account' })

await createAccount({ userId: otherUserId, name: 'Other Account' })

// Act

const result = await findAccountsByUser(testUserId)

// Assert

expect(result.success).toBe(true)

expect(result.data?.items).toHaveLength(1)

expect(result.data?.items[0].name).toBe('My Account')

})

})

describe('updateAccount', () => {

it('updates an existing account', async () => {

// Arrange

const createResult = await createAccount({

userId: testUserId,

name: 'Original Name',

})

const accountId = createResult.data!.id

// Act

const result = await updateAccount(accountId, testUserId, {

name: 'Updated Name',

status: 'inactive',

})

// Assert

expect(result.success).toBe(true)

expect(result.data?.name).toBe('Updated Name')

expect(result.data?.status).toBe('inactive')

})

it('returns error for non-existent account', async () => {

// Act

const result = await updateAccount(

faker.string.ulid(),

testUserId,

{ name: 'Updated' }

)

// Assert

expect(result.success).toBe(false)

expect(result.code).toBe('ACCOUNT_NOT_FOUND')

})

})

describe('deleteAccount', () => {

it('deletes an existing account', async () => {

// Arrange

const createResult = await createAccount({

userId: testUserId,

name: faker.company.name(),

})

const accountId = createResult.data!.id

// Act

const result = await deleteAccount(accountId, testUserId)

// Assert

expect(result.success).toBe(true)

// Verify deleted

const findResult = await findAccountById(accountId, testUserId)

expect(findResult.data).toBeNull()

})

})

})

```

Server Action Test Pattern

```typescript

// actions/create-account.test.ts

import { describe, it, expect, vi, beforeEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { createAccountAction } from './create-account'

import * as dalModule from '../dal'

// Mock the DAL module

vi.mock('../dal', () => ({

createAccount: vi.fn(),

}))

describe('createAccountAction', () => {

const mockUserId = faker.string.ulid()

const mockCtx = {

user: { id: mockUserId },

}

beforeEach(() => {

vi.clearAllMocks()

})

it('creates account successfully', async () => {

// Arrange

const input = {

name: faker.company.name(),

description: faker.lorem.sentence(),

}

const mockAccount = {

id: faker.string.ulid(),

...input,

userId: mockUserId,

status: 'active',

createdAt: new Date().toISOString(),

updatedAt: new Date().toISOString(),

}

vi.mocked(dalModule.createAccount).mockResolvedValue({

success: true,

data: mockAccount,

})

// Act

const result = await createAccountAction.handler({

input,

ctx: mockCtx,

})

// Assert

expect(dalModule.createAccount).toHaveBeenCalledWith({

...input,

userId: mockUserId,

})

expect(result).toEqual(mockAccount)

})

it('throws error when DAL returns failure', async () => {

// Arrange

const input = { name: faker.company.name() }

vi.mocked(dalModule.createAccount).mockResolvedValue({

success: false,

error: 'Database error',

code: 'CREATE_ACCOUNT_ERROR',

})

// Act & Assert

await expect(

createAccountAction.handler({ input, ctx: mockCtx })

).rejects.toThrow('Database error')

})

it('validates input with Zod schema', async () => {

// Arrange

const invalidInput = { name: '' } // Empty name should fail

// Act & Assert

await expect(

createAccountAction.handler({ input: invalidInput, ctx: mockCtx })

).rejects.toThrow()

})

})

```

Service Layer Test Pattern

```typescript

// service/accounts-service.test.ts

import { describe, it, expect, vi, beforeEach } from 'vitest'

import { faker } from '@faker-js/faker'

import { accountsService } from './accounts-service'

import * as dalModule from '../dal'

// Mock the DAL module

vi.mock('../dal', () => ({

findAccountById: vi.fn(),

findAccountsByUser: vi.fn(),

}))

describe('accountsService', () => {

const testUserId = faker.string.ulid()

beforeEach(() => {

vi.clearAllMocks()

})

describe('getAccountById', () => {

it('returns account summary when found', async () => {

// Arrange

const mockAccount = {

id: faker.string.ulid(),

name: faker.company.name(),

status: 'active',

description: faker.lorem.sentence(),

userId: testUserId,

createdAt: new Date().toISOString(),

updatedAt: new Date().toISOString(),

}

vi.mocked(dalModule.findAccountById).mockResolvedValue({

success: true,

data: mockAccount,

})

// Act

const result = await accountsService.getAccountById(mockAccount.id, testUserId)

// Assert

expect(result).toEqual({

id: mockAccount.id,

name: mockAccount.name,

status: mockAccount.status,

})

// Verify only necessary fields are exposed

expect(result).not.toHaveProperty('description')

expect(result).not.toHaveProperty('userId')

})

it('returns null when account not found', async () => {

// Arrange

vi.mocked(dalModule.findAccountById).mockResolvedValue({

success: true,

data: null,

})

// Act

const result = await accountsService.getAccountById(

faker.string.ulid(),

testUserId

)

// Assert

expect(result).toBeNull()

})

it('returns null when DAL returns error', async () => {

// Arrange

vi.mocked(dalModule.findAccountById).mockResolvedValue({

success: false,

error: 'Database error',

code: 'FIND_ERROR',

})

// Act

const result = await accountsService.getAccountById(

faker.string.ulid(),

testUserId

)

// Assert

expect(result).toBeNull()

})

})

describe('accountExists', () => {

it('returns true when account exists', async () => {

// Arrange

vi.mocked(dalModule.findAccountById).mockResolvedValue({

success: true,

data: { id: faker.string.ulid() } as any,

})

// Act

const result = await accountsService.accountExists(

faker.string.ulid(),

testUserId

)

// Assert

expect(result).toBe(true)

})

it('returns false when account does not exist', async () => {

// Arrange

vi.mocked(dalModule.findAccountById).mockResolvedValue({

success: true,

data: null,

})

// Act

const result = await accountsService.accountExists(

faker.string.ulid(),

testUserId

)

// Assert

expect(result).toBe(false)

})

})

})

```

Cross-Feature Mocking Pattern

CRITICAL: Never import from another feature's DAL. Mock the service layer instead.

When Feature A Tests Need Feature B Data

BAD:

```typescript

// In billing feature test

import { createAccount } from '@/features/accounts/dal' // VIOLATION!

it('creates invoice for account', async () => {

await createAccount({ ... }) // Direct DAL access

})

```

GOOD:

```typescript

// In billing feature test

import { accountsService } from '@/features/accounts'

import { vi } from 'vitest'

vi.mock('@/features/accounts', () => ({

accountsService: {

getAccountById: vi.fn(),

accountExists: vi.fn(),

},

}))

it('creates invoice for account', async () => {

// Mock the service layer response

vi.mocked(accountsService.accountExists).mockResolvedValue(true)

vi.mocked(accountsService.getAccountById).mockResolvedValue({

id: 'account-123',

name: 'Test Account',

status: 'active',

})

// Now test billing logic

const result = await createInvoice({ accountId: 'account-123', ... })

expect(result.success).toBe(true)

})

```

HTTP Mocking with MSW (for External APIs)

```typescript

// test/mocks/handlers.ts

import { http, HttpResponse } from 'msw'

export const handlers = [

// Mock Stripe API

http.post('https://api.stripe.com/v1/customers', () => {

return HttpResponse.json({

id: 'cus_test123',

email: 'test@example.com',

})

}),

// Mock SendGrid API

http.post('https://api.sendgrid.com/v3/mail/send', () => {

return HttpResponse.json({ message: 'success' })

}),

]

```

```typescript

// test/setup.ts

import { setupServer } from 'msw/node'

import { handlers } from './mocks/handlers'

import { beforeAll, afterAll, afterEach } from 'vitest'

const server = setupServer(...handlers)

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

afterAll(() => server.close())

afterEach(() => server.resetHandlers())

```

Test Lifecycle Hooks

beforeAll - Setup Database

```typescript

beforeAll(async () => {

await setupTestDb()

})

```

afterAll - Cleanup Database

```typescript

afterAll(async () => {

await cleanupTestDb()

})

```

beforeEach - Clear Test Data

```typescript

beforeEach(async () => {

await clearTestData('Account')

vi.clearAllMocks()

})

```

afterEach - Reset Mocks

```typescript

afterEach(() => {

vi.restoreAllMocks()

})

```

Test Data Factory Pattern

```typescript

// test/factories/account-factory.ts

import { faker } from '@faker-js/faker'

import type { AccountEntity, CreateAccountInput } from '@/features/accounts/model/account-schemas'

export const accountFactory = {

build(overrides: Partial = {}): AccountEntity {

return {

id: faker.string.ulid(),

userId: faker.string.ulid(),

name: faker.company.name(),

description: faker.lorem.sentence(),

status: 'active',

metadata: {},

createdAt: new Date().toISOString(),

updatedAt: new Date().toISOString(),

...overrides,

}

},

buildCreateInput(overrides: Partial = {}): CreateAccountInput {

return {

name: faker.company.name(),

description: faker.lorem.sentence(),

...overrides,

}

},

}

```

Usage:

```typescript

import { accountFactory } from '@/test/factories/account-factory'

it('creates account', async () => {

const input = accountFactory.buildCreateInput({ name: 'Custom Name' })

const result = await createAccount({ ...input, userId: testUserId })

expect(result.success).toBe(true)

})

```

Anti-Patterns to Avoid

Cross-Feature DAL Imports in Tests (CRITICAL)

BAD:

```typescript

// In billing test

import { createAccount } from '@/features/accounts/dal'

```

GOOD:

```typescript

// Mock the service layer instead

vi.mock('@/features/accounts', () => ({

accountsService: { getAccountById: vi.fn() },

}))

```

Using Jest Instead of Vitest

BAD:

```typescript

import { jest } from '@jest/globals'

jest.mock(...)

```

GOOD:

```typescript

import { vi } from 'vitest'

vi.mock(...)

```

Tests in `__test__` Folder

BAD:

```

src/features/accounts/__test__/create-account.test.ts

```

GOOD:

```

src/features/accounts/dal/create_account.test.ts

```

Missing RepositoryResult Assertions

BAD:

```typescript

it('creates account', async () => {

const result = await createAccount(input)

expect(result.id).toBeDefined() // Assumes success

})

```

GOOD:

```typescript

it('creates account', async () => {

const result = await createAccount(input)

expect(result.success).toBe(true)

expect(result.data?.id).toBeDefined()

})

```

Test Isolation Verification

Detection Command for Test Files

```bash

# Find cross-feature DAL imports in test files

grep -r "from '@/features/[^']dal'" src/features//.test.ts | \

awk -F: '{

match($1, /features\/([^/]+)/, feat);

match($2, /features\/([^/]+)\/dal/, imported);

if (feat[1] != imported[1] && imported[1] != "") {

print "VIOLATION: " $1 " imports from " imported[1] "/dal"

}

}'

```

Expected: Empty output

Verification Script

```bash

#!/bin/bash

# verify-test-isolation.sh

FEATURE=$1

echo "Verifying test isolation for: $FEATURE"

# Check for cross-feature DAL imports in tests

VIOLATIONS=$(grep -r "from '@/features/" src/features/$FEATURE/*/.test.ts 2>/dev/null | \

grep "/dal'" | \

grep -v "@/features/$FEATURE")

if [ ! -z "$VIOLATIONS" ]; then

echo "CRITICAL: Cross-feature DAL imports found in tests:"

echo "$VIOLATIONS"

exit 1

fi

echo "Test isolation verified"

```

Coverage Requirements

| Metric | Minimum | Target |

|--------|---------|--------|

| Branches | 70% | 80% |

| Functions | 75% | 85% |

| Lines | 75% | 85% |

| Statements | 75% | 85% |

Priority Order for Coverage

  1. DAL functions (High) - Core data operations
  2. Service layer (High) - Cross-feature contracts
  3. Server actions (Medium) - Input validation
  4. Error handling (Medium) - Edge cases

CI/CD Integration

GitHub Actions Workflow

```yaml

name: Tests

on: [push, pull_request]

jobs:

test:

runs-on: ubuntu-latest

services:

dynamodb-local:

image: amazon/dynamodb-local:latest

ports:

- 8000:8000

steps:

- uses: actions/checkout@v4

- name: Setup Node.js

uses: actions/setup-node@v4

with:

node-version: '20'

cache: 'npm'

- name: Install dependencies

run: npm ci

- name: Verify Test Isolation

run: |

VIOLATIONS=$(grep -r "from '@/features/" src/features/*/.test.ts 2>/dev/null | \

grep "/dal'" | \

awk -F: '{

match($1, /features\/([^/]+)/, feat);

match($2, /features\/([^/]+)\/dal/, imported);

if (feat[1] != imported[1] && imported[1] != "") {

print "VIOLATION: " $1

}

}')

if [ ! -z "$VIOLATIONS" ]; then

echo "$VIOLATIONS"

exit 1

fi

- name: Run Tests

run: npm test

env:

DYNAMODB_LOCAL_ENDPOINT: http://localhost:8000

TEST_TABLE_NAME: test-table

- name: Upload Coverage

uses: codecov/codecov-action@v4

with:

files: ./coverage/lcov.info

```

Running Tests

```bash

# Run all tests

npx vitest

# Run tests for specific feature

npx vitest src/features/accounts

# Run tests in watch mode

npx vitest --watch

# Run with coverage

npx vitest --coverage

# Run specific test file

npx vitest src/features/accounts/dal/create_account.test.ts

```

References

  • Vitest Documentation: https://vitest.dev
  • DynamoDB Local: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html
  • MSW Documentation: https://mswjs.io
  • Testing Patterns: docs/TESTING-PATTERNS.md
  • State Isolation: docs/STATE-ISOLATION.md

More from this repository10

🎯
tanstack-react-query🎯Skill

Provides expert React Query guidance for efficient data fetching, mutations, and server state management with seamless server action integration.

🎯
feature-architecture🎯Skill

Designs and structures feature-based architecture for scalable and modular Next.js applications with organized component and module layouts.

🎯
bun-aws-lambda🎯Skill

Deploys and optimizes AWS Lambda functions using Bun runtime, enabling efficient serverless development with TypeScript support and multiple event source integrations.

🎯
dynamodb-onetable🎯Skill

Simplifies DynamoDB interactions using the OneTable library for efficient, type-safe data modeling in Next.js applications.

🎯
nextjs-web-client🎯Skill

Generates a Next.js web client with pre-configured routing, components, and server-side rendering for efficient full-stack application development.

🎯
feature module generator (next.js + dynamodb)🎯Skill

Generates feature modules for Next.js applications with DynamoDB integration, streamlining backend and frontend component scaffolding.

🎯
nextjs-server-actions🎯Skill

Implements server-side actions in Next.js for handling form submissions and data mutations with simplified server-client interactions.

🎯
create-domain-module🎯Skill

Generates production-ready, state-isolated feature modules for Next.js with DynamoDB, following strict architectural principles and runtime-agnostic design.

🎯
modularity-maturity-assessor🎯Skill

Evaluates modular architecture compliance across 10 principles, focusing on state isolation, service layers, runtime independence, and explicit communication for Next.js and DynamoDB projects.

🎯
santry-observability🎯Skill

Monitors and tracks application performance, logs, and metrics in a comprehensive observability solution for Next.js projects.