npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@notum-cz/strapi-plugin-smart-populate

v1.0.1

Published

Smart populate utilities for Strapi content.

Downloads

424

Readme

Table of Contents

About the Project

Why this plugin exists

Large Strapi projects often contain many reusable components inside dynamic zones. As the content model grows, the populate object needed to fetch those components can become very large. Sending that object from the frontend on every request means Strapi has to parse, validate, and process a heavy populate query again and again.

That can make Strapi slower, especially for pages with many dynamic zones and nested components. In more demanding projects, the API can become unstable or start failing under load.

@notum-cz/strapi-plugin-smart-populate moves that responsibility into Strapi. Instead of sending a large populate object from the frontend, callers can use "smart" where they want Strapi to resolve the correct component populate shape.

How it works

When Strapi starts, the plugin reads the available component schemas and builds a smart populate map for components, nested components, media fields, and relations. When a REST query or a Documents API call contains "smart" inside populate, the plugin replaces it with the generated populate object that matches the current content type, component, or dynamic zone.

Relations that need a more specific shape can be configured with populateOverrides. See Populate Overrides for details.

Features

  • Uses "smart" as a compact populate token for dynamic zones and components.
  • Generates populate configuration from Strapi component schemas at bootstrap.
  • Supports multiple dynamic zones in the same request.
  • Supports components, and nested component paths.
  • Supports media and relation attributes inside generated component populate.
  • Supports manual populateOverrides for project-specific relation shapes.
  • Provides TypeScript helpers for smart populate params, editor autocomplete, and typed overrides.
  • Includes a Content-Type Builder admin banner for components with overrides.

Supported Versions

This plugin is compatible with Strapi v5.x.x and has been tested on Strapi v5.48.0. We expect it should also work on older versions of Strapi V5.

| Plugin version | Strapi Version | Full Support | | -------------- | -------------- | ------------ | | 0.x | ^5.48.0 | ✅ |

Getting Started

Installation

Install the plugin via npm or yarn:

# NPM
npm install @notum-cz/strapi-plugin-smart-populate

# Yarn
yarn add @notum-cz/strapi-plugin-smart-populate

Enable the plugin

Create or update config/plugins.ts in your Strapi app:

export default () => ({
  'smart-populate': {
    enabled: true,
  },
});

Rebuild Strapi and start the app:

yarn build
yarn develop

Add the REST middleware

To use "smart" in REST API queries, add the plugin middleware to config/middlewares.ts.

Place it after strapi::query and before strapi::body. At that point Strapi has already parsed the query, but has not yet validated the populate value.

export default [
  'strapi::errors',
  'strapi::security',
  'strapi::cors',
  'strapi::poweredBy',
  'strapi::logger',
  'strapi::query',
  // Position is important, place after `strapi::query` and before `strapi::body`.
+ 'plugin::smart-populate.sanitize-smart-populate',
  'strapi::body',
  'strapi::session',
  'strapi::favicon',
  'strapi::public',
];

The Documents API middleware is registered automatically during the plugin bootstrap lifecycle.

Usage

Use "smart" where you would normally provide a large populate object for a component or dynamic zone.

You can use it for one or many dynamic zones in the same query. The plugin collects all "smart" paths and resolves each of them independently.

Documents API

await strapi.documents('api::page.page').findMany({
  populate: {
    content: 'smart',
    footerBlocks: 'smart',
  },
});

REST API

const query = qs.stringify({
  populate: {
    content: 'smart',
  },
});

Components and nested components

The token also works for component attributes:

await strapi.documents('api::page.page').findOne({
  documentId,
  populate: {
    seo: 'smart',
  },
});

And it can be used deeper inside an existing populate object:

await strapi.documents('api::page.page').findMany({
  populate: {
    sections: {
      populate: {
        items: 'smart',
      },
    },
  },
});

The plugin collects all "smart" paths, replaces them with a native Strapi-safe populate value before request validation, and then injects the generated populate object before the final Documents API query runs.

Populate Overrides

The generated populate object is based on Strapi schemas. That is a good default for most components, nested components, media fields, and relations.

Relations are intentionally populated only at the first level by default. Relations can become very large, so it is usually better to control them manually instead of letting an automatic populate generator expand them too far.

You may want to limit it to a small set of fields, or explicitly expand it when the project needs a deeper relation shape. For example, a link component may only need the fullPath field from a related page. Use populateOverrides for those cases.

Typed overrides

If you want TypeScript to validate the override shape, create a component populate map in the host Strapi project and pass it to PopulateOverrideEntries.

The plugin cannot create this map internally because it does not have access to your generated Strapi component UIDs and schemas. Those types only exist inside the consuming Strapi project.

import type { Modules, UID } from '@strapi/strapi';
import type { PopulateOverrideEntries } from '@notum-cz/strapi-plugin-smart-populate/types';

type ComponentPopulateMap = {
  [TComponentUID in UID.Component]: Required<
    Modules.Documents.Params.Pick<TComponentUID, 'populate:object'>
  >['populate'];
};

