QUESTPIE
Build Your WorkspaceBlocks

Defining Blocks

Server-side block definitions — fields, admin metadata, and categories.

Blocks are defined in blocks/ using the block() factory. Each block has fields, admin metadata, and optional prefetch config.

Basic Block

blocks/hero.ts
import { block } from "#questpie/factories";

export const heroBlock = block("hero")
	.admin(({ c }) => ({
		label: { en: "Hero Section", sk: "Hero sekcia" },
		icon: c.icon("ph:image"),
		category: "sections",
	}))
	.fields(({ f }) => ({
		title: f.text().required().localized(),
		subtitle: f.textarea().localized(),
		backgroundImage: f.upload({ to: "assets" }),
		overlayOpacity: f.number().default(60),
		alignment: f.select(["left", "center", "right"]).default("center"),
		ctaText: f.text().localized(),
		ctaLink: f.text(),
	}))
	.prefetch({ with: { backgroundImage: true } });

Admin Metadata

.admin(({ c }) => ({
  label: { en: "Hero Section" },      // Display name in block picker
  icon: c.icon("ph:image"),           // Icon in block picker
  category: "sections",               // Group in block picker
}))

Using Blocks in Collections

Add a blocks field to any collection:

collections/pages.ts
import { collection } from "#questpie/factories";

export const pages = collection("pages").fields(({ f }) => ({
	title: f.text().required().localized(),
	slug: f.text().required(),
	content: f.blocks().localized(), // Block content field
}));

The admin renders a visual block editor for this field.

Multiple Blocks Per File

Export multiple named blocks from one file:

blocks/layout.ts
import { block } from "#questpie/factories";

export const twoColumnBlock = block("twoColumn")
	.admin(({ c }) => ({
		label: { en: "Two Columns" },
		icon: c.icon("ph:columns"),
		category: "layout",
	}))
	.fields(({ f }) => ({
		left: f.blocks(),
		right: f.blocks(),
	}));

export const spacerBlock = block("spacer")
	.admin(({ c }) => ({
		label: { en: "Spacer" },
		icon: c.icon("ph:arrows-out-line-vertical"),
		category: "layout",
	}))
	.fields(({ f }) => ({
		height: f.select(["sm", "md", "lg", "xl"]).default("md"),
	}));

On this page