# Deco: a Git-based visual CMS for TypeScript apps running on Deno

> Deco is a content management system that stores content in git and generates its editing interface from your TypeScript types, so a component's props become the fields an editor sees. It ships with server-side JSX templates, HTMX interactivity, Tailwind theming, a publishing workflow with staging and immutable releases, and one-click deployment to Deno-compatible hosts.

**deco-cx/deco** — Git-based Visual CMS for Deno, </> htmx and Tailwind apps. Deploy on any Deno-compatible host.

- Repository: https://github.com/deco-cx/deco
- Website: https://deco.cx
- Stars: 849 · Forks: 54
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/deco-cx-deco

## What the product is and what it refuses to be

Deco describes itself as a Git-based Visual CMS for Deno, htmx and Tailwind apps that deploy on any Deno-compatible host, and the README header calls it a Git-based Visual CMS for Typescript.

The repository topics are a good index of the intent. There is cms, deno, fresh, htmx, tailwind, tailwindcss, preact and typescript, alongside webflow and wordpress. That last pair is the positioning: Deco is presented as an alternative to those two, and the comparison it is making is about who owns the content and where it lives.

The first bullet of the feature list is a modern stack focused on performance and JavaScript-independence, and the sub-points are server-side JSX templates, client-side HTMX interactivity, local development with an HTTPS tunnel where you edit on the web and commit on your local git, and native Tailwind theme support with several component libraries supported: DaisyUI, Preline, FloatUI and Shadcn UI.

That JavaScript-independence is the interesting claim. The server renders JSX and the client gets HTMX, which is HTML over the wire rather than a JSON API and a client framework. The consequence is that the parts of the page that need interactivity still work without shipping a JavaScript bundle to every visitor, and the parts that need real client-side logic are added deliberately rather than by default.

The second bullet is aimed at business users and content editors. There is a TypeScript Props to Content Editor UI generator, an asset manager with multimedia support, a publishing workflow with a staging area, immutable releases and immediate rollbacks, and roles and permissions for content-only editors, with one invited content-editor member free per site.

The third bullet is deployment, which is covered in its own section below.

## The central idea: props become the editing interface

Deco's core feature is generating a content editor interface from your TypeScript interface, and the README shows both halves of it.

You declare a component with a Props interface:

```typescript
import ProductCard, { Layout } from "$store/components/product/ProductCard.tsx";
import type { Product } from "apps/commerce/types.ts";

export interface Props {
  products: Product[] | null;
  title?: string;
  description?: string;
  layout?: {
    headerAlignment?: "center" | "left";
    headerfontSize?: "Normal" | "Large";
  };
  cardLayout?: Layout;
}
```

And the admin interface is generated from that. The README states the rule plainly: declaring a ProductShelf JSX component with those Props will automatically generate the admin UI.

This is the design decision the whole product rests on, and it is worth thinking about carefully because it is unusual. Most visual CMSes derive their editor from a content schema you write in the CMS's own configuration format. Deco derives it from the type of the thing you are actually rendering. There is one description of your product's fields, it lives in TypeScript where your IDE can check it, and the editor is generated from it.

The optionality in the type carries through. A required string becomes a field an editor must fill, an optional one is offered but not demanded, and a union of literals becomes a choice. The nested layout object with its headerAlignment and headerfontSize becomes a group of settings.

The limitation follows from the same place. The editor can only offer what the type can express, so a component whose props are an untyped blob gets a blob field. That is a fair trade, and it is the same trade any type-driven system makes.

## Publishing, interoperability and the app ecosystem

Three capabilities sit on top of the prop-driven editor.

The publishing workflow has a staging area, immutable releases and immediate rollbacks, and the word immutable is doing work there. A release that cannot be edited after the fact is a release you can reason about, and a rollback is a pointer change rather than a re-deploy. For a team with non-technical editors, that is the difference between a safe workflow and a frightening one.

The second is the app ecosystem. The README describes composing pre-built features from a community-driven ecosystem of Apps with one-click installation, and the repository topics list platform, plugins and blocks. The typescript interfaces are what make the apps interoperable: the README states that Deco's blocks are interoperable, and that one's output can be visually configured as another's input in the visual editor, based on matching TypeScript types.

The example given is a product shelf UI component depending on a Product[] type, which is a good illustration. If one app produces products and another consumes them, and both agree on the type, the editor can wire them together without either app knowing about the other. That is a plugin architecture where the contract is the type rather than a manifest, which is either elegant or fragile depending on how carefully the types are chosen.

The third is built-in realtime feature flags, which the README lists as a way to roll out code or content to specific audiences. Since the content lives in git, a flag can select which version of a content entry a given audience sees, which is the same mechanism as a canary release but applied to copy rather than to code.

The framing in the advantages section is that you can craft modern web apps with a visual configuration editor for managing APIs, UIs and content, all in the same place. The emphasis on APIs as well as content is the part that distinguishes Deco from a page builder.

## Getting started, and running the engine locally

The getting started path is deliberately short, and the README claims it takes less than one minute.

You visit deco.new and choose a template, then choose a name and create a site. That gives you a free deco-sites GitHub repository and your own *.deco.site domain. You then follow the instructions to clone the repository and run the development server locally, or deploy to Deno Deploy with one click for free. The site is then ready to edit with the visual CMS, and all changes are saved to git.

To get to production you install any of the hosting apps available in deco.store by clicking Create new production environment.

