Use familiar web technology
Build with Nuxt, Vue, TypeScript and Hono rather than a proprietary template language.
export const defaultSiteConfig = {
id: "default",
defaultLocale: "en",
extensions: starterManifests
}
export const defaultSiteSdk = createStarterSdk()Keep source control, TypeScript, schemas, API contracts and tests. Habitat connects them to authoring and business tools in Studio.
Build with Nuxt, Vue, TypeScript and Hono rather than a proprietary template language.
Use typed blocks, collections and schemas for rendering, migrations and reuse.
Add blocks, routes, business tools and integrations while Studio remains consistent.
Run and test locally, then publish through Journi hosting. Ask us about data-residency requirements.
Follow real examples for a page block, reusable collection, validated API route and business workspace. Each snippet is shortened from the current repository.
A block owns its content schema, editing fields, defaults and published HTML. This shortened example follows the built-in Hero definition.
hero-blockconst hero = createBlock({
type: "hero", name: "Hero", category: "marketing",
schema: z.object({
eyebrow: z.string().max(80).default("Local business"),
heading: z.string().max(120),
body: z.string().max(1_000),
ctaLabel: z.string().max(60), ctaUrl: linkValueSchema
}),
editor: { fields: [
{ key: "heading", label: "Heading", type: "text" },
{ key: "body", label: "Introduction", type: "textarea" }
] },
render: (data) => `<section class="block block-hero">…</section>`
})Collections keep repeatable records typed and publishable. This is abbreviated from the Blog definition installed by the default site.
blog-collectionconst blog = {
id: state.settings.blog.collectionId,
name: "Blog", slug: "blog",
version: 1,
fields: [
{ id: "title", name: "Title", type: "text", required: true },
{ id: "summary", name: "Summary", type: "text", required: false },
{ id: "body", name: "Article", type: "richText", required: true }
],
rendering: { enabled: true, titleField: "title", templatePageId: null },
seo: { structuredDataType: "BlogPosting", descriptionField: "summary" }
}The booking route is registered from the shared operation inventory, validates the request and writes through Habitat's state boundary.
booking-routeapp.post(apiPath("booking.create"), async (c) => {
const key = requireIdempotencyKey(c)
const input = createBookingInputSchema.parse(await c.req.json())
let booking: Booking | null = null
await mutatePublicState(dependencies.repository, siteId, (state) => {
const result = createBooking(state, input, key)
booking = result.booking
return result.state
})
return c.json(booking!, 201)
})This is the current Bookings module contribution. The manifest declares the capability and the module maps it to real operations and Studio state.
bookings-moduledefineHabitatExtension({
manifest: {
id: "habitat.module.bookings",
name: "Bookings", version: "0.1.0",
kind: "module", capabilities: ["bookings"],
permissions: ["forms:manage"], trusted: true
},
modules: [{
id: "bookings", name: "Bookings",
capability: "bookings",
apiOperations: ["booking.service.upsert", "booking.create", "booking.status"],
studioSections: ["Operations"],
stateKeys: ["bookingServices", "bookings"]
}]
})A capability defines what the editor can change, how the public site renders it, which operations it creates and which permissions protect it.
Habitat fits source control, testing, review and managed release into one repeatable route.
Run the site, Studio and supporting services together with normal source control and local feedback.
Type checks, schemas and generated API contracts catch drift between content, Studio and the published site.
Preview responsive pages and the editing controls that clients will use before a release is accepted.
Ship the versioned site package through Journi hosting while keeping project-specific integrations explicit.
Types, schemas and API definitions keep the editor, integrations and published site working from the same model.
Share the same content shape between block code, collection data, editors and validation.
Use a generated API contract for integrations, client tooling and regression checks.
Versioned Markdown and llms.txt explain the supported model without asking an agent to infer it from the UI.
Machine-readable validation output makes automation useful in local development and delivery pipelines.
Build against clear boundaries without taking on Habitat hosting and release maintenance.
Join agency early access or browse the blocks and capability types already available.