Project structure
A Pluto project is a Nuxt app. It extends one or more layers.
The blog template
The blog template (templates/blog in the templates repository) works with both backends: the Git CMS (no database) and Supabase. With the Git CMS, it has these files:
content/posts/holds the posts as Markdown files (Git CMS only).app/pages/holds the public pages. They read posts withusePosts,usePostanduseAdjacentPosts. See Public API.app/components/PostArticle.vuerenders one post, with the core componentPlutoHtmlfor the body. The post page and the preview of the post editor (PlutoPostPreview.vue) both use it.app/components/content/Callout.vueis a content component (a note, a tip or a warning). The post editor lists it under Insert a component, because it callsdefinePlutoBlock. Add your own components next to it.main.cssis the whole look, in Tailwind CSS: the colors as variables for light and dark, and the post body (.pluto-prose). Each color is also a Tailwind class, for exampletext-heading,text-mutedandborder-line. The template uses no UI library and no Pluto styles. To use them, see Styles.- The site starts in light mode (
colorMode.preferenceinnuxt.config.ts).ColorModeButtonof core in the navbar switches it. - The texts are in English, in the files. For a site in more than one language, see Internationalization.
nuxt.config.tsextends@plutocms/core, and the SEO add-on@plutocms/seowhen you said yes to Add SEO?. When needed, it sets theplutoGithuboptions.package.jsonlists@plutocms/core,nuxt,vue, andvue-router, and@plutocms/seowith SEO.
With Supabase, three things differ, and the CLI sets them:
nuxt.config.tsextends@plutocms/supabase-blogin place of core (and@plutocms/seowith SEO). The blog layer brings@plutocms/supabaseand core.package.jsonalso lists@plutocms/supabase-blog, and has thesupabase-typesscript.- There is no
content/folder: the posts are in the database.
The pages link to a post by its slug (/posts/<slug>), the same for both backends.
The template has no .env file. The CLI writes it when you create the project. With the Git CMS, Create the GitHub App in the admin gives the GitHub App values. See Deploy.
The shop template
The shop template (Supabase) has these files:
Its nuxt.config.ts extends @plutocms/supabase-shop and the 3D add-on @plutocms/3d, so a product can have a 3D model. The shop layer brings @plutocms/supabase and core.
The Dashboard only template
The Dashboard only template has no public site:
It has no CSS entry: it has no public pages, and the admin has its own CSS. See Styles.
A Supabase project (the shop, or the blog with Supabase) does not ship shared/types/supabase.ts. Git ignores it. In development, the server writes the generated database types to this file after it applies the migrations.
app.vue
app.vue is your site: the header, the layout, the footer. You write nothing for Pluto in it. Pluto wraps it:
- The admin (
/admin) and the preview of the visual editor never render yourapp.vue. They get the admin shell. - A public page renders your
app.vue, with the admin bar for signed-in editors. When yourapp.vuehas noUApp, Pluto adds one.
With no app.vue, Pluto uses its own: the page in the default layout.
To take control yourself, wrap your app in PlutoRoot. Pluto then leaves app.vue as it is:
<template>
<PlutoRoot>
<NuxtPage />
</PlutoRoot>
</template>
PlutoRoot includes the admin navbar, UApp, NuxtLayout, NuxtLoadingIndicator, and the base styles. On the admin routes and the preview route, render only <NuxtPage /> in it.
If the UApp of your site is in a layout or a component, Pluto cannot see it from app.vue. Tell it with plutoRoot: { siteApp: true } in nuxt.config.ts, so the page does not get a second one. plutoRoot: { wrap: false } turns the wrapping off.
nuxt.config.ts
The config extends the layer for the template. This example shows the core blog template:
export default defineNuxtConfig({
extends: ['@plutocms/core', '@plutocms/seo'],
css: ['~/assets/css/main.css']
})
The CMS is on by default. The plutoGithub options have defaults: the storage depends on the mode, and Pluto finds the repository from the environment. The template sets no plutoGithub option: the defaults are enough. See Git CMS reference.
The CSS entry
The admin has its own CSS, so this file is for your site only. The blog template uses Tailwind and no UI library:
@import 'tailwindcss';
A site on Nuxt UI, such as the shop template, also imports Nuxt UI and the Pluto CSS:
@import 'tailwindcss';
@import '@nuxt/ui';
@import '@plutocms/css';
@import '@plutocms/css/base';
@import '@plutocms/css/site';
@plutocms/css/base gives the look of the Pluto components, such as PlutoHtml. Add your own @theme after these lines. See Styles.
The admin routes
Core owns the /admin routes. They need no page files in your app.
| Route | Purpose |
|---|---|
/admin | Redirects to /admin/home |
/admin/home | The dashboard |
/admin/login | The sign-in page |
/admin/no-access | The page for a signed-in user with no capability |
/admin/not-configured | The page that shows in production when no backend registers an auth driver |
/admin/media | The media library, when the backend has a media driver |
/admin/settings | The settings pages |
/admin/users | Git CMS: the people with write access to the repository (read only) |
/admin/content/<type> | The generated list, new, and edit pages of a content type |