Skip to content

Repository files navigation

Tailor

Tailor Author

A configurable headless CMS, built for learning content.

Traditional courses, adaptive learning paths, knowledge bases, content libraries - or a shape of your own. Author it in one place, reuse it across projects, and publish to storage you own.

LicenseVersionCINodepnpm

Documentation · What's new in X · Element Kit · Quickstart · Contributing


The Tailor editor: the outline on the left, a page composed of typed content elements on the right

The editor - your outline on the left, the page you are writing on the right

Built-in extensions: 27 content elements · 5 containers · 12 meta inputs
Every one is a swappable package, not core code · 10 example schemas included

Note

Tailor X is here. Read the release brief at x.tailor-cms.com.

Arrived from ExtensionEngine/tailor? You are in the right place - this is the project's current home, and the original repository is archived.

Why Tailor

A course is not a list of pages with media. Pedagogy decides shape, and every approach wants a different one:

  • Direct instruction runs linear - explain, demonstrate, check - and ends on a graded assessment.
  • Scenario-based learning branches through decisions and debriefs each choice, so the outline is a web, not a line.
  • Microlearning is small standalone units, revisited on a schedule, with no deep hierarchy at all.
  • Competency-based training gates every level until the learner passes, so structure and assessment are the same thing.
  • Blended and flipped designs split material into pre-work, live session and follow-up, each carrying different information.

Most content tools can express none of these, because they already decided the shape for you: here is a page, here are some fields, squeeze your material in.

The structure view: a nested outline, with the selected level's status, fields and comments alongside
Levels you name yourself, nested as deep as the material needs, each carrying its own information

Tailor starts from your model instead. You describe the shape your material actually takes - the levels it needs, the checkpoints along the way, the information each one carries - and the whole application reshapes itself around it: the editor, the validation, the permissions, the published output. Bespoke learning experiences, tailored to the pedagogy, with no fork and no custom build.

  • Configurable, not hardcoded. Content types are configuration. Changing your model is an edit, not a migration.
  • Deeply structured. Content is a tree you nest as far as your material needs, not a flat pile of entries.
  • Learning-shaped, not learning-locked. Assessments, question pools and progress are first-class - and the same schema system runs knowledge bases, Q&A libraries and article collections, all shipped as working examples.
  • Rich out of the box. 27 content elements, 5 containers and 12 meta inputs ship built in - and every one is an extension package, written with the same API you'd use for your own.
  • AI that earns its keep. A reviewer that scores your pages against rubrics, and an assistant that acts on whatever you have open.
  • Built for teams. Comments, revisions, workflow states, per-role access and live editing updates come as standard.
  • Publish once, consume anywhere. Publishing writes a clean, versioned manifest into storage you own - S3 or the filesystem. No proprietary delivery API sits between your content and whatever renders it: an LMS, your own app, a static site. Every built-in element also ships a Vue 3 display component, so rendering the result is not a from-scratch job.
  • MIT licensed. Self-host it, fork it, ship it.

Why not just use a regular headless CMS?

A typical headless CMSTailor
Your outlineA flat list of entries. Any hierarchy is something you fake with reference fields and slugs.A real tree, and you name the levels yourself - module, chapter, topic, unit, entry, whatever your material calls for. Each level sets what can sit inside it, and authors work directly in that tree.
Where content livesA rich-text field and a few extra fields. Whether it reads as a lesson or a quiz is your frontend's problem.Any level in your outline can hold content instead of more levels, and its type decides the shape that content takes - a reading page, a template of named sections, a timed exam, a pool of questions to draw from. You fill it with typed blocks: 27 in the box, from tables and flashcards to eight kinds of question.
The details you trackThe same fixed set of fields on every entry.You decide what each level carries - say, a duration on a module, a difficulty on a page, a source note on one image. Different fields at every level, all set in the schema.
Checking understandingNot something it does. You store questions as entries and grade them in another system.Eight kinds of question, graded or ungraded, written right next to the material they test - and grouped into an exam or a pool to draw from.
Using something twicePoint at another entry by its ID. A copy is a copy.Reuse one question, a page, or an entire module in another project. The copy stays in step with the original until you change it - then it's yours.
Making it fitYou can add new field types.Add a new kind of block, a new way to lay content out, a new field, or a whole app-wide feature. Four places to extend, and each project installs only the ones it uses.

Publishing a blog or a marketing site? Use one of those instead - they are better at it. Tailor earns its keep when the structure itself matters: real depth, checks along the way, information that differs per level, and material reused across projects.

What you can do

✍️ Author without detours

  • One workspace. Build the outline and write the content in the same view - add, reorder and edit anything inline, with no jumping between screens.
  • Discuss in place. Comment on any activity or individual element, resolve threads, and keep the conversation next to the work instead of in a chat app.
  • Find any element. Search every piece of content in a project, with highlighted snippets and in-place preview.
  • Every change on record. Browse a page's past versions, restore one with a click, or roll an entire project back to any point in its history.
  • See what a republish will change. Compare any page against the version already published, so nothing ships by surprise - and the project tells you at a glance when it has unpublished changes.
  • Templates with guardrails. Build a level out of named sections you define in the schema - each with its own fields and its own content - so every page of that kind comes out consistent.
  • Author in any language. Switch your working language and translate rich text inline; visual cues flag what's still untranslated.
  • Make it yours. Light and dark themes, plus a color system to rebrand the whole app.

