Tested demoQuality 91/100Review permissions

payloadcms/payload/packages/payload/skills/payload/SKILL.md

payload

Use when working with Payload projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.

Source repository stars
44,385
Declared platforms
0
Static risk flags
2
Last source update
2026-08-24
Source checked
2026-08-25

Decision brief

What it does: where it fits

Payload is a Next.js native CMS with TypeScript-first architecture, providing admin panel, database management, REST/GraphQL APIs, authentication, and file storage.

Best for

  • Use when working with Payload projects (payload.

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.
Controlled single-run demoChecked 2026-08-20

What changed when the Skill was used

In this controlled same-task single run, enabling payload changed the output from 4621 non-whitespace characters and 9 headings to 4723 characters and 8 headings. Matches among 8 signals extracted from the pinned source changed from 2 to 2. Both actual outputs are shown; this is a structural observation, not a quality score or a universal performance claim.

Same test task

Design and implement a representative production change for a TypeScript webhook retry service. Include the key code or pseudocode, tradeoffs, and verification steps. The deliverable must specifically reflect this user intent: Use when working with Payload projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.

Without the Skill
Screenshot of the actual model output for payload without the Skill

Baseline: 4621 non-whitespace characters, 9 headings, and 38 list items.

With the Skill
Screenshot of the actual model output for payload with the Skill

With Skill: 4723 non-whitespace characters, 8 headings, and 25 list items.

ObservationWithout SkillWith Skill
Source-signal coverage2/8: payload, application2/8: payload, config
Output structure4621 chars · 9 headings · 38 list items · 3 code blocks4723 chars · 8 headings · 25 list items · 3 code blocks
Verification and caution signals14 verification signals · 6 risk/limitation signals12 verification signals · 9 risk/limitation signals

A prompt you can use

Use the payload Skill pinned at f7df2137d03b for my task. Follow its source-specific constraints around `payload`, `application`, `development`, `quick`, then return the finished deliverable with explicit assumptions, verification, failure conditions, and limits. Do not treat the Skill text as a factual source or claim that a single demonstration proves universal performance.

Method and limitationsExpand

Test method

  • Baseline and treatment used the same task, model (gpt-5.3-codex-low), and runner; the only planned difference was whether the complete target Skill text was injected.
  • The treatment used snapshot c6e79520e3ea70afc2a001b7cf8ec32683246c57; the current source commit f7df2137d03b6d87540b32b48cfce86417bf6048 was verified against content hash fffa08a184f0. The baseline explicitly prohibited loading any Skill or external rule file.
  • The same deterministic script counted characters, headings, lists, code blocks, verification terms, caution terms, and source signals in both artifacts. Source signals: `payload`, `application`, `development`, `quick`, `reference`, `start`, `minimal`, `config`.
  • The visuals are local screenshots of the actual Markdown artifacts in a fixed 1200 × 800 evidence canvas, not recreated product mockups. Raw JSON artifacts and request records are retained in the research directory.

Do not over-read this demo

  • This is one controlled demonstration per condition, not a multi-run statistical benchmark; the model is stochastic.
  • Character, structure, and keyword counts show observable differences but cannot by themselves prove correctness, originality, or business impact.
  • The task is a representative test designed for repeatability, not every real-world use of the Skill; rerun after a material source change.
Editorial review
SkillSignal editorial
Runner
Cursor Agent 2026.08.04-aaa8809
Model
gpt-5.3-codex-low
Refresh due
2026-11-18
Reviewed commit
f7df2137d03b6d87540b32b48cfce86417bf6048
Test snapshot
c6e79520e3ea70afc2a001b7cf8ec32683246c57

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/payloadcms/payload --skill "packages/payload/skills/payload"
Safe inspection promptEditorial

Inspect the Agent Skill "payload" from https://github.com/payloadcms/payload/blob/237fcb3d735f737d467fb61096cfeb3772e58e68/packages/payload/skills/payload/SKILL.md at commit 237fcb3d735f737d467fb61096cfeb3772e58e68. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Quick Start

    Review the “Quick Start” section in the pinned source before continuing.

    Review and apply the “Quick Start” source section.
  2. 02

    Quick Reference

    Review the “Quick Reference” section in the pinned source before continuing.

    Review and apply the “Quick Reference” source section.
  3. 03

    Minimal Config

    Review the “Minimal Config” section in the pinned source before continuing.

    Review and apply the “Minimal Config” source section.
  4. 04

    Essential Patterns

    Apply these defaults when modeling content unless there's a clear reason not to:

    Enable drafts/versions by default: versions: { drafts: true }. This is theUse the native slug field type for all slugs instead of hand-rollingposition: 'sidebar' is for short, at-a-glance fields — status, category,
  5. 05

    Defaults & Conventions

    Apply these defaults when modeling content unless there's a clear reason not to:

    Enable drafts/versions by default: versions: { drafts: true }. This is theUse the native slug field type for all slugs instead of hand-rollingposition: 'sidebar' is for short, at-a-glance fields — status, category,

Permission review

Static risk signals and limitations

Runs scripts

medium · line 42

The documentation asks the agent to run terminal commands or scripts.

npx create-payload-app@latest my-app

Runs scripts

medium · line 44

The documentation asks the agent to run terminal commands or scripts.

pnpm dev

Reads files

low · line 497

The documentation asks the agent to read local files, directories, or repositories.

Extract access control to `access/` directory

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score91/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars44,385SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guidetested outcome pageTestedGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
payloadcms/payload
Skill path
packages/payload/skills/payload/SKILL.md
Commit
237fcb3d735f737d467fb61096cfeb3772e58e68
License
MIT
Collected
2026-08-25
Default branch
main
View the original SKILL.md

Payload Application Development

Payload is a Next.js native CMS with TypeScript-first architecture, providing admin panel, database management, REST/GraphQL APIs, authentication, and file storage.

Quick Reference

TaskSolutionDetails
Auto-generate slugs{ type: 'slug', useAsSlug: 'title' }FIELDS.md#slug-field
Restrict content by userAccess control with queryACCESS-CONTROL.md#row-level-security-with-complex-queries
Local API user opsuser + overrideAccess: falseQUERIES.md#access-control-in-local-api
Draft/publish workflowversions: { drafts: true }COLLECTIONS.md#versioning--drafts
Computed fieldsvirtual: true with field-level hooks.afterRead returning the valueFIELDS.md#virtual-fields
Document titlesStored top-level field in admin.useAsTitleCOLLECTIONS.md#useastitle
Conditional fieldsadmin.conditionFIELDS.md#conditional-fields
Custom field validationvalidate functionFIELDS.md#validation
Filter relationship listfilterOptions on fieldFIELDS.md#relationship
Select specific fieldsselect parameterQUERIES.md#field-selection
Auto-set author/datesbeforeChange hookHOOKS.md#collection-hooks
Prevent hook loopsreq.context checkHOOKS.md#context
Cascading deletesbeforeDelete hookHOOKS.md#collection-hooks
Geospatial queriespoint field with near/withinFIELDS.md#point-geolocation
Reverse relationshipsjoin field typeFIELDS.md#join-fields
Next.js revalidationContext control in afterChangeHOOKS.md#nextjs-revalidation-with-context-control
Query by relationshipNested property syntaxQUERIES.md#nested-properties
Complex queriesAND/OR logicQUERIES.md#andor-logic
TransactionsPass req to operationsADAPTERS.md#threading-req-through-operations
Background jobsJobs queue with tasksADVANCED.md#jobs-queue
Custom API routesCollection custom endpointsADVANCED.md#custom-endpoints
Cloud storageStorage adapter pluginsADAPTERS.md#storage-adapters
Multi-languagelocalization config + localized: trueADVANCED.md#localization
Create plugin(options) => (config) => ConfigPLUGIN-DEVELOPMENT.md#plugin-architecture
Plugin package setupPackage structure with SWCPLUGIN-DEVELOPMENT.md#plugin-package-structure
Add fields to collectionMap collections, spread fieldsPLUGIN-DEVELOPMENT.md#adding-fields-to-collections
Plugin hooksPreserve existing hooks in arrayPLUGIN-DEVELOPMENT.md#adding-hooks
Check field typeType guard functionsFIELD-TYPE-GUARDS.md

Quick Start

npx create-payload-app@latest my-app
cd my-app
pnpm dev

Minimal Config

import { buildConfig } from 'payload'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import path from 'path'
import { fileURLToPath } from 'url'

const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

export default buildConfig({
  admin: {
    user: 'users',
    importMap: {
      baseDir: path.resolve(dirname),
    },
  },
  collections: [Users, Media],
  editor: lexicalEditor(),
  secret: process.env.PAYLOAD_SECRET,
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
  },
  db: mongooseAdapter({
    url: process.env.DATABASE_URL,
  }),
})