const populateOverrides = [
  {
    componentUid: 'utilities.link',
    mergeWithGeneratedPopulate: true,
    overridePopulate: {
      page: {
        fields: ['fullPath'],
      },
    },
  },
] satisfies PopulateOverrideEntries<ComponentPopulateMap>;

export default () => ({
  'smart-populate': {
    enabled: true,
    config: {
      populateOverrides,
    },
  },
});

You can also write populateOverrides manually without satisfies. The helper type only exists to make the config easier to validate and maintain.

Merging behavior

When mergeWithGeneratedPopulate is true, the override is merged with the schema-generated populate object for that component.

When mergeWithGeneratedPopulate is omitted or false, overridePopulate becomes the full populate object for that component.

TypeScript

The plugin exports generic wrapper types from @notum-cz/strapi-plugin-smart-populate/types.

These helpers intentionally do not import generated Strapi schemas. A plugin package does not know the generated types of the project that consumes it. The intended pattern is to export your own project types from the Strapi app and wrap the relevant Strapi params with the helpers from this plugin.

When those wrapped params are used in your project, TypeScript keeps the native Strapi populate shape and adds "smart" as an available value in populate positions. That means your editor can autocomplete the smart token where it is valid instead of forcing every caller to remember or manually type the string.

Minimal wrapper

import type { Modules, UID } from '@strapi/strapi';
import type { WithSmartPopulate } from '@notum-cz/strapi-plugin-smart-populate/types';

export type FindMany<TContentTypeUID extends UID.ContentType> = WithSmartPopulate<
  Modules.Documents.ServiceParams<TContentTypeUID>['findMany']
>;

Project type export example (Experimental)

This is the pattern we as Notum commonly use in project-level Strapi type exports:

import type { Modules, UID } from '@strapi/strapi';
import type {
  WithSmartPopulate,
  WithSmartPopulateResultParams,
} from '@notum-cz/strapi-plugin-smart-populate/types';

// Re-export document engine service function types
export type FindMany<TContentTypeUID extends UID.ContentType> = WithSmartPopulate<
  Modules.Documents.ServiceParams<TContentTypeUID>['findMany']
>;

export type FindFirst<TContentTypeUID extends UID.ContentType> = WithSmartPopulate<
  Modules.Documents.ServiceParams<TContentTypeUID>['findFirst']
>;

export type FindOne<TContentTypeUID extends UID.ContentType> = WithSmartPopulate<
  Modules.Documents.ServiceParams<TContentTypeUID>['findOne']
>;

// Re-export original Result type
export type Result<
  TSchemaUID extends UID.Schema,
  TParams extends { populate?: unknown } = never,
> = Modules.Documents.Result<
  TSchemaUID,
  WithSmartPopulateResultParams<
    TParams,
    Modules.Documents.Params.Pick<TSchemaUID, 'fields' | 'populate'>
  >
>;

If you want to support also fetchAll functions. You can add more robust type configuration for Result export.

export type Result<
  TUID extends UID.ContentType,
  TParams extends { populate?: unknown } = never,
> = WithSmartPopulateResult<
  Modules.Documents.Result<
    TUID,
    WithSmartPopulateResultParams<
      TParams,
      Modules.Documents.Params.Pick<TUID, 'fields' | 'populate'>
    >
  >,
  TParams,
  {
    contentType: Data.ContentType<TUID>;
    populatableKeys: Extract<Schema.PopulatableAttributeNames<TUID>, keyof Data.ContentType<TUID>>;
  }
>;

Frontend apps and shared packages can then import from your project-owned Strapi type export:

import type { FindMany, Result } from '@repo/strapi/types';

type PageFindManyParams = FindMany<'api::page.page'>;
type PageResult<TParams extends { populate?: unknown } = never> = Result<'api::page.page', TParams>;

You can also see this pattern used in the latest version of our Strapi + Next.js monorepo starter.

Admin Banner

The plugin adds a small Content-Type Builder integration. When you open a component that has a matching populateOverrides entry, the admin displays a banner on that component screen.

The banner color depends on how the override is configured:

Merged override warning: If mergeWithGeneratedPopulate is true, the banner is displayed as a warning. The component still uses the generated populate config, but the manual override is merged into it. Smart populate merged override warning

Manual override alert: If mergeWithGeneratedPopulate is omitted or false, the banner is displayed as a red alert. In this mode the manual override fully replaces the generated populate config for that component. Smart populate manual override alert

This makes schema maintenance safer. When someone changes a component schema in the Content-Type Builder, the banner makes it visible that the smart populate behavior is partially or fully controlled by a manual override and should be reviewed.

(We are currently facing some issues with Admin Banner on mobile devices.)

🤝 Community

Maintained by Notum Technologies

Built and maintained by Notum Technologies, a Czech-based Strapi Enterprise Partner with a passion for open-source tooling.

Current maintainer

Libor Říha

Contributors

Contributing

Contributions of all kinds are welcome: code, documentation, bug reports, and feature ideas. Browse the open issues to find something to work on, or open a new one to start a discussion. Pull requests are always appreciated!

If you'd like to directly contribute, check our Contributions document.