A rich-text element selected for editing, with its formatting toolbar above and its settings sidebar alongsideA comment thread open beside the page being edited
Edit in place - every block, with its own settings · Discuss in place - threads next to the work

✨ AI that does the heavy lifting

  • Lens is your pre-publish reviewer. It scores every page against quality rubrics - clarity, credibility, accessibility, publish-readiness - flags blockers, and turns each one into a concrete fix.
  • Renoir is an agent, not a chat box. Give it a goal and it plans the work, then carries it out on the project you have open - reaching for any of 30 tools to restructure an outline, create and refine elements, find and import media, or generate a whole section. It reads your schema before it acts, so what it builds fits your model, and it stops to ask when a decision is yours to make.
  • Media discovery surfaces the right images for exactly the section you're working on and pulls them into your library, ready to use.

The Lens review panel scoring a module against the Publish Readiness rubricRenoir docked beside a page of content, scoped to the page currently open in the editor
Lens - scored against a rubric, turned into fixes · Renoir - an agent working on the project you have open

♻️ Build once, reuse everywhere

  • Link it, don't copy it. Reuse a question, a page or an entire module from another project. Linked copies stay in sync with their source - and the moment you edit one, it's yours.
  • Collections. Model short-form material as flat entities that relate to each other - articles to authors, terms to topics - instead of forcing it into a tree.
  • Asset library. Upload, import and organize every file in one place, trace exactly where each one is used before you change it, and pull in what's missing straight from the web.

The asset library: images, video, YouTube and web links with type filters and a usage panelA collection: articles, authors, tags and categories with an item sidebar
Asset library - every file in one home · Collections - flat entities, related as you write

👥 Run it across an organisation

  • Groups, not just people. Put users into groups, give a group access to a set of projects, and set someone's role per group as well as per project.
  • Single sign-on. OIDC alongside local accounts and email invites.
  • A workflow you define. Move each part of a project through your own states, with priority, assignee and due date, on a board or in a list.
  • Know what's live. Every project flags when it has unpublished changes, and any page can be compared against its published version before you republish.
  • Move projects between environments. Export a whole project - structure, content and media - and import it elsewhere. Clone one to start the next.

How content is modelled

Four ideas, and a schema that decides how they fit together.

ConceptWhat it is
RepositoryOne unit of content - a course, a knowledge base, a collection of articles.
ActivityA step in your outline. You name the levels and decide which can sit inside which, so the tree goes as deep as your material needs.
Content ContainerThe type given to a level that holds content rather than more levels. It decides how that content is laid out and what belongs there - a reading page, a template of named sections, an exam, a pool of questions.
Content ElementThe thing an author actually places: a paragraph, an image, a video, a flashcard, a question.

In practice, that looks like this:

Pizza Fundamentals repository
└─ Introduction to Pizza Making activity (a module)
├─ History of Pizza activity (a page)
│ ├─ Section content container
│ │ ├─ Rich text content element
│ │ ├─ Image content element
│ │ └─ Multiple choice content element
│ └─ Assessment pool content container
└─ Baking Techniques activity (a module)

Anything in that tree can carry its own information - a duration on a module, a difficulty on a page, a source note on a single image - and your schema decides which. Reuse works at any level too: link one question, one page, or an entire module into another project.

Change the schema and the shape changes with it. These all ship as examples, and none of them is special-cased in the code:

flowchart LR
subgraph course["Course"]
direction TB
c1["Module"] --> c2["Module"] --> c3["Page"] --> c4["Section"]
end
subgraph kb["Knowledge Base"]
direction TB
k1["Category"] --> k2["Entry"] --> k3["Section"]
end
subgraph vc["Video Course"]
direction TB
v1["Chapter"] --> v2["Lesson"] --> v3["Video unit"]
end
subgraph feed["Feed"]
direction TB
f1["Article"]
f2["Podcast"]
f3["Event"]
end
course ~~~ kb ~~~ vc ~~~ feed
Loading

What ships in the box

Nothing below is hardcoded into the core. Every item here is an extension - the same kind of package you'd write yourself, installed and versioned like any other. Each element comes in two halves: the authoring component your team writes with, and a Vue 3 display component that renders the published result for learners.

27 content elements - the blocks an author actually places:

GroupElements
TextRich text (TipTap, Quill, Jodit), raw HTML
MediaImage, video, audio, PDF, file, embed, Mux and Brightcove video
InteractiveAccordion, carousel, modal, table, flashcards, sequence, section break
QuestionsSingle choice, multiple choice, true/false, matching, fill in the blank, numerical response, text response, drag & drop - each available graded or ungraded

