Ir al contenido

Strapi Cheat Sheet

Overview

Strapi is the leading open-source headless CMS built with Node.js. It provides an auto-generated REST and GraphQL API, a customizable admin panel for content editors, and a flexible plugin system. Strapi lets you define content types through the admin UI or code, and it automatically generates CRUD endpoints for each type.

Strapi supports PostgreSQL, MySQL, MariaDB, and SQLite as database backends. It includes a role-based access control system, media library with image optimization, internationalization (i18n), and webhook integrations. Content can be delivered to any frontend framework, mobile app, or IoT device through its API.

Installation

# Create a new Strapi project
npx create-strapi-app@latest my-project

# With specific database
npx create-strapi-app@latest my-project --dbclient=postgres

# Quick start with SQLite (no prompts)
npx create-strapi-app@latest my-project --quickstart

# Start development server
cd my-project
npm run develop

# Admin panel: http://localhost:1337/admin
# API: http://localhost:1337/api

Docker

# docker-compose.yml
version: "3"
services:
  strapi:
    image: strapi/strapi:latest
    environment:
      DATABASE_CLIENT: postgres
      DATABASE_HOST: db
      DATABASE_PORT: 5432
      DATABASE_NAME: strapi
      DATABASE_USERNAME: strapi
      DATABASE_PASSWORD: strapi
    ports:
      - "1337:1337"
    volumes:
      - ./app:/srv/app
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: strapi
      POSTGRES_USER: strapi
      POSTGRES_PASSWORD: strapi
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Core Commands

CommandDescription
npm run developStart in development mode with auto-reload
npm run startStart in production mode
npm run buildBuild the admin panel
npm run strapi generateGenerate components, APIs, plugins
npm run strapi routes:listList all registered routes
npm run strapi ts:generate-typesGenerate TypeScript types
npm run strapi configuration:dumpExport configuration
npm run strapi configuration:restoreImport configuration
npm run strapi transferTransfer data between instances

REST API

CRUD Operations

# List entries (with pagination)
curl "http://localhost:1337/api/articles?pagination[page]=1&pagination[pageSize]=25"

# Get single entry
curl "http://localhost:1337/api/articles/1"

# Create entry
curl -X POST "http://localhost:1337/api/articles" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer JWT_TOKEN" \
  -d '{"data":{"title":"New Article","content":"Article body","publishedAt":"2026-01-01T00:00:00.000Z"}}'

# Update entry
curl -X PUT "http://localhost:1337/api/articles/1" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer JWT_TOKEN" \
  -d '{"data":{"title":"Updated Title"}}'

# Delete entry
curl -X DELETE "http://localhost:1337/api/articles/1" \
  -H "Authorization: Bearer JWT_TOKEN"

Filtering and Population

# Filter results
curl "http://localhost:1337/api/articles?filters[title][$contains]=hello"

# Deep filtering
curl "http://localhost:1337/api/articles?filters[category][name][$eq]=tech"

# Populate relations
curl "http://localhost:1337/api/articles?populate=*"

# Nested population
curl "http://localhost:1337/api/articles?populate[author][populate]=avatar"

# Sort and pagination
curl "http://localhost:1337/api/articles?sort=createdAt:desc&pagination[page]=1&pagination[pageSize]=10"

# Select specific fields
curl "http://localhost:1337/api/articles?fields[0]=title&fields[1]=slug"

Filter Operators

OperatorExampleDescription
$eqfilters[status][$eq]=publishedEqual
$nefilters[status][$ne]=draftNot equal
$lt / $ltefilters[price][$lt]=100Less than
$gt / $gtefilters[price][$gt]=10Greater than
$infilters[status][$in][0]=publishedIn array
$notInfilters[status][$notIn][0]=archivedNot in array
$containsfilters[title][$contains]=helloContains substring
$startsWithfilters[title][$startsWith]=HowStarts with
$nullfilters[deletedAt][$null]=trueIs null

Configuration

Database Configuration

// config/database.js
module.exports = ({ env }) => ({
  connection: {
    client: "postgres",
    connection: {
      host: env("DATABASE_HOST", "127.0.0.1"),
      port: env.int("DATABASE_PORT", 5432),
      database: env("DATABASE_NAME", "strapi"),
      user: env("DATABASE_USERNAME", "strapi"),
      password: env("DATABASE_PASSWORD", "strapi"),
      ssl: env.bool("DATABASE_SSL", false),
    },
  },
})

Server Configuration

// config/server.js
module.exports = ({ env }) => ({
  host: env("HOST", "0.0.0.0"),
  port: env.int("PORT", 1337),
  url: env("PUBLIC_URL", "http://localhost:1337"),
  app: {
    keys: env.array("APP_KEYS"),
  },
})

Plugin Configuration

// config/plugins.js
module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: "aws-s3",
      providerOptions: {
        s3Options: {
          credentials: {
            accessKeyId: env("AWS_ACCESS_KEY_ID"),
            secretAccessKey: env("AWS_ACCESS_SECRET"),
          },
          region: env("AWS_REGION"),
          params: { Bucket: env("AWS_BUCKET") },
        },
      },
    },
  },
  email: {
    config: {
      provider: "sendgrid",
      providerOptions: {
        apiKey: env("SENDGRID_API_KEY"),
      },
      settings: {
        defaultFrom: "noreply@example.com",
        defaultReplyTo: "support@example.com",
      },
    },
  },
  graphql: {
    config: {
      defaultLimit: 25,
      maxLimit: 100,
    },
  },
})

Advanced Usage

Custom Controllers

// src/api/article/controllers/article.js
const { createCoreController } = require("@strapi/strapi").factories

module.exports = createCoreController("api::article.article", ({ strapi }) => ({
  async find(ctx) {
    const { data, meta } = await super.find(ctx)
    // Add custom logic
    return { data, meta }
  },

  async customAction(ctx) {
    const entries = await strapi.entityService.findMany("api::article.article", {
      filters: { publishedAt: { $notNull: true } },
      sort: { createdAt: "desc" },
      limit: 10,
    })
    return entries
  },
}))

Custom Routes

// src/api/article/routes/custom.js
module.exports = {
  routes: [
    {
      method: "GET",
      path: "/articles/featured",
      handler: "article.customAction",
      config: {
        auth: false,
      },
    },
  ],
}

Lifecycle Hooks

// src/api/article/content-types/article/lifecycles.js
module.exports = {
  async beforeCreate(event) {
    const { data } = event.params
    if (data.title) {
      data.slug = data.title.toLowerCase().replace(/\s+/g, "-")
    }
  },

  async afterCreate(event) {
    const { result } = event
    await strapi.service("api::notification.notification").send({
      message: `New article: ${result.title}`,
    })
  },
}

Webhooks

// Configure in Admin > Settings > Webhooks
// Or programmatically
// Triggers: entry.create, entry.update, entry.delete, entry.publish, entry.unpublish

Troubleshooting

IssueSolution
Admin panel blank after buildRun npm run build to rebuild the admin; clear browser cache
Database connection refusedVerify database credentials and host; ensure DB service is running
API returning 403Check permissions in Settings > Roles; enable public access for the endpoint
Slow API responsesAdd indexes to database; use populate selectively instead of populate=*
Upload failsCheck file size limits in config/plugins.js; verify storage permissions
TypeScript types outdatedRun npm run strapi ts:generate-types after content type changes
Migration errors after upgradeBack up database first; follow Strapi migration guides for version jumps
GraphQL not availableInstall plugin: npm run strapi install graphql
i18n content missingEnable i18n on the content type; create content for each locale