mirror of
https://github.com/greedychipmunk/agent-skills.git
synced 2026-09-14 20:46:42 +08:00
feat: update all five skills with 2025-2026 best practices
AngularJS Unit Testing: - Add Legacy Status & Migration Guidance section (AngularJS EOL Dec 2021) - Recommend Jest over Jasmine/Karma; mark Karma as legacy - Add Jest Migration Guide with practical steps - Add Handling Environmental Flakiness section (js-env-sanitizer pattern) - Add Test Pyramid Guidance for legacy codebases - Update CI/CD examples to actions/checkout@v4, setup-node@v4, codecov@v4 MedusaJS Developer: - Update to Medusa v2.15+ and Node.js 20+ - Add MFA primitives (TOTP, SMS, recovery codes) - Add Promotion context hooks for conditional logic - Add Product SKU search - Add mcloud proxy for Cloud tunneling - Add MikroORM v6.6.12 migration notes and snapshot cleanup Next.js Developer: - Update to Next.js 15+ with React 19 support - Add Partial Prerendering (PPR) section with incremental adoption - Add Turbopack (stable for dev and build) - Update caching semantics (uncached by default in v15) - Add React 19 features (use(), useFormStatus, useOptimistic) - Add after() post-response API - Add navigation hooks (useLinkStatus, onNavigate) - Add next.config.js patterns for PPR and Turbopack Roblox Game Developer: - Add Luau New Type Solver (general release Jan 2026) - Add DataStore per-experience quotas and throttling - Add Data Stores Manager tool - Add DataStore2 migration guidance (deprecated → native DataStoreService) - Update Data Persistence example with rate limiting awareness Supabase Developer: - Add Deno 2.1 full rollout (August 2025) - Update Edge Function examples to use npm: specifiers and Deno.serve() - Add Dashboard Editor with AI Assistant - Add no-Docker deployment option - Add Management API for programmatic deploys 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta Code <noreply@letta.com>
This commit is contained in:
+164
-49
@@ -1,13 +1,29 @@
|
||||
---
|
||||
name: angularjs-unit-testing
|
||||
description: Use this skill for any AngularJS unit testing tasks
|
||||
description: Use this skill for AngularJS unit testing, maintenance, and migration tasks
|
||||
---
|
||||
|
||||
# AngularJS Unit Testing Skill
|
||||
|
||||
## Overview
|
||||
|
||||
This skill specializes in writing, refactoring, and maintaining high-quality unit tests for AngularJS applications using both **Jasmine** and **Jest**. It provides comprehensive guidance on testing controllers, services, filters, directives, and other AngularJS components.
|
||||
This skill focuses on writing, refactoring, and maintaining unit tests for AngularJS applications, with guidance for teams keeping legacy code healthy while planning a move to modern Angular.
|
||||
|
||||
## Legacy Status & Migration Guidance
|
||||
|
||||
AngularJS reached end-of-life in December 2021. Treat it as a legacy maintenance platform:
|
||||
- No new features; only critical security fixes and targeted maintenance
|
||||
- New projects should use Angular 19+ (the modern Angular framework)
|
||||
- This skill exists to support teams maintaining existing AngularJS codebases and planning migrations
|
||||
|
||||
**Migration path: AngularJS → Angular**
|
||||
- Modules / services / controllers → NgModules or standalone components, injectable services, and component classes
|
||||
- `$scope` / `$rootScope` → component state, `@Input()` / `@Output()`, and modern change detection
|
||||
- `$http` / `$resource` → `HttpClient`
|
||||
- Directives → components/directives with modern APIs
|
||||
- `$q` / digest cycle → RxJS, promises/async-await, and Angular lifecycle hooks
|
||||
- `$routeProvider` → Angular Router
|
||||
- Globals and ad-hoc DOM access → dependency injection and testable abstractions
|
||||
|
||||
## Skill Capabilities
|
||||
|
||||
@@ -17,13 +33,13 @@ This skill specializes in writing, refactoring, and maintaining high-quality uni
|
||||
- **Services**: Test factory/service dependencies, HTTP calls, and business logic
|
||||
- **Filters**: Validate filter transformations and edge cases
|
||||
- **Directives**: Test directive compilation, linking, and DOM manipulation
|
||||
- **HTTP Mocking**: Mock HTTP calls using `$httpBackend` (Jasmine) or `jest.mock()` (Jest)
|
||||
- **HTTP Mocking**: Mock HTTP calls using `$httpBackend` for legacy Jasmine suites or Jest-friendly mocks for modern suites
|
||||
- **Promises & Async**: Handle `$q`, deferred objects, and `$timeout`
|
||||
- **Dependency Injection**: Test with mocked and real dependencies
|
||||
- **Scope Management**: Test scope lifecycle, watchers, and event broadcasting
|
||||
- **Coverage Analysis**: Generate and interpret code coverage reports
|
||||
- **Test Organization**: Structure tests following best practices and maintainability principles
|
||||
- **Framework Choice**: Understand when to use Jasmine vs Jest, or both
|
||||
- **Framework Choice**: Prefer Jest by default; keep Jasmine/Karma for legacy suites only
|
||||
|
||||
### Testing Patterns
|
||||
|
||||
@@ -52,11 +68,14 @@ This skill implements the following testing patterns:
|
||||
- Capture expected component output
|
||||
- Detect unintended changes in UI rendering
|
||||
|
||||
6. **Deterministic Async**
|
||||
- Prefer fake timers, controlled promises, and isolated state over timing-sensitive assertions
|
||||
|
||||
## Testing Frameworks & Test Runners
|
||||
|
||||
### Jasmine (Recommended for AngularJS)
|
||||
### Jasmine (Legacy Default)
|
||||
|
||||
Jasmine is a behavior-driven development (BDD) testing framework optimized for unit testing AngularJS applications.
|
||||
Jasmine remains the safest choice when you are preserving an existing AngularJS + Karma suite.
|
||||
|
||||
**Key Concepts**:
|
||||
- `describe()`: Group related tests into a test suite
|
||||
@@ -70,46 +89,139 @@ Jasmine is a behavior-driven development (BDD) testing framework optimized for u
|
||||
npm install --save-dev jasmine karma karma-jasmine karma-chrome-launcher
|
||||
```
|
||||
|
||||
### Jest (Modern Alternative)
|
||||
**Use when**:
|
||||
- You are maintaining an existing Jasmine/Karma suite
|
||||
- You want the smallest possible change set for legacy AngularJS code
|
||||
|
||||
Jest is a modern testing framework with powerful mocking, coverage, and snapshot testing capabilities. It can also test AngularJS applications with appropriate configuration.
|
||||
### Jest (Recommended)
|
||||
|
||||
Jest is the modern default for AngularJS test maintenance and migration work. It runs tests in parallel, has stronger mocking APIs, supports snapshots, and includes built-in coverage reporting.
|
||||
|
||||
**Key Concepts**:
|
||||
- `describe()`: Group related tests (same as Jasmine)
|
||||
- `describe()`: Group related tests
|
||||
- `test()` or `it()`: Define individual test cases
|
||||
- `expect()`: Create assertions (Jasmine-compatible)
|
||||
- `expect()`: Create assertions
|
||||
- `beforeEach()` / `afterEach()`: Setup and teardown hooks
|
||||
- `jest.fn()`: Create mock functions
|
||||
- `jest.spyOn()`: Spy on existing methods
|
||||
- `jest.mock()`: Mock modules
|
||||
|
||||
**Setup**:
|
||||
```bash
|
||||
npm install --save-dev jest jest-preset-angular @angular/core
|
||||
npm install --save-dev jest jest-preset-angular angular-mocks
|
||||
npm install @angular/core
|
||||
```
|
||||
|
||||
**Jest Configuration** (package.json or jest.config.js):
|
||||
**Jest Configuration** (`jest.config.js`):
|
||||
```javascript
|
||||
{
|
||||
"preset": "jest-preset-angular",
|
||||
"setupFilesAfterEnv": ["<rootDir>/setup-jest.ts"],
|
||||
"testPathIgnorePatterns": ["/node_modules/", "/dist/"],
|
||||
"collectCoverage": true,
|
||||
"collectCoverageFrom": ["src/**/*.js", "!src/**/*.spec.js"]
|
||||
}
|
||||
module.exports = {
|
||||
preset: 'jest-preset-angular',
|
||||
testEnvironment: 'jsdom',
|
||||
setupFilesAfterEnv: ['<rootDir>/setup-jest.js'],
|
||||
transform: {
|
||||
'^.+\.js$': 'babel-jest'
|
||||
},
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.js', '!src/**/*.spec.js']
|
||||
};
|
||||
```
|
||||
|
||||
### Karma (Test Runner for Jasmine)
|
||||
**Use when**:
|
||||
- You want faster feedback from parallel execution
|
||||
- You need better mocking, snapshots, and coverage out of the box
|
||||
- You are preparing an AngularJS codebase for an Angular migration
|
||||
|
||||
Karma is a test runner that executes Jasmine tests in real browsers and provides reporting.
|
||||
### Karma (Legacy Runner)
|
||||
|
||||
Karma is the legacy browser test runner traditionally paired with Jasmine. It is still usable for existing suites, but it has seen no major releases since 2021 and should not be the basis for new investment.
|
||||
|
||||
**Configuration**:
|
||||
- `karma.conf.js`: Main configuration file
|
||||
- Specifies browser environment, files to load, and plugins
|
||||
- Supports code coverage reporting and CI integration
|
||||
|
||||
## Jest Migration Guide
|
||||
|
||||
Use these steps when moving an AngularJS test suite from Jasmine/Karma to Jest:
|
||||
|
||||
1. **Install the core tooling**
|
||||
```bash
|
||||
npm install --save-dev jest jest-preset-angular angular-mocks
|
||||
npm install @angular/core
|
||||
```
|
||||
Add `@angular/core` when the repo is hybrid or actively migrating toward Angular.
|
||||
|
||||
2. **Create a Jest setup file**
|
||||
- Add `setup-jest.js` or `setup-jest.ts`
|
||||
- Load `angular`, `angular-mocks`, and any shared test polyfills there
|
||||
|
||||
3. **Configure Jest for AngularJS files**
|
||||
- Use `jest.config.js` with `testEnvironment: 'jsdom'`
|
||||
- Add a transform for legacy JavaScript sources
|
||||
- Keep template or DOM-specific setup in the Jest bootstrap file
|
||||
|
||||
4. **Load AngularJS modules in Jest**
|
||||
```javascript
|
||||
beforeEach(() => {
|
||||
require('angular');
|
||||
require('angular-mocks');
|
||||
angular.mock.module('myApp');
|
||||
});
|
||||
```
|
||||
|
||||
5. **Migrate spies and stubs**
|
||||
- `spyOn(obj, 'method')` → `jest.spyOn(obj, 'method')`
|
||||
- `jasmine.createSpy()` → `jest.fn()`
|
||||
- `jasmine.createSpyObj()` → `jest.fn()` or explicit mock objects
|
||||
|
||||
6. **Replace `$httpBackend` where practical**
|
||||
- Prefer `fetch` mocks or MSW for new Jest tests
|
||||
- Keep `$httpBackend` only for legacy tests that are expensive to rewrite immediately
|
||||
|
||||
7. **Reset state between tests**
|
||||
- Use `jest.clearAllMocks()` / `jest.resetAllMocks()`
|
||||
- Recreate AngularJS modules and services in `beforeEach()`
|
||||
|
||||
## Handling Environmental Flakiness
|
||||
|
||||
Legacy AngularJS suites often fail because the environment is unstable, not because the code is broken.
|
||||
|
||||
**Common sources of flakiness**:
|
||||
- Timing issues and race conditions
|
||||
- Shared state between tests
|
||||
- Browser environment differences
|
||||
- Network-dependent tests and real external services
|
||||
- Time zone, locale, and date-sensitive logic
|
||||
|
||||
**Deterministic test patterns**:
|
||||
- Use fake timers for scheduled work and debounce/throttle logic
|
||||
- Keep async work controlled with explicit promise resolution and digest flushing
|
||||
- Reset shared state, mocks, and module caches in `afterEach()`
|
||||
- Avoid real browser/network dependencies in unit tests
|
||||
- Prefer fixed test data over generated or time-based values
|
||||
|
||||
**js-env-sanitizer pattern**:
|
||||
- Snapshot and restore environment-dependent globals around each test
|
||||
- Isolate `window`, `document`, `localStorage`, `Date`, `Math.random`, feature flags, and DOM mutations
|
||||
- This is especially useful in long-lived AngularJS suites where hidden environment coupling causes intermittent failures
|
||||
|
||||
## Test Pyramid Guidance for Legacy Codebases
|
||||
|
||||
Legacy AngularJS codebases often have an inverted test pyramid: too many end-to-end tests and too few unit tests.
|
||||
|
||||
**Recommended shape**:
|
||||
- **Base**: many fast unit tests for controllers, services, filters, and directives
|
||||
- **Middle**: fewer integration tests for module wiring, routing, and API boundaries
|
||||
- **Top**: a small number of end-to-end tests for critical user journeys only
|
||||
|
||||
**Guidance**:
|
||||
- Shift coverage toward unit tests first
|
||||
- Keep integration tests as the middle layer, not the base
|
||||
- Use e2e tests sparingly because they are slower and more environment-sensitive
|
||||
|
||||
## Test Structure
|
||||
|
||||
### Jasmine Test Structure (Recommended for AngularJS)
|
||||
### Jasmine Test Structure (Legacy Default)
|
||||
|
||||
All Jasmine tests follow this standard structure:
|
||||
|
||||
@@ -117,16 +229,13 @@ All Jasmine tests follow this standard structure:
|
||||
describe('Component Name', function() {
|
||||
var componentUnderTest, dependencies;
|
||||
|
||||
// Load the module
|
||||
beforeEach(module('myApp'));
|
||||
|
||||
// Inject dependencies
|
||||
beforeEach(inject(function($injector) {
|
||||
componentUnderTest = $injector.get('ComponentName');
|
||||
dependencies = $injector.get('DependencyName');
|
||||
}));
|
||||
|
||||
// Cleanup after each test
|
||||
afterEach(function() {
|
||||
// Cleanup code
|
||||
});
|
||||
@@ -146,24 +255,24 @@ describe('Component Name', function() {
|
||||
});
|
||||
```
|
||||
|
||||
### Jest Test Structure (Modern Alternative)
|
||||
### Jest Test Structure (Recommended)
|
||||
|
||||
Jest tests follow a similar structure but with some differences:
|
||||
Jest tests follow a similar structure with modern mocking and cleaner teardown:
|
||||
|
||||
```javascript
|
||||
describe('Component Name', () => {
|
||||
let componentUnderTest;
|
||||
let dependencies;
|
||||
let dependency;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
// Setup code or mock initialization
|
||||
componentUnderTest = require('./component').default;
|
||||
dependencies = jest.mock('./dependency');
|
||||
dependency = { method: jest.fn() };
|
||||
componentUnderTest = require('./component');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Cleanup code
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Functionality Group', () => {
|
||||
@@ -172,7 +281,7 @@ describe('Component Name', () => {
|
||||
const input = 'test';
|
||||
|
||||
// Act
|
||||
const result = componentUnderTest.method(input);
|
||||
const result = componentUnderTest.method(input, dependency);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe('expected');
|
||||
@@ -182,9 +291,8 @@ describe('Component Name', () => {
|
||||
```
|
||||
|
||||
**Key Differences**:
|
||||
- Jest uses arrow functions (ES6) while Jasmine supports both
|
||||
- Jest uses `jest.fn()` / `jest.spyOn()` instead of Jasmine spies for modern test code
|
||||
- Jest uses `test()` or `it()` (both work)
|
||||
- Jest uses `jest.mock()` instead of Jasmine spies for module mocking
|
||||
- Jest auto-discovers `.spec.js` and `.test.js` files
|
||||
- Jest provides built-in snapshot testing and code coverage
|
||||
|
||||
@@ -216,7 +324,7 @@ describe('Component Name', () => {
|
||||
- Test async operations and race conditions
|
||||
|
||||
### 6. Performance
|
||||
- Keep tests fast (< 100ms per test)
|
||||
- Keep tests fast
|
||||
- Use in-memory mocks instead of real HTTP requests
|
||||
- Avoid unnecessary database operations
|
||||
|
||||
@@ -351,11 +459,16 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- run: npm install
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm test -- --coverage
|
||||
- uses: codecov/codecov-action@v2
|
||||
- uses: codecov/codecov-action@v4
|
||||
with:
|
||||
files: ./coverage/lcov.info
|
||||
```
|
||||
|
||||
### Jenkins Example
|
||||
@@ -365,7 +478,7 @@ pipeline {
|
||||
stages {
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'npm install'
|
||||
sh 'npm ci'
|
||||
sh 'npm test'
|
||||
publishHTML([
|
||||
reportDir: 'coverage',
|
||||
@@ -385,7 +498,8 @@ pipeline {
|
||||
- [Jest Documentation](https://jestjs.io/)
|
||||
- [jest-preset-angular](https://github.com/thymikee/jest-preset-angular)
|
||||
- [AngularJS Testing Guide](https://docs.angularjs.org/guide/unit-testing)
|
||||
- [Angular Testing Guide](https://angular.io/guide/testing)
|
||||
- [Angular Testing Guide](https://angular.dev/guide/testing)
|
||||
- [Angular Update Guide](https://angular.dev/update-guide)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -397,7 +511,7 @@ pipeline {
|
||||
### Async tests timing out
|
||||
- Ensure promises are resolved: `$rootScope.$apply()` or `$httpBackend.flush()`
|
||||
- Use `done()` callback: `it('...', function(done) { ... done(); })`
|
||||
- For Jest: use `async/await` or return promise
|
||||
- For Jest: use `async/await` or return a promise
|
||||
|
||||
### HTTP mocks not working
|
||||
- Verify mock is set up before service call
|
||||
@@ -412,14 +526,15 @@ pipeline {
|
||||
## Next Steps
|
||||
|
||||
1. **Start Small**: Write tests for a single component
|
||||
2. **Understand Patterns**: Study the testing patterns guide
|
||||
3. **Use Templates**: Reference template files for your component type
|
||||
4. **Refine**: Improve tests based on coverage and feedback
|
||||
5. **Automate**: Integrate tests into your CI/CD pipeline
|
||||
6. **Share**: Document testing patterns for your team
|
||||
2. **Choose the Right Runner**: Keep Jasmine/Karma only for legacy maintenance; prefer Jest for new work
|
||||
3. **Understand Patterns**: Study the testing patterns guide
|
||||
4. **Use Templates**: Reference template files for your component type
|
||||
5. **Refine**: Improve tests based on coverage and feedback
|
||||
6. **Automate**: Integrate tests into your CI/CD pipeline
|
||||
7. **Plan the Migration**: Map AngularJS modules, controllers, and `$scope` usage to Angular components and services
|
||||
|
||||
---
|
||||
|
||||
**Specialization**: AngularJS Unit Testing with Jasmine and Jest
|
||||
**Version**: 1.0
|
||||
**Last Updated**: January 10, 2026
|
||||
**Version**: 2.0
|
||||
**Last Updated**: May 2026
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
---
|
||||
name: medusajs-developer
|
||||
description: Specialized agent for MedusaJS development including custom modules, API routes, data models, workflows, scheduled jobs, and third-party integrations. Provides expert guidance on commerce platform architecture and plugin development.
|
||||
description: Specialized agent for MedusaJS v2.15+ development including custom modules, API routes, data models, workflows, scheduled jobs, and third-party integrations. Provides expert guidance on commerce platform architecture and plugin development.
|
||||
license: MIT
|
||||
compatibility: Requires Node.js 18+, TypeScript, and MedusaJS v2
|
||||
compatibility: Requires Node.js 20+, TypeScript, and MedusaJS v2.15+
|
||||
metadata:
|
||||
category: ecommerce
|
||||
framework: medusajs
|
||||
version: 2.x
|
||||
framework: Medusa v2.15+
|
||||
version: 2.15+
|
||||
expertise: commerce-modules, api-development, plugin-creation
|
||||
allowed-tools: [Read, Write, Edit, MultiEdit, Bash, Grep, Glob, WebFetch]
|
||||
---
|
||||
|
||||
# MedusaJS Developer Agent Skill
|
||||
|
||||
An expert agent specializing in MedusaJS development, focusing on building scalable e-commerce solutions with custom modules, API integrations, and third-party plugins.
|
||||
An expert agent specializing in MedusaJS v2.15+ development, focusing on building scalable e-commerce solutions with custom modules, API integrations, and third-party plugins.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
@@ -47,6 +47,56 @@ An expert agent specializing in MedusaJS development, focusing on building scala
|
||||
- **Webhooks**: Handle incoming webhooks from external systems
|
||||
- **Data Synchronization**: Sync data with external platforms
|
||||
|
||||
## Medusa v2.15+ Updates
|
||||
|
||||
### Auth & Security
|
||||
- Medusa v2.15+ includes built-in MFA primitives for auth flows.
|
||||
- Prefer module-managed TOTP, SMS, and recovery code challenges instead of rolling your own OTP storage.
|
||||
- Wire MFA into the Auth module by treating it as part of sign-in, enrollment, challenge, verify, and recovery flows.
|
||||
|
||||
```ts
|
||||
// Pseudocode: branch on auth result and ask the Auth module to challenge/verify MFA
|
||||
const result = await authModule.authenticate(credentials)
|
||||
|
||||
if (result.mfa_required) {
|
||||
await authModule.mfa.challenge({
|
||||
user_id: result.user_id,
|
||||
method: "totp", // "sms" | "recovery_code"
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Promotions
|
||||
- Promotion workflows can consume context hooks for conditional application.
|
||||
- Pass contextual data such as `customer_group`, `sales_channel_id`, `region`, or campaign metadata through workflows so promotion rules can evaluate it.
|
||||
- Example: apply a wholesale promotion only when `context.customer_group === "wholesale"`.
|
||||
|
||||
### Catalog Search
|
||||
- Products now support native SKU search.
|
||||
- Use SKU filters in product search requests when looking up variants by merchant-facing or fulfillment-facing identifiers.
|
||||
- Example: search by SKU and keyword together to narrow a catalog query.
|
||||
|
||||
```bash
|
||||
GET /store/products?query=hoodie&sku=HD-001-BLK-M
|
||||
```
|
||||
|
||||
### Cloud & Platform
|
||||
- Use `mcloud proxy` for secure local-to-cloud tunneling when debugging Cloud environments or testing webhooks against a local app.
|
||||
- Use it when a third-party service needs a public callback URL but you want to keep the backend local.
|
||||
|
||||
### Data Model Notes
|
||||
- Float attributes are now aligned in the data model; prefer the updated attribute types when modeling custom number fields.
|
||||
|
||||
## Critical Migration Notes
|
||||
- Medusa v2.15.2 includes the MikroORM v6.6.12 security update and fixes the v6.13.6 snapshot regression.
|
||||
- If you're on v2.13.6+, upgrade before running production migrations and clean stale snapshots first:
|
||||
|
||||
```bash
|
||||
npx medusa db:migrate --clean-snapshots
|
||||
```
|
||||
|
||||
- Pin all `@medusajs/*` packages to the same release line during the upgrade and avoid partial version drift.
|
||||
|
||||
## Development Patterns
|
||||
|
||||
### Module Structure
|
||||
@@ -528,3 +578,6 @@ npx create-medusa-app@latest my-store
|
||||
- Developer Tools and CLI Commands
|
||||
|
||||
This skill enables comprehensive MedusaJS development with focus on maintainable, scalable e-commerce solutions.
|
||||
|
||||
Version: 2.0
|
||||
Last Updated: May 2026
|
||||
|
||||
+137
-11
@@ -7,7 +7,7 @@ description: Expert Next.js development with App Router, Server Components, and
|
||||
|
||||
## Overview
|
||||
|
||||
This skill provides comprehensive expertise in building production-ready Next.js applications using the **App Router** (Next.js 13+). It covers Server Components, data fetching patterns, routing, API routes, caching, and performance optimization.
|
||||
This skill provides comprehensive expertise in building production-ready Next.js applications using the **App Router** (Next.js 15+). It covers Server Components, React 19 support, data fetching patterns, routing, API routes, caching, and performance optimization.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
@@ -21,7 +21,7 @@ This skill provides comprehensive expertise in building production-ready Next.js
|
||||
|
||||
### Data Fetching
|
||||
- **Server-side fetching**: Direct database/API access in Server Components
|
||||
- **Caching strategies**: Static, dynamic, and incremental regeneration
|
||||
- **Caching strategies**: Dynamic rendering by default, explicit caching, and incremental regeneration
|
||||
- **Revalidation**: Time-based and on-demand cache invalidation
|
||||
- **Parallel fetching**: Optimized data loading patterns
|
||||
|
||||
@@ -100,21 +100,21 @@ export function Counter() {
|
||||
|
||||
### Data Fetching Patterns
|
||||
|
||||
#### Static Generation (Default)
|
||||
#### Dynamic Rendering (Default)
|
||||
```typescript
|
||||
// Cached indefinitely (can be revalidated)
|
||||
// In Next.js 15+, fetch is uncached by default (implicit cache: 'no-store')
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data')
|
||||
return <div>{data}</div>
|
||||
}
|
||||
```
|
||||
|
||||
#### Dynamic Rendering
|
||||
#### Static Generation (Opt-in)
|
||||
```typescript
|
||||
// Opt out of caching
|
||||
// Explicitly opt into caching
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data', {
|
||||
cache: 'no-store'
|
||||
cache: 'force-cache',
|
||||
})
|
||||
return <div>{data}</div>
|
||||
}
|
||||
@@ -124,12 +124,14 @@ async function Page() {
|
||||
```typescript
|
||||
async function Page() {
|
||||
const data = await fetch('https://api.example.com/data', {
|
||||
next: { revalidate: 3600 } // Revalidate every hour
|
||||
next: { revalidate: 3600 }, // Revalidate every hour
|
||||
})
|
||||
return <div>{data}</div>
|
||||
}
|
||||
```
|
||||
|
||||
> Note: The client router cache is also uncached by default in Next.js 15, replacing the old 30s/5m defaults.
|
||||
|
||||
### Server Actions
|
||||
```typescript
|
||||
// app/actions.ts
|
||||
@@ -160,11 +162,135 @@ export default function NewPost() {
|
||||
}
|
||||
```
|
||||
|
||||
### Partial Prerendering (PPR)
|
||||
- PPR combines a static shell with dynamic streaming in a single HTTP request.
|
||||
- It is production-ready in Next.js 15+ and was experimental in Next.js 14.
|
||||
- Enable incremental adoption with `experimental.ppr: 'incremental'` in `next.config.js`, or use `ppr: true` when you want full PPR.
|
||||
- Use `Suspense` boundaries to define dynamic holes inside static shells.
|
||||
- Adopt PPR route by route so you can gradually expand coverage without rewriting the whole app.
|
||||
|
||||
```typescript
|
||||
// app/page.tsx — static shell with dynamic hole
|
||||
export const experimental_ppr = true
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<StaticHeader />
|
||||
<Suspense fallback={<ProductSkeleton />}>
|
||||
<DynamicProductList />
|
||||
</Suspense>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Turbopack
|
||||
- Turbopack is stable for `next dev` in Next.js 15 and for `next build` in Next.js 15.3+.
|
||||
- The production build path passes 8,298 test suite cases.
|
||||
- Use `next dev --turbopack` and `next build --turbopack` to opt in.
|
||||
- It can be up to 10x faster than Webpack for dev server startup.
|
||||
- Some Webpack loaders and plugins may still need migration work.
|
||||
|
||||
```bash
|
||||
next dev --turbopack
|
||||
next build --turbopack
|
||||
```
|
||||
|
||||
### React 19 Features
|
||||
- React 19 is the default runtime in Next.js 15+ App Router projects.
|
||||
- Use `use()` to consume promises and contexts during render.
|
||||
- Server Actions are stable and no longer experimental.
|
||||
- Use `useFormStatus()` for form state without prop drilling.
|
||||
- Use `useOptimistic()` for optimistic UI updates.
|
||||
|
||||
```typescript
|
||||
import { use } from "react"
|
||||
import { useFormStatus } from "react-dom"
|
||||
import { useOptimistic } from "react"
|
||||
|
||||
function ProductName({ productPromise }: { productPromise: Promise<{ name: string }> }) {
|
||||
const product = use(productPromise)
|
||||
return <h1>{product.name}</h1>
|
||||
}
|
||||
```
|
||||
|
||||
### `after()` Post-Response Work
|
||||
- Next.js 15 introduces `after()` for post-response work.
|
||||
- Use it for logging, analytics, and other non-critical tasks after the response is sent.
|
||||
- Import it from `next/server`.
|
||||
|
||||
```typescript
|
||||
import { after } from 'next/server'
|
||||
|
||||
after(() => {
|
||||
logAnalytics()
|
||||
})
|
||||
```
|
||||
|
||||
### Navigation Hooks (Next.js 15.4)
|
||||
- `useLinkStatus()` helps show inline link-loading indicators.
|
||||
- `onNavigate` lets you track or block client-side navigation.
|
||||
- `useLinkStatus()` is a client hook from `next/link` and returns `{ pending }`.
|
||||
- `onNavigate` is a `Link` prop for SPA navigations only.
|
||||
|
||||
```typescript
|
||||
'use client'
|
||||
|
||||
import Link, { useLinkStatus } from 'next/link'
|
||||
|
||||
function LinkHint() {
|
||||
const { pending } = useLinkStatus()
|
||||
return <span aria-hidden>{pending ? 'Loading…' : null}</span>
|
||||
}
|
||||
|
||||
export function Nav() {
|
||||
return (
|
||||
<nav>
|
||||
<Link href="/dashboard" prefetch={false} onNavigate={() => trackNavigation('/dashboard')}>
|
||||
Dashboard <LinkHint />
|
||||
</Link>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### next.config.js Patterns
|
||||
- Keep experimental flags only when needed; several features have graduated to stable in Next.js 15+.
|
||||
- Use `experimental.ppr: 'incremental'` for route-by-route PPR adoption.
|
||||
- Use `ppr: true` only when you want a fully PPR-enabled app.
|
||||
- Turbopack is enabled via CLI flags, not a `next.config.js` switch.
|
||||
|
||||
```typescript
|
||||
// next.config.ts
|
||||
import type { NextConfig } from 'next'
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
experimental: {
|
||||
ppr: 'incremental',
|
||||
},
|
||||
// For full PPR:
|
||||
// ppr: true,
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Performance
|
||||
- Use Server Components by default
|
||||
- Implement proper caching strategies
|
||||
- Prefer dynamic rendering unless you explicitly need caching
|
||||
- Use PPR for fast static shells with dynamic holes
|
||||
- Optimize images with `next/image`
|
||||
- Use `next/font` for font optimization
|
||||
- Implement streaming with Suspense boundaries
|
||||
@@ -265,5 +391,5 @@ This skill includes detailed reference guides in the `resources/` folder:
|
||||
---
|
||||
|
||||
**Specialization**: Next.js App Router Development
|
||||
**Version**: 1.0
|
||||
**Last Updated**: January 2026
|
||||
**Version**: 2.0
|
||||
**Last Updated**: May 2026
|
||||
|
||||
@@ -18,11 +18,26 @@ This skill includes a comprehensive collection of production-ready resources:
|
||||
## Core Capabilities
|
||||
|
||||
### Luau Programming
|
||||
- **Modern Luau Features**: Utilize type annotations, generics, and performance optimizations
|
||||
- **Modern Luau Features**: Utilize type annotations, generics, the New Type Solver (general release), improved type inference/autocomplete, and performance optimizations
|
||||
- **Script Architecture**: Implement clean, modular code with proper separation of concerns
|
||||
- **Performance Optimization**: Write efficient scripts that handle large player counts
|
||||
- **Error Handling**: Robust error management and debugging techniques
|
||||
|
||||
### Luau Type System Updates
|
||||
- **New Type Solver**: General release (no longer a Studio Beta); enabled by default for `nonstrict` and `nocheck` modes starting January 7, 2026
|
||||
- **Key Improvements**: Better type inference, fewer false positives, stronger generics support, and improved autocomplete
|
||||
- **Legacy Solver Timeline**: The legacy solver remains available through 2026, but it is slated for removal
|
||||
- **Migration Guidance**: Most code works without changes, but a few edge cases may need explicit type annotations or cleanup
|
||||
- **Best Practices**: Prefer explicit annotations on public APIs, use generics where appropriate, and lean on improved autocomplete for faster iteration
|
||||
|
||||
```lua
|
||||
-- New Type Solver infers types more accurately
|
||||
local function processPlayer(player: Player)
|
||||
local name: string = player.Name -- inferred correctly
|
||||
local team = player.Team -- Team? properly inferred
|
||||
end
|
||||
```
|
||||
|
||||
### Game Systems Development
|
||||
- **Player Data Management**: DataStore implementation with backup systems (see [DataManager.lua](scripts/DataManager.lua))
|
||||
- **Inventory Systems**: Item management, trading, and equipment systems
|
||||
@@ -79,24 +94,40 @@ This skill includes a comprehensive collection of production-ready resources:
|
||||
|
||||
## Common Patterns & Solutions
|
||||
|
||||
### DataStore Access and Storage Updates
|
||||
- **Per-Experience Quotas**: Each experience gets its own DataStore read/write quota, and Roblox is enforcing these limits starting in early 2026
|
||||
- **Throttle Behavior**: Exceeding limits throttles requests instead of throwing hard errors, so code should gracefully retry or fall back
|
||||
- **Best Practices**: Batch operations, cache locally, and keep transient state in session data tables instead of writing every change immediately
|
||||
- **Studio Tooling**: Use **Data Stores Manager** in Roblox Studio to view, edit, and delete entries directly without publishing (`Studio → View → Data Stores Manager`)
|
||||
|
||||
### Data Persistence
|
||||
Complete implementation available in [DataManager.lua](scripts/DataManager.lua)
|
||||
|
||||
```lua
|
||||
-- DataStore best practices with retry logic and caching
|
||||
-- DataStore best practices with retry logic, caching, and rate limiting awareness
|
||||
local DataStoreService = game:GetService("DataStoreService")
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local PlayerDataModule = {}
|
||||
local dataStore = DataStoreService:GetDataStore("PlayerData_v1")
|
||||
local sessionData = {}
|
||||
local cachedData = {}
|
||||
|
||||
local function safeGetAsync(dataStore, key)
|
||||
local success, result = pcall(function()
|
||||
return dataStore:GetAsync(key)
|
||||
end)
|
||||
if not success then
|
||||
warn("DataStore request failed, using cached data")
|
||||
return cachedData[key]
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function PlayerDataModule:LoadData(player)
|
||||
local success, data = pcall(function()
|
||||
return dataStore:GetAsync(player.UserId)
|
||||
end)
|
||||
local data = safeGetAsync(dataStore, player.UserId)
|
||||
|
||||
if success and data then
|
||||
if data then
|
||||
sessionData[player.UserId] = data
|
||||
else
|
||||
-- Default data structure
|
||||
@@ -108,10 +139,19 @@ function PlayerDataModule:LoadData(player)
|
||||
}
|
||||
end
|
||||
|
||||
cachedData[player.UserId] = sessionData[player.UserId]
|
||||
return sessionData[player.UserId]
|
||||
end
|
||||
```
|
||||
|
||||
### DataStore2 Migration Guidance
|
||||
- **Deprecation Status**: Berezaa/DataStore2 is deprecated; prefer native `DataStoreService` for new and existing projects
|
||||
- **Why Migrate**: Per-experience quotas and the built-in Data Stores Manager reduce the need for an extra caching layer
|
||||
- **Migration Steps**:
|
||||
- Replace `DataStore2()` calls with `DataStoreService:GetDataStore()`
|
||||
- Manage session caching manually with tables for transient state
|
||||
- Use `UpdateAsync` for atomic updates instead of DataStore2's `:Update()` helper
|
||||
|
||||
### Remote Communication
|
||||
Complete implementation available in [RemoteManager.lua](scripts/RemoteManager.lua)
|
||||
|
||||
@@ -198,6 +238,7 @@ Comprehensive debugging resources available in [Debugging Guide](resources/debug
|
||||
- **Roblox Studio Debugger**: Breakpoints and variable inspection
|
||||
- **Performance Profiler**: CPU and memory usage analysis
|
||||
- **Network Monitor**: Remote event tracking and bandwidth usage
|
||||
- **Data Stores Manager**: View, edit, and delete DataStore entries directly in Studio for debugging and testing (`Studio → View → Data Stores Manager`)
|
||||
- **Error Logging**: Custom logging systems for production debugging
|
||||
|
||||
### Quick Reference
|
||||
@@ -237,3 +278,6 @@ Essential commands and snippets available in [Quick Reference](resources/quick_r
|
||||
- **[Quick Reference](resources/quick_reference.md)** - Essential commands and code snippets
|
||||
|
||||
This skill enables comprehensive Roblox game development from concept to launch, with focus on best practices, security, and player engagement. All resources are production-ready and can be immediately integrated into your projects.
|
||||
|
||||
Version: 2.0
|
||||
Last Updated: May 2026
|
||||
|
||||
Reference in New Issue
Block a user