The content element picker, grouped into content elements, assessments and nongraded questions
The picker an author sees - plus Copy existing, Link Content and Generate with AI on the same dialog

5 content containers decide how those blocks are laid out: a plain page; a template of named sections, each carrying its own fields and its own content; an exam; a pool of questions to draw from; and a collection item.

12 meta inputs attach configurable fields to a repository, an activity or a single element - text field, textarea, select, combobox, radio group, checkbox, switch, date/time, color, file, HTML and rating.

Extensible at every level

Four extension points, each plugging in at a different level of the model. Everything user-facing is a package, so a project only carries the extensions it actually uses - install one, drop one, or list what is currently in, all without touching core.

ExtensionPlugs in atWhat it addsIn the boxManage
🧱 Content Elementinside a containera new kind of block an author can place27pnpm ce
📐 Content Containeron any level that holds contenta new way to lay that content out5pnpm cc
🎛️ Meta Inputon a repository, an activity or a single elementa new configurable field12pnpm mi
🔌 Pluginacross the whole appa feature with its own UI, data hooks and statei18npnpm pl

The admin Installed Elements page listing 19 content elements and 8 question types, each versioned
Every extension is a versioned package, listed and manageable from admin

Each command opens a small CLI for that extension type: list what a project has installed, add one, remove one, or rebuild the registry.

Writing your own? Start with the extension guide. For content elements there is also the Content Element Kit - a separate project built alongside Tailor. It emulates the Tailor runtime and APIs, so you build both halves of an element in one place, with live previews: the authoring side your team writes with, and the display side that renders it for learners.

Quickstart

You'll need Node 26+, pnpm 11+ and PostgreSQL 15+. Docker is optional but gets you Postgres, Redis and S3 in one command.

git clone https://github.com/tailor-cms/author.git &&cd author
docker compose -f docker-compose.dev.yaml up -d # Postgres, Redis, MinIO
pnpm setup:dev # install, configure, seed
pnpm dev # http://localhost:8080

Sign in with admin@gostudion.com / gostudion.

Without Docker

Point setup:dev at your own PostgreSQL instance when it prompts you, then run pnpm dev. Redis and S3 are optional in development.

Running in production mode
cp .env.example .env # fill in your configuration
pnpm build
pnpm db:migrate
pnpm start

Migrations apply automatically at boot unless you set DATABASE_DISABLE_MIGRATIONS_ON_STARTUP. Deployment to AWS is covered by the Pulumi program in infrastructure/ - see the deployment guide.

Under the hood

  • Frontend - Nuxt 4, Vue 3, Vuetify 4, Material Design 3, Pinia.
  • Backend - one handler per endpoint, validated end to end. The same schemas generate the OpenAPI spec and a fully typed API client.
  • Data - PostgreSQL, optional Redis. Storage on S3 or the filesystem.
  • Auth - local accounts, invites, and OIDC single sign-on.
  • Quality - 448 Playwright tests across 62 spec files: functional, visual (Percy) and accessibility suites, on a sharded CI pipeline.
apps/frontend the authoring UI
apps/backend the API, publishing and AI services
apps/marketing the x.tailor-cms.com release brief
config/ schemas - your content model, as configuration
extensions/ content element / container / meta input / plugin registries
packages/ shared libraries and the generated API client
tests/ Playwright: functional, visual, accessibility
docs/ source for docs.tailor-cms.com
infrastructure/ Pulumi program for AWS deployment
Common scripts
CommandWhat it does
pnpm devRun backend, frontend and the API client watcher
pnpm dcThe above, plus Docker Compose services
pnpm buildBuild every workspace package
pnpm lint / pnpm typecheckLint and type-check the monorepo
pnpm seedLoad demo content
pnpm db:migrate / pnpm db:resetMigrate or reset the database
pnpm e2e:functionalPlaywright functional suite
pnpm e2e:visual / pnpm e2e:a11yPercy visual and accessibility suites
pnpm docs:devPreview the documentation site locally

More of the app

The catalog: repository cards labelled by schema typeProject-wide element search with previews and type filters
Catalog - every project, labelled by type · Search - every element, previewed in place

The workflow board: activities across todo, in progress, review and doneRepository history: a chronological audit trail of every change and who made it
Workflow - status, priority and assignee per activity · History - who changed what, and when

Documentation

WhereWhat you'll find
docs.tailor-cms.comConcepts, configuration, extensions, publishing, deployment
x.tailor-cms.comWhat's new in Tailor X
Content Element KitSeparate toolkit for building elements - emulates the Tailor runtime, covers authoring and display
Publishing guideThe manifest format, and how to consume it in your app

Contributing

Issues and pull requests are welcome. Open a bug report or a proposal to get started, and check the installation guide for a working development environment.

License

MIT © Studion

Acknowledgements

This project is tested with BrowserStack, who support open source with free cross-browser testing.

Built on a decade of custom learning experiences. Made to measure since 2016.

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages