Reusable Components.
Define reusable field groups with defineComponent() or build them visually in the admin panel. Embed single or multiple instances across any collection or single.
Components are reusable field groups that you define once and embed anywhere. Think of them like building blocks: an SEO metadata component, a hero section, or a CTA block. Define the fields once, then use the component() field type to embed them in any collection or single.
You can use a component as a single instance (one SEO block per page), as a repeatable list (multiple feature cards), or as a dynamic zone where editors choose from several component types to build flexible layouts.
Each component gets its own database table, and instances are linked to their parent entry via foreign keys. Components can nest up to 3 levels deep, with automatic circular reference detection.
Key capabilities
- Define Once, Reuse Everywhere — Create a component like SEO metadata or a hero section once, then embed it across any collection, single, or other component.
- Nestable Up to 3 Levels — Components can contain other components. Build complex layouts from simple building blocks, up to 3 levels of nesting with circular reference protection.
- Dynamic Zones — Let editors choose from multiple component types in a single field. Build flexible page layouts where each section can be a different component.
- All Field Types — Components support every field type: text, rich text, uploads, relationships, selects, arrays, groups, and even nested components.
Define and use a component
Define components in TypeScript for version control and type safety, or build them visually in the admin panel. Both approaches produce the same reusable component.
Define the component:
import { defineComponent, text, upload, select } from "nextly/config";
export default defineComponent({
slug: "hero",
label: { singular: "Hero Section" },
admin: {
category: "Blocks",
icon: "Image",
},
fields: [
text({ name: "heading", required: true }),
text({ name: "subheading" }),
upload({
name: "backgroundImage",
relationTo: "media",
}),
text({ name: "ctaText" }),
text({ name: "ctaLink" }),
select({
name: "alignment",
options: [
{ label: "Left", value: "left" },
{ label: "Center", value: "center" },
{ label: "Right", value: "right" },
],
defaultValue: "center",
}),
],
});Use it in a collection:
import { defineCollection, text, component } from "nextly/config";
export default defineCollection({
slug: "pages",
fields: [
text({ name: "title", required: true }),
text({ name: "slug", unique: true }),
// Single component instance
component({
name: "seo",
component: "seo",
}),
// Dynamic zone — editors pick from multiple component types
component({
name: "layout",
components: ["hero", "cta", "testimonial", "content"],
repeatable: true,
maxRows: 20,
admin: { isSortable: true },
}),
],
});Code-defined components are locked in the UI, so edits happen in your codebase. UI-built components can be modified by any admin user.
Components inside components
Nest components up to 3 levels deep. Circular references are automatically detected and prevented.
- Level 1 — Collection "pages" embeds component("layout")
- Level 2 — Component "hero" embeds component("cta")
- Level 3 — Component "cta" — fields only (max depth)
Each component gets its own database table (comp_hero, comp_cta). Instances are linked to their parent entry via foreign keys.
Start building with Nextly
Free, open source, and yours to own. No sign-up required.