Devs define blocks. Marketing assembles pages.
Define your component library once in TypeScript: hero sections, feature grids, testimonial carousels, CTAs. Your marketing team assembles landing pages in the admin panel without filing tickets or waiting for a developer.
Component Blocks
Use the component field with a list of block types. Editors pick and arrange blocks on each page. Devs control the available types.
Site Settings (Single)
Navigation links, footer content, and global CTAs as a single document. One place to update site-wide settings.
CTAs & Testimonials
Reusable CTA and testimonial collections. Reference them from page blocks without duplicating content across pages.
No CMS Subscription
Marketing teams get a page builder interface. Developers get TypeScript types. No third-party CMS subscription.
Marketing teams shouldn't need a developer to launch a landing page.
Hardcoded marketing pages require a developer to update copy, swap hero images, or add a new testimonial section. Visual page builders let marketing teams move fast but produce fragile, hard-to-maintain output that lives outside your codebase.
With Nextly, developers define the block types and their fields in TypeScript. Marketing editors assemble pages from those blocks in the admin. Everyone stays in their lane.
Marketing site schema: pages, navigation, CTAs
Pages collection with blocks
import {
defineCollection, text, component, group,
} from"@revnixhq/nextly/config";
export default defineCollection({
slug:"pages",
fields: [
text({ name:"title", required: true }),
text({ name:"slug", unique: true }),
// SEO metadata as a group
group({
name:"seo",
fields: [
text({ name:"metaTitle" }),
text({ name:"metaDescription" }),
],
}),
// Dynamic page layout - editors pick and arrange blocks
component({
name:"layout",
components: ["hero","features","testimonials","cta","faq"],
repeatable: true,
maxRows: 20,
}),
],
});Navigation (single)
import {
defineSingle, text, array, upload,
} from"@revnixhq/nextly/config";
export default defineSingle({
slug:"navigation",
fields: [
upload({ name:"logo", relationTo:"media" }),
array({
name:"links",
fields: [
text({ name:"label", required: true }),
text({ name:"url", required: true }),
],
}),
text({ name:"ctaLabel" }),
text({ name:"ctaUrl" }),
],
});CTAs collection
import {
defineCollection, text, select,
} from"@revnixhq/nextly/config";
export default defineCollection({
slug:"ctas",
fields: [
text({ name:"headline", required: true }),
text({ name:"subheadline" }),
text({ name:"primaryLabel", required: true }),
text({ name:"primaryUrl", required: true }),
text({ name:"secondaryLabel" }),
text({ name:"secondaryUrl" }),
select({
name:"style",
options: [
{ label:"Light", value:"light" },
{ label:"Dark", value:"dark" },
{ label:"Brand", value:"brand" },
],
}),
],
});Start building with Nextly
Free, open source, and yours to own. No sign-up required.
npx create-nextly-app@latest