Essential Patterns

Defaults & Conventions

Apply these defaults when modeling content unless there's a clear reason not to:

  • Enable drafts/versions by default: versions: { drafts: true }. This is the recommended starting point for any content collection. It auto-injects a _status field (draft / published / changed) — don't add your own status field, it's redundant. Only skip versions for collections that have no publish/draft lifecycle (e.g. internal join tables, settings).
  • Use the native slug field type for all slugs instead of hand-rolling { name: 'slug', type: 'text', unique: true }. It auto-generates the slug from a source field, adds a regenerate toggle, and defaults to required, unique, index, and position: 'sidebar'. useAsSlug is required — name the source field to generate from: { name: 'slug', type: 'slug', useAsSlug: 'title' }.
  • position: 'sidebar' is for short, at-a-glance fields — status, category, author, publish date. Avoid it for long fields that need horizontal space to be usable (description, rich text content, long text). Those belong in the main document area.
  • Use a stored top-level field for admin.useAsTitle. Never set admin.useAsTitle to a computed field configured with virtual: true; these fields are not queryable and Payload rejects the configuration. A relationship-path virtual such as virtual: 'author.name' is supported, but use it only when the title must come from a related document.

Basic Collection

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
    // _status (from versions.drafts) shows the draft/published state — no custom status field needed
    defaultColumns: ['title', 'author', '_status', 'createdAt'],
  },
  versions: {
    drafts: true,
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'slug', useAsSlug: 'title' }, // auto-generates from `title`, unique + indexed, sidebar position
    { name: 'content', type: 'richText' }, // long field — stays in the main area, not the sidebar
    // short, at-a-glance field — good sidebar candidate
    { name: 'author', type: 'relationship', relationTo: 'users', admin: { position: 'sidebar' } },
  ],
  timestamps: true,
}

