Invert
БесплатноНе проверенInvert is a database-less, headless, adapter-driven content presentation layer built on Astro.
Описание
Invert is a database-less, headless, adapter-driven content presentation layer built on Astro.
README
A database-less, adapter-driven content presentation layer built on Astro. Invert renders content from any source — JSON files, markdown, a WordPress site, a Drupal site, an AI tool over MCP — without an admin panel, without a database, and without opinions about where your content lives.
There is no admin. That's the point. If there's no admin, then the admin can be anything.
Philosophy
The presentation layer and the content management layer are separate concerns. Conflating them is the mistake the industry keeps making.
Invert doesn't replace your CMS. It sits in front of it — or in front of no CMS at all. Content comes in from adapters, gets normalized into a common JSON shape, and gets rendered. Where the content comes from is not Invert's problem. That's yours.
You can use WordPress and keep your admin panel. You can commit markdown to a git repo. You can talk to an AI tool over MCP and let it create content as JSON files. You can do all three at the same time. The choice is yours.
An inversion is when you flip yourself upside down — a fundamental move in aerial arts. You hold your whole body weight in your hands while you rotate 180 degrees. It's a test of grip and strength. In this context, Invert means: look at the same stuff from a different angle. We don't have to throw our toys away. We can have new things and still honor the old things.
Requirements
- Node.js >= 22.12.0 (use nvm:
nvm use)
Quick Start
- Click "Use this template" on GitHub to create your own repository
- Clone your new repo locally
- Install dependencies:
npm install
- Start the dev server:
npm run dev
Your site is running at http://localhost:4321.
Adding Content
JSON Files
Drop .json files into content/[type]/[slug].json. The directory name is the content type; the filename is the slug.
content/
posts/
my-post.json → /posts/my-post
pages/
about.json → /pages/about
A content file:
{
"id": "my-post",
"slug": "my-post",
"title": "My Post",
"body": "<p>Content here.</p>",
"contentType": "posts",
"date": "2026-04-06",
"author": "Chris",
"taxonomies": {
"tags": ["example"]
}
}
Markdown Files
Drop .md files into markdown/ with YAML frontmatter:
---
title: My Post
slug: my-post
contentType: posts
date: 2026-04-06
author: Chris
tags: [example]
---
Content here.
Remote Markdown (GitHub)
Point the markdown adapter at a GitHub repository and Invert pulls content from it at build time:
// src/lib/config.ts
new MarkdownAdapter({
source: 'github',
repo: 'your-org/your-repo',
contentDir: 'content',
branch: 'main',
token: process.env.GITHUB_TOKEN, // optional, for private repos
})
MCP (AI Tools)
Start the MCP server and connect it to Claude Desktop or any MCP-compatible tool:
npm run mcp
The AI tool can then create, read, update, and search content. Write operations produce JSON files in content/ — the JSON adapter's write path. Markdown files (markdown/, docs/) are treated as externally managed source files and are not writable via MCP. See MCP write path below.
Configuration
All configuration lives in src/lib/config.ts:
import { join } from 'node:path';
import { JsonAdapter } from '../adapters/json.ts';
import { MarkdownAdapter } from '../adapters/markdown.ts';
import { DocsAdapter } from '../adapters/docs.ts';
const root = process.cwd();
export const invertConfig = {
siteName: 'My Site',
siteUrl: 'https://example.com',
adapters: [
new JsonAdapter({ contentDir: join(root, 'content') }),
new MarkdownAdapter({ source: 'local', contentDir: join(root, 'markdown') }),
new DocsAdapter({ contentDir: join(root, 'docs') }),
],
};
Paths must be absolute — use join(root, '...') where root = process.cwd(). Relative paths fail during Astro's static build phase.
Multiple adapters run simultaneously. Content merges from all sources. If two adapters return content with the same contentType and slug, the first adapter in the array wins.
Content Shape
All content from all adapters normalizes to InvertContent:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Unique identifier |
slug |
string | yes | URL slug — used in routing |
title |
string | yes | Display title |
body |
string | yes | HTML string |
contentType |
string | yes | e.g., "posts", "pages", "docs" |
date |
string | no | ISO 8601 date |
modified |
string | no | ISO 8601 date |
author |
string | no | Author name |
excerpt |
string | no | Short summary |
featuredImage |
string | no | URL or path to image |
taxonomies |
object | no | e.g., { tags: ["a", "b"] } |
meta |
object | no | Arbitrary pass-through data |
Content types are strings. There is no structural difference between a "post" and a "page" and a "recipe." The system doesn't enforce schemas — that's the adapter's job.
Routing
/— Landing page/[type]/— All content of a given type (e.g.,/posts/,/docs/)/[type]/[slug]— Individual content item (e.g.,/docs/getting-started)
Routes are generated at build time from whatever adapters return. No configuration needed.
MCP Server
Invert includes a Model Context Protocol server for AI tool integration (mcp/server.ts).
Read Tools
| Tool | Description |
|---|---|
invert_list |
List content, optionally filtered by type and paginated |
invert_get |
Get a single content item by type and slug |
invert_search |
Full-text search across title, body, excerpt |
invert_types |
List all available content types |
Write Tools
| Tool | Description |
|---|---|
invert_create |
Create a new content item |
invert_update |
Update an existing content item |
invert_delete |
Delete a content item |
MCP Write Path
Write tools create and modify JSON files in content/ only. This is intentional.
Invert treats content/ (JSON files) as the AI-writable layer. Markdown files in markdown/ and docs/ are externally managed — written by humans, pulled from git, or fetched from a remote source. The separation is the point: if you want an AI tool to author structured content items, it goes through MCP into content/. If you want to manage documentation or long-form writing, you edit the markdown files directly or in your source repo.
Changes written via MCP appear on the site after a rebuild, or immediately in dev mode with hot reload.
Connecting to Claude Desktop
{
"mcpServers": {
"invert": {
"command": "npm",
"args": ["run", "mcp"],
"cwd": "/path/to/your/site"
}
}
}
Adapters
Built-in
- JsonAdapter — Reads
.jsonfiles from a local directory. Directory structure maps to content types. - MarkdownAdapter — Reads
.mdfiles with YAML frontmatter. Supports local directories and remote GitHub repos. - DocsAdapter — Reads markdown from a
docs/directory and forcescontentType: "docs". Ships as a worked example of building a custom adapter — seesrc/adapters/docs.ts.
Writing Your Own
DocsAdapter is the reference implementation. The minimum viable adapter:
import type { InvertAdapter, InvertContent } from './interface.ts';
export class MyAdapter implements InvertAdapter {
name = 'my-adapter';
async getAll(): Promise<InvertContent[]> {
return []; // fetch and return InvertContent[]
}
async getBySlug(slug: string): Promise<InvertContent | null> {
const all = await this.getAll();
return all.find((c) => c.slug === slug) ?? null;
}
async getByType(contentType: string): Promise<InvertContent[]> {
const all = await this.getAll();
return all.filter((c) => c.contentType === contentType);
}
}
Register it in src/lib/config.ts alongside existing adapters.
Planned
- WordPress REST API — Fetch posts, pages, and CPTs from a WordPress site
- Drupal JSON:API — Fetch content entities from Drupal
- Content Publisher — Pantheon Content Publisher for Google Docs workflows
- RSS/Atom — Feed entries as content items
- Generic HTTP — Configurable adapter for any JSON API
Deployment
Invert builds to a static dist/ directory. No server-side runtime required.
GitHub Pages
The included .github/workflows/deploy-docs.yml builds and deploys on push to main. Enable Pages in your repo settings (Settings → Pages → Source: GitHub Actions).
For project pages (e.g. username.github.io/repo-name), the workflow sets SITE_BASE automatically from the repo name. For a custom domain, remove the SITE_BASE env var from the workflow.
Cloudflare Pages
Connect your GitHub repo in the Cloudflare Pages dashboard:
- Build command:
npm run build - Output directory:
dist - Environment variable:
NODE_VERSION = 22
Other Platforms
Any static host works: Netlify, Vercel, S3, etc. Run npm run build and deploy dist/.
Commands
| Command | Description |
|---|---|
npm run dev |
Start Astro dev server at localhost:4321 |
npm run build |
Build for production to dist/ |
npm run preview |
Preview the production build locally |
npm run mcp |
Start the MCP server (stdio transport) |
Project Structure
invert/
├── astro.config.mjs # Astro configuration
├── CLAUDE.md # Claude Code conventions
├── docs/ # Project documentation (rendered via DocsAdapter)
│ ├── ARCHITECTURE.md
│ ├── getting-started.md
│ ├── adapters.md
│ ├── content-shape.md
│ └── mcp.md
├── src/
│ ├── adapters/
│ │ ├── interface.ts # InvertAdapter + InvertContent types
│ │ ├── json.ts # JSON file adapter
│ │ ├── markdown.ts # Markdown adapter (local + GitHub)
│ │ └── docs.ts # DocsAdapter — custom adapter example
│ ├── lib/
│ │ ├── config.ts # Site config + adapter registration
│ │ ├── content.ts # Content query helpers
│ │ └── utils.ts # URL helper for base-path-aware links
│ ├── layouts/
│ │ └── Base.astro # Base HTML layout
│ ├── pages/
│ │ ├── index.astro # Landing page
│ │ ├── [type]/
│ │ │ ├── index.astro # Content type listing
│ │ │ └── [slug].astro # Individual content page
│ │ └── 404.astro
│ └── components/
│ ├── ContentCard.astro # Listing card
│ └── ContentBody.astro # Content body renderer
├── mcp/
│ ├── server.ts # MCP server entry point
│ └── tools.ts # MCP tool implementations
├── webhooks/
│ └── rebuild.ts # Git push webhook listener scaffold
├── content/ # JSON content (MCP-writable)
├── markdown/ # Markdown content (human-managed)
└── public/ # Static assets
License
MIT
Author
Установка Invert
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/jazzsequence/InvertFAQ
Invert MCP бесплатный?
Да, Invert MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Invert?
Нет, Invert работает без API-ключей и переменных окружения.
Invert — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Invert в Claude Desktop, Claude Code или Cursor?
Открой Invert на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
wenb1n-dev/SmartDB_MCP
A universal database MCP server supporting simultaneous connections to multiple databases. It provides tools for database operations, health analysis, SQL optim
автор: wenb1n-devPostgres Server
This server enables interaction with PostgreSQL databases through the Model Context Protocol, optimized for the AWS Bedrock AgentCore Runtime. It provides tools
автор: madhurprashPostgres
Query your database in natural language
автор: AnthropicPostgreSQL
Read-only database access with schema inspection.
автор: modelcontextprotocolCompare Invert with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории data
