Nuxt Editable is a free content editor UI to embed in your Nuxt site. It gives you a great editing experience by allowing you to click to edit content in-place.
- Drop-in a component to edit your Nuxt site with a live preview!
- Works with any content by defining your own schemas.
- Bring your own data – integrates with any database or headless CMS.
Check out these examples to get up and running in no time:
TL;DR Add NuxtEditableEditor
to your app.vue
. Provide items through the items
prop. Listen for data changes through @change
. That's it! ✨
Here's a step-by-step setup:
# Using pnpm
pnpm add nuxt-editable typescript tailwindcss
# Using yarn
yarn add nuxt-editable typescript tailwindcss
# Using npm
npm install nuxt-editable typescript tailwindcss
Create a file called editable.config.ts in the root of your project. This will contain your editor configuration:
Now, add nuxt-editable
to the modules
section of nuxt.config.ts
, with a reference to your config file as second argument.
import editableConfig from './editable.config';
export default defineNuxtConfig({
modules: [['nuxt-editable', editableConfig]],
});
Nuxt Editable requires a scheme to know what you data looks like. It uses this to render the tables and form fields. Here's an example for Posts
collection:
// editable.config.ts
export default {
collections: {
posts: {
name: {
singular: 'Post',
plural: 'Posts',
},
icon: 'i-heroicons-newspaper',
schema: {
title: {
type: EditableCollectionSchemaFieldType.Text,
help: 'A title for the post',
required: true,
},
slug: {
type: EditableCollectionSchemaFieldType.Text,
help: 'A URL-friendly slug for the post page',
required: true,
},
excerpt: {
type: EditableCollectionSchemaFieldType.Text,
help: 'A short excerpt of the post',
},
content: {
type: EditableCollectionSchemaFieldType.RichText,
help: 'The content of the post',
},
},
},
},
};
You can add the Editor component anywhere in your Nuxt app, but to allow the editor to be rendered regardless of which route you're on, it's probably best to add the editor to your app.vue
.
// app.vue
<NuxtEditableEditor
:user="currentEditorUser"
:data="currentEditorData"
:pending="isPendingEditorData"
@change="onEditorChangeData"
@request-data="onEditorRequestData"
/>
Users can bring up the editor by passing ?editable=true
in the route.
With your Posts
collection defined, bringing up the editor will now list a Posts item. When a user clicks on a collection or a collection item, the editor requests data for it. You need to listen to the requestData
event. Example:
// app.vue
const currentEditorData = ref({
posts: []
})
const onEditorRequestData = async (event: EditableRequestDataEvent) => {
isPendingEditorData.value = true
currentEditorData.value.posts = await $fetch(`/api/posts`)
isPendingEditorData.value = false
}
When a user makes a change, e.g. when creating, updating or deleting an item, the editor emits a change
event. You need to listen for the change
event and update data accordingly. Example:
// app.vue
const onEditorChangeData = async (event: EditableChangeEvent) => {
const { type, payload } = event
isPendingEditorData.value = true
switch (type) {
// When creating an item
case EditableChangeEventType.Create:
$fetch(`/api/posts`, {
method: 'POST',
body: payload.data
})
break
// Other cases for updating and deleting here
}
isPendingEditorData.value = false
// Optional: Refresh the data on your current page so it reflects edits that have just been made!
refreshNuxtData()
}
You'll typically want to allow users to log in to the editor. You can provide the currently logged in user through the user
prop. On the built-version of your Nuxt app, the Editor will default to a login screen if the user
has not been provided. The editor emits a login
and logout
event for you to handle accordingly.
Allowing users to highlight and click to navigate to the editor item directly makes for a great UX. To enable this, you need to provide the editor a hint to which collection
and primary key your item refers to. To make this easy, the module exposes a v-editable
directive to your Nuxt app. Example:
<h1 v-editable="{ collection: 'posts', id: '23984832' }">Some great post title</h1>
You'll need to provide the primary key as configured in your collections configuration.
Nuxt Editable provides a flexible way to extend the editor UI to acommodate custom use-cases.
To add your own actions (such as buttons) to the list or form view, you can use a slot:
// app.vue
<NuxtEditableEditor
:user="currentEditorUser"
:data="currentEditorData"
:pending="isPendingEditorData"
@change="onEditorChangeData"
@request-data="onEditorRequestData"
>
<template #posts-list-actions>
<!-- Elements here will be shown alongside the buttons for the posts collection list -->
</template>
<template #posts-form-actions>
<!-- Elements here will be shown alongside the buttons for a posts form -->
</template>
</NuxtEditableEditor/>
Your scheme fields can contain different types, such as text
, number
, rich-text
and more. For a full list, refer to EditableCollectionSchemaFieldType
.
Your scheme can contain validators such as required
, minLength
, date
. For a list of supported validators, refer to: EditableCollectionSchemaFieldValidator
.
Nuxt Editable is in its early stages, so there's still a few things that are on my list to build in order to make this ready for production.
- Add test coverage
- Add pagination in the collection list UI
- Add provider login UI configuration options for Github, Google, social media and the likes
- Support file uploads with a UI configuration option to view a collection as a grid of files.
Beyond this, there's a lot more this project could become:
- State: Keeping edits and new items in the local state so users can freely navigate around and leave the editor, without losing changes.
- Publish: Instead of creating and update items directly, configure the editor to keep local changes changes in a batch, and allow the users to hit 'Publish', to commit all changes (e.g. as part of a database transaction).
- Extendable UI: The ability to swap the default form fields out for your own custom ones, to cover complex use-cases.
# Install dependencies
npm install
# Generate type stubs
npm run dev:prepare
# Develop with the playground
npm run dev
# Build the playground
npm run dev:build
# Run ESLint
npm run lint
# Run Vitest
npm run test
npm run test:watch
# Release new version
npm run release
I couldn't have built Nuxt Editable without standing on the shoulders of giants. A special thanks goes to the incredible work done by: