Content files & fields

A content file is a TypeScript module whose default export is plain data. editsy infers the editing form from the values, so there is no schema to author.

Two shapes

defineContent({...}) for a single object (a page, the footer, settings) and defineCollection([...]) for repeated items (posts, projects, events):

import { defineContent, f } from "editsy";

export default defineContent({
  hero: {
    heading: "A tidy little website.",
    launched: "2026-07-02",
    body: f.markdown("Some **rich** text."),
  },
});

The wrappers are optional. A plain export default {...} works too (as const and satisfies included), which is how you adopt editsy on an existing site without touching its files. The wrappers add type-checking that keeps functions and JSX out of content.

What the values become

  • short string → text input
  • long string or one with line breaks → textarea
  • "2026-10-09" → date picker
  • number or boolean → matching inputs
  • string[] → a tag list
  • array of objects → a collection with add, duplicate, reorder, delete
  • nested object → a grouped fieldset

Field key names become form labels, so heroImage shows as "Hero Image". Name keys like labels.

Field annotations

When inference can't guess, wrap the value: f.markdown() for rich text (WYSIWYG in the editor, markdown in the file), f.html() when a site already stores HTML fragments (edited as rich text, stored as HTML; your site renders and sanitizes it like any HTML it sets), f.image() for an image picker over your public folder, f.url() for links, f.date(), f.textarea(). Every f.* helper returns its argument unchanged, so your site consumes plain data.

JSON files too

Plain .json files under your content globs are editable the same way: an object is a page, an array of objects is a collection. Handy for i18n dictionaries and config-style content. Field types are inferred (JSON has no annotations), and saves keep strict, valid JSON.

The one rule

Values must be JSON-serializable literals: strings, numbers, booleans, arrays, plain objects. No functions, no JSX, no computed values, no spreads. That constraint is what makes reliable file round-tripping possible, and npx editsy check enforces it.