For more collection patterns (auth, upload, drafts, live preview), see COLLECTIONS.md.

Common Fields

// Text field
{ name: 'title', type: 'text', required: true }

// Relationship
{ name: 'author', type: 'relationship', relationTo: 'users', required: true }

// Rich text
{ name: 'content', type: 'richText', required: true }

// Slug — use the native field type instead of a hand-rolled text field
{ name: 'slug', type: 'slug', useAsSlug: 'title' }

// Select (for genuine taxonomy — NOT publish state; use versions.drafts + _status for that)
{ name: 'category', type: 'select', options: ['news', 'tutorial', 'opinion'] }

// Upload
{ name: 'image', type: 'upload', relationTo: 'media' }

For all field types (array, blocks, point, join, virtual, conditional, etc.), see FIELDS.md.

Hook Example

Hooks live at one of two levels and they are not interchangeable. Collection hooks receive { doc, data, req, operation, ... } and act on the whole document. Field hooks live inside an individual field's hooks object, receive { value, siblingData, ... }, and return the new value for that field. Computed/virtual fields, per-field formatters, and per-field access masking are field hooks; cross-field business logic is a collection hook.

// Collection-level: business logic across the document
export const Posts: CollectionConfig = {
  slug: 'posts',
  hooks: {
    beforeChange: [
      async ({ data, operation }) => {
        if (operation === 'create') {
          data.slug = slugify(data.title)
        }
        return data
      },
    ],
  },
  fields: [{ name: 'title', type: 'text' }],
}

// Field-level: compute / format a single field's value (virtual fields use this)
export const Users: CollectionConfig = {
  slug: 'users',
  fields: [
    { name: 'firstName', type: 'text' },
    { name: 'lastName', type: 'text' },
    {
      name: 'fullName',
      type: 'text',
      virtual: true,
      hooks: {
        afterRead: [({ siblingData }) => `${siblingData.firstName} ${siblingData.lastName}`],
      },
    },
  ],
}

When asked to "compute a field" or "populate a field's value in a hook", use a field-level hook on that field — never a collection-level afterRead that mutates doc.

For all hook patterns, see HOOKS.md. For access control, see ACCESS-CONTROL.md.

Access Control with Type Safety

import type { Access } from 'payload'
import type { User } from '@/payload-types'

// Type-safe access control
export const adminOnly: Access = ({ req }) => {
  const user = req.user as User
  return user?.roles?.includes('admin') || false
}

// Row-level access control
export const ownPostsOnly: Access = ({ req }) => {
  const user = req.user as User
  if (!user) return false
  if (user.roles?.includes('admin')) return true

  return {
    author: { equals: user.id },
  }
}

Query Example

