Skip to main content

Smart Population

@notum-cz/strapi-plugin-smart-populate expands "smart" populate tokens into native Strapi populate objects.

Use it for content that contains nested components, dynamic zones, media fields, or relations where hand-written populate trees would be repetitive. The plugin reads Strapi schemas at bootstrap and builds the default population shape from them.

Frontend Usage​

Pass "smart" for fields that should use schema-generated population:

In this example, the page fetch loads components in the content dynamic zone and populates all of their children. It also loads the seo component and populates its nested media/components.

import { PublicStrapiClient } from "@/lib/strapi-api"

const page = await PublicStrapiClient.fetchOneByFullPath(
"api::page.page",
fullPath,
{
locale,
status: "published",
populate: { seo: "smart", content: "smart" },
}
)

Effectively, "smart" gives the common nested SEO population out of the box. Without it, the same request would need explicit call parameters like:

const page = await PublicStrapiClient.fetchOneByFullPath(
"api::page.page",
fullPath,
{
locale,
status: "published",
populate: {
seo: {
populate: {
metaImage: true,
twitter: { populate: { images: true } },
og: { populate: { image: true } },
},
},
content: "smart",
},
}
)

Manual populate objects can still be used next to "smart" when an endpoint only needs a small custom shape.

Strapi Configuration​

Plugin registration lives in apps/strapi/config/plugins.ts:

import { smartPopulateConfig } from "./plugins/smart-populate"

export default () => {
return {
"smart-populate": smartPopulateConfig(),
}
}

This usually is enough for most content.

For extended customization, project-specific overrides live in apps/strapi/config/plugins/smart-populate.ts:

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

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 function smartPopulateConfig() {
return {
enabled: true,
config: {
populateOverrides,
},
}
}

Use populateOverrides only when generated component population needs relation-specific fields or depth. See the plugin README for populate override details.