@plutocms/pluto
| Install | |
|---|---|
npm install @plutocms/pluto |
|
| Latest Version: | 0.17.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 21, 2026 |
| Links: | GitHub · npm |
Pluto CMS
A layer-based CMS powered by Nuxt.
[!WARNING] Pluto CMS is currently in alpha and at a very early stage. Expect breaking changes, incomplete features, and rough edges.
Also note: npm is still not supported due to layer dependencies not being installed correctly. It is strongly recommended to use modern package managers like pnpm or bun.
Pluto CMS is designed to be modular, extensible, and developer-friendly. Instead of a monolithic system, it lets you compose your CMS using layers. You only install what you need.
Features
- Layer-based architecture using Nuxt Layers
- Modern SSR + SPA hydration with Nuxt
- TypeScript-first developer experience
- Opt-in features instead of global plugin mutations
- Deployment-friendly (Edge and Serverless ready)
- Works as a full CMS or as a headless backend
- Standalone mode: a Markdown blog stored in GitHub, with no database
Requirements
- Node.js (22+) or Bun
- pnpm or Bun
npm is not supported at this stage and may cause unexpected issues.
Getting started
Create a new Pluto project using the CLI:
npm create pluto@latest
# or
pnpm create pluto@latest
# or
bun create pluto@latest
This will launch an interactive setup wizard where you can:
- Choose a database provider
- Configure database credentials (all stored locally on your project's .env)
- Select a starter template (blog, store, etc.)
Then:
cd your-project
bun install # or pnpm install
bun run dev # or pnpm dev
Architecture overview
Pluto CMS is built around layers, each responsible for a specific concern.
Core layer (@plutocms/pluto)
The core layer provides the foundation for your CMS:
<PlutoRoot>: Wraps your entire app (used inapp.vue). Includes the admin navbar,NuxtLayout,NuxtLoadingIndicator, and base styles.<ColorModeButton>: Light/dark mode toggle with zero configuration.- Built-in auth and admin layouts, the
/adminroute, the/admin/loginpage, the route guard and the admin navbar. A backend layer plugs in with an auth driver (authDriverindefinePlutoExtension). See.claude/skills/admin-shell/SKILL.md. <PlutoNavbarAdmin>and<PlutoNavbarAdminActions>Provide structure for injecting actions from other layers
A layer plugs into the admin UI with one function, definePlutoExtension, called from a
plugin. It registers any of: an auth driver, navbar actions, sidebar nav entries, admin page
metadata, dashboard widgets, and a settings panel or driver:
// app/plugins/pluto-registrations.ts
export default defineNuxtPlugin(() => {
definePlutoExtension({
id: 'supabase-blog',
nav: [{ id: 'posts', label: 'Posts', icon: 'lucide:file-text', to: '/admin/posts' }],
})
})
See .claude/skills/extension-registry/SKILL.md for the full type of each registrable thing
and the ordering/dedupe rules. The old useNavbarAdmin().registerNavbar(component) and
useNavbarAdminActions().addAction(component) composables still work, through a compatibility
bridge, but definePlutoExtension is the current recommended way to plug in.
Backend layers
Backend layers handle data, authentication, and APIs.
Examples:
@plutocms/supabaseProvides Supabase integration (database, auth, users, etc.)- Future possibilities:
- Custom database providers (MySQL, MongoDB, etc.)
- Other backend-as-a-service providers (Convex, Neon, Firebase, etc.)
Feature layers
Feature layers add domain-specific functionality on top of backend layers.
Examples:
@plutocms/supabase-shopAdds e-commerce features like:- Products
- Media
- Cart
- Other possible layers:
- Blog
- Portfolio
- Analytics
- Payments
Feature layers depend on backend layers. For example,
@plutocms/supabase-shoprequires@plutocms/supabase.
Using Pluto in existing Nuxt projects
Pluto is not limited to new projects.
You can extend an existing Nuxt app using layers:
// nuxt.config.ts
export default defineNuxtConfig({
extends: [
'@plutocms/pluto'
// Then add any backend or feature layers you need.
]
})
Styles: one Tailwind build
Your app owns the only Tailwind build. Pluto layers do not register their own. Start your CSS entry with these three imports, then add your own theme after them:
/* app/assets/css/main.css */
@import 'tailwindcss';
@import '@nuxt/ui';
@import '#build/pluto.css';
@theme {
/* your site's tokens */
}
// nuxt.config.ts
export default defineNuxtConfig({
css: ['~/assets/css/main.css'],
})
#build/pluto.css brings in the CSS of every Pluto layer, including the admin theme. Nuxt UI
already scans the source of every layer. If your app has no Tailwind entry, Pluto uses a
fallback entry. If the setup is wrong, the build prints a pluto-css warning with the fix.
The admin keeps its own palette and font. Your site's app.config colors and @theme
tokens do not change the admin.
Standalone mode: a Markdown blog in GitHub
@plutocms/pluto can run on its own, with no database and no other layer. Posts are Markdown
files in a GitHub repository. Editors write them in the Pluto admin, and each save is a commit.
The public site reads the posts from GitHub at runtime, with a cache, so a save publishes in
seconds without a new build.
The quickest start is the template:
bunx create-pluto@latest my-blog -t core-blog
Or turn it on in an existing app. It is off by default, and it refuses to run next to the supabase layer:
// nuxt.config.ts
export default defineNuxtConfig({
extends: ['@plutocms/pluto'],
plutoCms: {
enabled: true,
github: { repo: 'owner/name', branch: 'main', appSlug: 'my-blog-cms' },
dir: 'content', // posts live in content/posts/<slug>.md
},
})
- Sign-in: with a GitHub App. Users with push access to the repository are editors. Commits carry the name of the editor.
- Drafts:
status: draftin the frontmatter. The public routes never show them. In a public repository, drafts are still readable on GitHub, and the admin warns about this. - Public pages:
usePlutoCmsList('post')andusePlutoCmsItem('post', slug)read the published posts.<PlutoMarkdown :html="post.html" />shows a post as sanitized HTML. - Development: set
storage: 'fs'to read and write the localcontent/folder. A dev server then never writes to the real repository.
The GitHub App setup, the environment variables and every option are in the template README
and in .claude/skills/github-cms/SKILL.md.
Dashboard & headless usage
Although Pluto is built on Nuxt, it is not limited to Nuxt-only consumption.
- The admin dashboard can run as a standalone app on providers like Vercel or Netlify
- Data can be consumed via:
- Composables (within Nuxt apps)
- REST APIs exposed by layers
This allows you to:
- Use Pluto as a headless CMS
- Power web apps (any stack)
- Power mobile apps
Why not just WordPress?
- Modern SSR and SPA hydration via Nuxt
- TypeScript-first experience
- Better control through Vue composables or REST APIs
- Deployment flexibility (Vercel, Cloudflare, Netlify, etc.)
If you're a Vue developer, you'll feel right at home.
Roadmap ideas
- More official backend layers
- Rich ecosystem of feature layers
- Better developer tooling and DX improvements
- Community layers are very welcome! ❤️
License
MIT (planned)
Related Packages
Version History
| Version | Released | License |
|---|---|---|
| 0.17.0 | MIT | |
| 0.16.4 | MIT | |
| 0.16.3 | MIT | |
| 0.16.2 | MIT | |
| 0.16.1 | MIT | |
| 0.16.0 | MIT | |
| 0.15.0 | MIT | |
| 0.14.3 | MIT | |
| 0.14.2 | MIT | |
| 0.14.1 | MIT | |
| 0.14.0 | MIT | |
| 0.13.0 | MIT | |
| 0.12.0 | MIT | |
| 0.11.0 | MIT | |
| 0.10.0 | MIT | |
| 0.9.1 | MIT | |
| 0.9.0 | MIT | |
| 0.8.1 | MIT | |
| 0.8.0 | MIT | |
| 0.7.0 | MIT | |
| 0.6.0 | MIT | |
| 0.5.0 | MIT | |
| 0.4.0 | MIT | |
| 0.3.2 | MIT | |
| 0.3.1 | MIT | |
| 0.3.0 | MIT | |
| 0.2.1 | MIT | |
| 0.2.0 | MIT | |
| 0.1.0 | MIT | |
| 0.0.9 | MIT |
Showing the latest 30 of 32. See every release on npm
Pre-releases (4)
| Version | Released | License |
|---|---|---|
| 0.0.1-alpha.4 | MIT | |
| 0.0.1-alpha.3 | MIT | |
| 0.0.1-alpha.2 | MIT | |
| 0.0.1-alpha.1 | MIT |