// Local API
const posts = await payload.find({
  collection: 'posts',
  where: {
    status: { equals: 'published' },
    'author.name': { contains: 'john' },
  },
  depth: 2,
  limit: 10,
  sort: '-createdAt',
})

// Query with populated relationships
const post = await payload.findByID({
  collection: 'posts',
  id: '123',
  depth: 2, // Populates relationships (default is 2)
})
// Returns: { author: { id: "user123", name: "John" } }

// Without depth, relationships return IDs only
const post = await payload.findByID({
  collection: 'posts',
  id: '123',
  depth: 0,
})
// Returns: { author: "user123" }

For all query operators and REST/GraphQL examples, see QUERIES.md.

Getting Payload Instance

// In API routes (Next.js)
import { getPayload } from 'payload'
import config from '@payload-config'

export async function GET() {
  const payload = await getPayload({ config })

  const posts = await payload.find({
    collection: 'posts',
  })

  return Response.json(posts)
}

// In Server Components
import { getPayload } from 'payload'
import config from '@payload-config'

export default async function Page() {
  const payload = await getPayload({ config })
  const { docs } = await payload.find({ collection: 'posts' })

  return <div>{docs.map(post => <h1 key={post.id}>{post.title}</h1>)}</div>
}

Security Pitfalls

1. Local API Access Control (CRITICAL)

By default, Local API operations bypass ALL access control, even when passing a user.

// ❌ SECURITY BUG: Passes user but ignores their permissions
await payload.find({
  collection: 'posts',
  user: someUser, // Access control is BYPASSED!
})

// ✅ SECURE: Actually enforces the user's permissions
await payload.find({
  collection: 'posts',
  user: someUser,
  overrideAccess: false, // REQUIRED for access control
})

When to use each:

  • overrideAccess: true (default) - Server-side operations you trust (cron jobs, system tasks)
  • overrideAccess: false - When operating on behalf of a user (API routes, webhooks)

See QUERIES.md#access-control-in-local-api.

2. Transaction Failures in Hooks

Nested operations in hooks without req break transaction atomicity.

// ❌ DATA CORRUPTION RISK: Separate transaction
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.create({
        collection: 'audit-log',
        data: { docId: doc.id },
        // Missing req - runs in separate transaction!
      })
    },
  ]
}

// ✅ ATOMIC: Same transaction
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.create({
        collection: 'audit-log',
        data: { docId: doc.id },
        req, // Maintains atomicity
      })
    },
  ]
}

See ADAPTERS.md#threading-req-through-operations.

3. Infinite Hook Loops

Hooks triggering operations that trigger the same hooks create infinite loops.

// ❌ INFINITE LOOP
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.update({
        collection: 'posts',
        id: doc.id,
        data: { views: doc.views + 1 },
        req,
      }) // Triggers afterChange again!
    },
  ]
}

// ✅ SAFE: Use context flag
hooks: {
  afterChange: [
    async ({ doc, req, context }) => {
      if (context.skipHooks) return

      await req.payload.update({
        collection: 'posts',
        id: doc.id,
        data: { views: doc.views + 1 },
        context: { skipHooks: true },
        req,
      })
    },
  ]
}

See HOOKS.md#context.

Project Structure

src/
├── app/
│   ├── (frontend)/
│   │   └── page.tsx
│   └── (payload)/
│       └── admin/[[...segments]]/page.tsx
├── collections/
│   ├── Posts.ts
│   ├── Media.ts
│   └── Users.ts
├── globals/
│   └── Header.ts
├── components/
│   └── CustomField.tsx
├── hooks/
│   └── slugify.ts
└── payload.config.ts

Building & Type Generation

Payload generates payload-types.ts for you — you rarely need to run generate:types by hand.

  • During development: typescript.autoGenerate defaults to true, so the dev server regenerates types automatically whenever your config changes. Don't run generate:types manually while the dev server is running — it's redundant.
  • During builds: payload build generates the import map and types before running next build. Prefer it over calling next build directly so neither is ever stale. Pass --no-types to skip type generation.
  • Manual generation (payload generate:types) is an escape hatch — only when neither the dev server nor a build is in the loop (e.g. a one-off script, or CI before a step that doesn't run payload build).
// payload.config.ts
export default buildConfig({
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
    // autoGenerate defaults to true — types regenerate in dev automatically
  },
})

// Usage
import type { Post, User } from '@/payload-types'