The hosting options are listed with a clear status. Deno Deploy is the preferred partner, described as a global platform with a generous free tier. Azion Edge, Fly.io, Nirvana Cloud and Digital Ocean are all marked as coming soon. And there is deco.cx PRO hosting at 99 USD per month for always-on multi-zone deployment on what the README calls enterprise-scale managed infrastructure.

So the deployment story today is Deno Deploy plus a paid managed option, with several other platforms announced. That is a real constraint if you have an existing hosting arrangement, and it is worth checking the current list rather than assuming the coming-soon entries have arrived.

For working on the engine itself, the README gives four steps: clone the repository, navigate to a target project that runs deco, run the dev script pointing at your local clone, and add any missing packages.

```bash
git clone https://github.com/deco-cx/deco.git
```

```bash
cd path/to/your-deco-site
```

```bash
deno run -A jsr:@deco/deco/scripts/dev ../deco
```

The relative path at the end points the dev script at your local checkout of the engine instead of the published version, and the README asks you to replace it with wherever you cloned the repository.

## Limits: Deno coupling, a paid tier and a young type system

Several limits follow from the choices the project has made.

The first is Deno. The runtime, the package management with deno add, the jsr package reference and the deployment target are all Deno-specific. A project on Node.js or Bun cannot use this CMS as it stands, and while htmx and Tailwind are portable, the engine is not.

The second is the deployment list. Only Deno Deploy is described as available today, with four other platforms marked as coming soon, so the hosting options for anything other than Deno Deploy are the paid deco.cx PRO plan at 99 USD per month for always-on multi-zone deployment. The free tier is generous on Deno Deploy, but a team with an existing contract elsewhere is either waiting or paying.

The third is that the editor is only as good as your types. The generated interface comes from TypeScript props, which is elegant until a component takes a prop that is technically typed but not really an editor's business, such as a React node or an opaque string. You then get a text field where a person wanted a picker, and the type system has not saved you.

The fourth is the licence position. The repository records Apache-2.0 and carries a LICENSE file, and the package is published to JSR as @deco/deco and to Deno Land as deco, so the licensing of the published packages should be checked rather than inferred from the repository. The project also ships a MAINTAINERS.txt, which is a reasonable signal for a project with a commercial tier attached.

The fifth is the release numbering, which is unusual. The tags are 1.214.1, 1.214.0 and 1.213.0, with the newest from 2026-10-16, so the numbers are not semantic versions and the 1.213 to 1.214 jump suggests a versioning scheme tied to something other than breaking changes. Do not assume semver compatibility guarantees from that numbering.

## Deco against a headless CMS plus a separate admin app and against building on git directly

Two comparisons make the choice clearer.

The first is against the usual headless CMS arrangement, where content lives in a hosted database with an admin interface and your site fetches from an API at runtime. The difference in approach is where the content and the types live. In the hosted arrangement the schema is defined in the CMS, your code consumes a generated client, and a field added in the CMS does not change your TypeScript types. In Deco the schema is your TypeScript, the editor is generated from it, and the content is in the same repository as the code.

That gives you type safety across the boundary and a single review surface for code and copy, at the cost of deploying the content with the code, which means a content change is a release unless the deployment model handles it otherwise. The staging area and immutable releases in the README are the answer to that, and they are a meaningful design decision rather than an afterthought.

The second comparison is against just using git and a markdown directory with no CMS at all. The difference in approach is the editing experience. If the people writing your content are developers, a folder of markdown and a pull request is simpler than any CMS, and the git-based approach Deco takes is only a step beyond that. If the people writing your content are not developers, a visual editor is the whole value proposition, and Deco generates one from the types you already have rather than asking you to write a schema a second time.

That is the dividing line. Deco is for the case where the code is typed and the content is not, and you want one description of the data instead of two.

## Conclusion

Adopt Deco if you build on Deno, want editors working in a visual interface without a separate admin application, and are willing to have content live in git alongside your code. Do not adopt it if your stack is not Deno, or if you need a headless content API with no visual editing at all, since the whole product is built around the editor. Verify first that the hosting target you need is one of the supported platforms, that your component props describe fields an editor can sensibly fill in, and that you understand the free tier and per-site editor limits before inviting your team.

## FAQ

### What is Deco and how does it generate its editor interface?

Deco is a Git-based visual CMS for TypeScript apps running on Deno, with HTMX interactivity and Tailwind theming. Its core feature is generating the content editor interface from your TypeScript props, so declaring a component with a Props interface automatically produces the admin UI for those fields. Content itself is stored in git.

### How do I run the Deco engine locally to contribute to it?

Clone the repository, change into a site project that runs deco, and run the dev script pointing at your local clone with deno run -A jsr:@deco/deco/scripts/dev ../deco, replacing the relative path with wherever you cloned the engine. If you hit missing package errors, add them to your project with deno add.

### Where can I deploy a Deco site?

Deno Deploy is the preferred partner and is described as a global platform with a generous free tier, and you can deploy there with one click. Azion Edge, Fly.io, Nirvana Cloud and Digital Ocean are listed as coming soon, and there is a paid deco.cx PRO option at 99 USD per month for always-on multi-zone deployment. Production environments are created through the hosting apps in deco.store.

## Sources

- [deco-cx/deco on GitHub](https://github.com/deco-cx/deco)
- [License: Apache-2.0](https://github.com/deco-cx/deco/blob/main/LICENSE)
- [Project website](https://deco.cx)
- [README](https://github.com/deco-cx/deco/blob/main/README.md)
- [Releases](https://github.com/deco-cx/deco/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/deco-cx-deco
