Skip to content

Sammy-T/snow-cms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

82ba461 · Mar 3, 2025
Jan 2, 2025
Jun 6, 2024
Mar 3, 2025
Jun 25, 2024
Jun 27, 2024
Jun 4, 2024
Jun 27, 2024
Jun 16, 2024
Jun 26, 2024
Mar 1, 2025
Mar 3, 2025
Mar 1, 2025

Repository files navigation

Snow CMS

A configurable CMS built with Svelte and inspired by Decap CMS and Sveltia CMS.

I created this project because I wanted a CMS with a rich-text markdown widget, more intuitive custom preview configuration, and a configurable backend.

snow_screens_01 snow_screens_02

Features

  • Editor Widgets
    • Boolean
    • Number
    • DateTime
    • Text
    • Markdown
    • Hidden
  • Editor Preview layout templates (Using html templates with replacement tags)
  • Editor Preview styles
  • CMS Backends
    • Local filesystem backend (Changes can be manually committed via your external Git CLI/GUI.)
    • GitHub backend
    • Specify your own custom backend
  • Optional hooks into editor actions
  • Output Markdown files with YAML front matter

Note

When using the local backend, certain filesystem interactions may perform slowly on Firefox.
For maximum compatibility, use a Chrome-based browser.

Getting Started

Installing

npm i snow-cms

Import the CMS into your project

  • Create a path in your project where you want the CMS to be accessed.
    ex. [my-site]/cms
    • Create a javascript module and import the CMS css and js.
    • Create an html file that loads the module and contains a root element with an id of app.
  • Create a path named cms-config in your project at the same level as the previously created cms path.
    ex. [my-site]/cms-config
    • Add a config.yml and any relevant css, html template, and js files.

Structure

An example of a basic project with the expected structure would look something like this:

index.html
cms/                        // The path to access the CMS. (Path name can be anything)
 |-- index.html             // Page that loads 'cms.js'
 |-- snow.js                // JS module that imports the CMS. (File name can be anything)
cms-config/                 // The path containing CMS config files. (Must be named 'cms-config')
 |-- config.yml             // CMS config file
 |-- preview-template.html  // Layout template to apply to page previews in the editor
 |-- preview-styles.css     // Styles to apply to page previews in the editor
 |-- cms-actions.js         // Additional behavior to hook into editor actions. (Optional)

Note

This example assumes the use of a build system that allows importing css in js. But you should adapt importing of the css and js to your project's build system.

cms/index.html

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
    <!-- The module that loads the CMS -->
    <script type="module" src="snow.js"></script>
  </head>
  <body>
    <!-- The root element used to load the CMS -->
    <slot id="app"></slot>
  </body>
</html>

cms/snow.js

// Import the CMS css and js
import 'snow-cms/dist/index.css';
import 'snow-cms/dist/index';

cms-config/

See Config for information on configuration as well as dev-site/cms-config for example config files.

Development

Install pnpm

npm install -g pnpm

Install necessary packages

pnpm install

Run the dev server

pnpm run dev

Then navigate to http://localhost:5173/ in your browser to view the dev site.

Build output files

pnpm run build

Built files will be output to the dist/ directory.

Structure

cms/

Contains the source files to build the CMS.

dev-site/

Contains files for running the development server.

Development server site's photos by Pixabay and Simon Berger from Pexels.

Config

See dev-site/cms-config for example config files.

Note

The GitHub backend requires a GitHub App to authenticate through and a server-side handler to exchange the access token.

The GitHub app should be configured with Callback URL and Setup URL set to the url of the CMS.

The server-side handler should exchange the received auth code for a user access token. Using one of the Oauth App middlewares makes this easy to set up.

Widgets

Widgets share the following configuration options:

  • label: The input label displayed in the editor interface.
  • name: The name of the input.
  • default: The input's default value.
  • required: Whether the input is required. (Defaults to true.)

Important

Each collection must have widgets configured for the names title, date, draft, and body.

Boolean

  • widget: 'boolean'
{
  label: 'Draft',
  name: 'draft',
  widget: 'boolean',
  required: false
}

Note

If the Boolean Widget's required option is set to true or isn't specified, the input's value must be true for editor data to submit.

Number

  • widget: 'number'
  • step: The amount the value increments / decrements by. (Defaults to 1.)
  • min: The minimum value allowed.
  • max: The maximum value allowed.
{
  label: 'Cookies',
  name: 'cookies',
  widget: 'number',
  step: 5
}

DateTime

  • widget: 'datetime'
  • type: 'datetime-local|date|time' Which input to display.
  • datetime_format: How the datetime should be displayed.
  • date_format: How the date should be displayed.
  • time_format: How the time should be displayed.
{
  label: 'Publish Date',
  name: 'date',
  widget: 'datetime',
  type: 'datetime-local',
  datetime_format: 'MM.DD.YYYY HH:mm'
}

Note

The corresponding format option should be set depending on the type.

Text

  • widget: 'string|text' Which input to display. Use string for single-line or text for multiline.
{
  label: 'Title',
  name: 'title',
  widget: 'string'
}

Markdown

  • widget: 'markdown'
{
  label: 'Body',
  name: 'body',
  widget: 'markdown'
}

Hidden

  • widget: 'hidden'
  • type: 'boolean|number|text|datetime-local|date|time' The type of the input's value.
  • default: The value of the hidden input.
{
  name: 'hiddenValue',
  widget: 'hidden',
  type: 'text',
  default: 'secret box'
}