Common Gotchas

  1. Local API bypasses access control unless you pass overrideAccess: false
  2. Missing req in nested operations breaks transaction atomicity
  3. Hook loops — operations in hooks can re-trigger the same hooks; use req.context flags
  4. Field-level access returns boolean only, no query constraints
  5. Relationship depth defaults to 2; set depth: 0 for IDs only
  6. Draft status_status field is auto-injected when drafts are enabled
  7. Types regenerate automatically in dev (autoGenerate) and during payload build — avoid running generate:types manually
  8. MongoDB transactions require replica set configuration
  9. SQLite transactions are disabled by default; enable with transactionOptions: {}
  10. Point fields are not supported in SQLite
  11. Computed virtual titles — fields configured with virtual: true cannot be used in admin.useAsTitle; use a stored top-level field

Best Practices

Content Modeling

  • Enable versions: { drafts: true } by default on content collections; rely on the auto-injected _status field rather than adding a custom status field
  • Use the native slug field type for slugs instead of hand-rolling a unique text field
  • Use a stored top-level field for admin.useAsTitle; never use a computed virtual: true field as the title
  • Reserve position: 'sidebar' for short, at-a-glance fields (status, category, author, date); keep long fields (description, rich text) in the main area

Security

  • Default to restrictive access, gradually add permissions
  • Use overrideAccess: false when passing user to Local API
  • Field-level access only returns boolean (no query constraints)
  • Never trust client-provided data
  • Use saveToJWT: true for roles to avoid database lookups

Performance

  • Index frequently queried fields
  • Use select to limit returned fields
  • Set maxDepth on relationships to prevent over-fetching
  • Prefer query constraints over async operations in access control
  • Cache expensive operations in req.context

Data Integrity

  • Always pass req to nested operations in hooks
  • Use context flags to prevent infinite hook loops
  • Enable transactions for MongoDB (requires replica set) and Postgres
  • Use beforeValidate for data formatting
  • Use beforeChange for business logic

Type Safety

  • Let dev (autoGenerate) and payload build generate types; run generate:types manually only when neither is running
  • Import types from generated payload-types.ts
  • Type your user object: import type { User } from '@/payload-types'
  • Use field type guards for runtime type checking
  • When extracting any Payload value into a named constant — a collection, field, hook, access function, plugin, etc. — annotate it with the matching Payload type (CollectionConfig, Field, CollectionBeforeChangeHook, Access, Plugin, …) or use satisfies <Type>. Without an annotation, string properties like type: 'text' widen to string and discriminated unions (Field, CollectionConfig) fail to resolve. Inline literals get this for free via contextual typing; extracted constants do not.

Organization

  • Keep collections in separate files
  • Extract access control to access/ directory
  • Extract hooks to hooks/ directory
  • Use reusable field factories for common patterns
  • Document complex access control with comments

Reference Documentation

  • FIELDS.md - All field types, validation, admin options
  • FIELD-TYPE-GUARDS.md - Type guards for runtime field type checking and narrowing
  • COLLECTIONS.md - Collection configs, auth, upload, drafts, live preview
  • HOOKS.md - Collection hooks, field hooks, context patterns
  • ACCESS-CONTROL.md - Collection, field, global access control, RBAC, multi-tenant
  • ACCESS-CONTROL-ADVANCED.md - Context-aware, time-based, subscription-based access, factory functions, templates
  • QUERIES.md - Query operators, Local/REST/GraphQL APIs
  • ENDPOINTS.md - Custom API endpoints: authentication, helpers, request/response patterns
  • ADAPTERS.md - Database, storage, email adapters, transactions
  • ADVANCED.md - Authentication, jobs, endpoints, components, plugins, localization
  • PLUGIN-DEVELOPMENT.md - Plugin architecture, monorepo structure, patterns, best practices

Resources

Frequently asked questions

What to verify before installation and use

What does the payload source document cover?

Payload is a Next.js native CMS with TypeScript-first architecture, providing admin panel, database management, REST/GraphQL APIs, authentication, and file storage.

How do I install payload?

The source record exposes this install command: npx skills add https://github.com/payloadcms/payload --skill "packages/payload/skills/payload". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged exec-script, read-files in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing

Computed 10045,511

coreyhaines31/marketingskills

ab-testing

When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

Computed 10029,034

garrytan/gbrain

bulk-ingestion

End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.

Computed 10024,921

alirezarezvani/claude-skills

app-store-optimization

App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

Computed 1005,241

dotnet/skills

migrate-vstest-to-mtp

Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing