Customising previews
One of the best features of Imput is the ability of viewing how the text in your page is going to look as you write it, including React components! Imput handles all of the MDX and compilation logic so you don't need to do it yourself.
Let's start from a basic configuration:
const CMS = () => (
<NextCMS
{...{
settings: {
// more settings here !
collections: [
{
name: 'docs',
label: 'Docs',
folder: 'apps/docs/pages/docs',
create: true,
slug: '{{name}}',
extension: 'mdx',
fields: [
{ label: 'Name', name: 'name', widget: 'string' },
{ label: 'Content', name: 'body', widget: 'markdown' },
],
// the preview object is what we'll use to configure
// our CMS preview
preview: {}
},
],
},
}}
/>
)
HTML Preview
The easiest way to start is to add an empty preview.components
object:
{
preview: {
components: {},
},
}
This will tell Imput to convert your Markdown into HTML, even though it will be unstyled. To add styles you can use another preview
configuration: wrapper
. Wrapper renders an React component around your preview! You can use it to render a CSS-in-JS component that targets your preview or for a utility class like tailwind-prose
.
{
preview: {
components: {},
wrapper: ({ children }) => <div className="prose">{children}</div>
},
}
Previewing Frontmatter
All your frontmatter data (i.e. things that aren't the main body of your content like title, date or author) are passed to the header
and footer
configurations. You can use these methods to make your preview look more like your actual page, or just display useful information to the editor.
{
preview: {
components: {},
// this will use your title contents and add it to an <h1> tag on top of your content
header: ({ title }) => <h1 className="my-blog-heading">{title}</h1>,
// this will use your author's name and render it below your content
footer: ({ authorName }) => <p className="article-author">{authorName}</p>
},
}
React Components Preview
Imput is also able to render React components added with the "Block" feature in real-time. Adding a components
object will replace any components in your MDX with the component matching its name.
{
preview: {
// Any component defined here will be automatically rendered
components: {
// Imput will now render this component instead of the text "<Note>"
Note: ({ children }: any) => {
return (
<div>
<div>💡</div>
<div>{children}</div>
</div>
)
}
},
},
// This will add the option to add a <Note> component
// into the editor
blocks: [
{
name: 'Note',
label: 'Note',
fields: [
{
name: 'children',
label: 'Children',
type: {
widget: 'markdown',
},
},
],
},
],
}
You can also use this configuration object to replace HTML tags! Define a component that matches an HTML tag:
{
preview: {
components: {
// Imput will now replace all H1 tags with the following HTML
h1: (props: any) => (
<h1 {...props} className="my-custom-class" />
)
}
},
},
Adding styles to your previews
The last piece of the puzzle is adding styles to your previews. You can do so by using the styles
array which accepts any number of public CSS files which will be fetched and loaded at runtime.
{
preview: {
styles: ["/css/global.css", "https://mysite.com/style.css"]
}
}
Styles need to be public to separate Imput's css from yours! If your styles are built at runtime you can usually add an extra rule to output a static version of them into a public-facing folder.
Adding TailwindCSS to the preview
A good example of this limitation is TailwindCSS. On a normal application postcss
would compile Tailwind on the fly transforming:
@tailwind base;
@tailwind components;
@tailwind utilities;
Into actual CSS classes. Imput can't do this since it runs on your browser so we need to tell Tailwind to output CSS that we can read. Doing this is pretty easy thankfully! We just need to add an extra script to our package.json
.
{
// your other scripts
"styles": "npx tailwindcss -i './app/global.css' -o ./public/css/global.css --minify",
"dev": "npm run styles && <your dev command>
}
We're essentially telling Node that we want it to generate out our CSS before starting our dev server. The CSS is then placed somewhere we can access publicly (like Next.js' public folder).