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.