Introduction Last updated: 2026-08-30

Sling CMS is an open-source CMS. Studio edits the site. The storefront is the live site. The API sits between them. Create can generate a page with AI. Nothing goes live until you publish.

  • Hosted Studio Sign up at studio.sling.biz. Create is capped at 20 pages a day. Use npx create-sling-app if you also want a local storefront.
  • Self-hosted The installer runs Studio, the API, and the storefront on your machine. Create uses your Gemini key and has no daily cap. Sign up at localhost:2021.

Connect your own APIs to widgets when you want a listing, a product page, or any other data-backed page.


Features

Studio

Edit pages, routes, widgets, theme, members, and the gallery from one place. Create generates a page as named sections. You review, then publish.

Storefront

A Next.js site that reads layout from the API. What you publish in Studio is what people see.

Widgets

Pages are React widgets with props you can edit in Studio. Add your own widgets in the storefront repo. AI writes JSX. It does not replace widget props.

Theme and gallery

Theme lives at /theme in Studio. Gallery is the asset library. Image props pick from Gallery.

What's next?

If you're already convinced to use Sling CMS, check the Installation guide.

And If you want to learn more, check out the Key concepts behind Sling CMS.

Quick Start Guide

Sling CMS offers a lot of flexibility. Whether you want to go fast and quickly see the final result,
or would rather dive deeper into the product, we got you covered.

Prerequisites

You need Node.js 18 or newer. Self-host also needs MongoDB. Local Mongo, Docker Desktop, or Atlas all work. The installer can start Mongo in Docker if the local URI is down. Create needs a Gemini API key. You can skip it and add it later.


👇 Let's get started!


Step 1: Create a project

# latest installer

npx create-sling-app@latest my-site

Pick Hosted or Self-hosted.

Hosted clones the storefront and points it at studio.sling.biz.

Self-hosted clones Studio, the API, and the storefront, then starts all three.


Step 2: Self-host prompts

If you chose self-hosted, you will be asked for a MongoDB URI and a Gemini key.

? Do you want a hosted solution or self-hosted dashboard? Self-hosted Dashboard ? Enter the name of your project: my-site ? Enter your MongoDB URI: mongodb://localhost:27017/sling ? Enter your GEMINI_API_KEY. Skip to add it later.

Skipped the Gemini key? Add GEMINI_API_KEY to sling-api/.env before Create will generate.


Step 3: Open the three URLs

When the installer finishes, it prints:

  1. Sign up at http://localhost:2021
  2. API at http://localhost:10001 — Studio and the storefront talk to this
  3. Preview the live site at http://localhost:4087

Create an account in Studio first. One company is picked automatically. A second company: paste that company’s key from Settings → Keys into sling-fe/.env and restart the storefront.

Then generate a page at localhost:2021/create (self-host) or studio.sling.biz/create (hosted). Create never takes over /. Home stays your first page.

Ctrl + C in the installer terminal stops all three.

Questions: hello@sling.biz.



Hosted vs self-host

Same product. The difference is who runs the API and where Create gets its model key.

Sample Screenshots

The screenshots below are taken from Sling CMS Studio.


What changes
  • Hosted — Studio at studio.sling.biz. Create is 20 pages a day. You do not run Mongo or the API.
  • Self-host — Studio, API, and storefront run on your box. Create uses your Gemini key and has no daily cap.
  • Widgets, pages, routes, theme, gallery, and members are the same in both.

Use Cases

  • Manage your Static Pages.
    • Frequent updates on your Static and Marketing pages can be productivity killer. Instead, Sling CMS can come very handy in updating content on the fly from the Studio. Use Page Templates to create blueprint of your static pages and create as many Page Routes (Actual URLs) by over-riding the defaults.
  • Modify Banners, In-Page Filters and Recommendations on your Product Listing & Detail Pages on the Fly without deploying any code.
    • Create Page Templates for Listing and Detail pages and customize the Banners run time from Sling CMS Studio for category and product pages.
  • Ready to use Widgets and Components
    • Use the widgets that ship with the storefront, or add your own in the repo and register them.
  • Quick launch your WebSite or Ecommerce Store.
    • Sling CMS comes with ready to use customizable Material UI theme and bootstrapped NextJS code. This can be used to create any kind of website quickly. Example use cases can be - A Real Estate Property search platform, a Used Car web portal, and advanced Blog or an Ecommerce webapp.

    Installation

    Key Concepts

    Sling CMS has 3 parts:

    • Studio — edit and publish (localhost:2021 or studio.sling.biz)
    • API — layout, auth, and Create (localhost:10001 when self-hosted)
    • Storefront — the live Next.js site (localhost:4087)
    The storefront reads page layout from the API. Studio writes that layout. Widget props you set in Studio are what the storefront renders.

    Page Templates

    Page Templates are like blue prints of an actual page. They allow you to add a React Widget on the Page and adjust its position using CSS Grid Layout. You should see a list of all page templates you create in templates section.

    logo

    A blue print of a page in the template looks like the image below. Below example, shows how a Product List Template looks like. This template has 3 sections header, body and footer with list of below mentioned React Widget components aligned as per their Grid Widths.

    • Head
      • Default Header Component
    • Body
      • BreadCrumbs
      • Filter Toggle Component
      • Product Filters
      • Product List Summary
      • Product Search Bar
      • Product Grid
    • Footer
      • Default Footer Component

    Screenshot of Product Listing Page Template.

    logo


    Page Props

    Click on a Widget in the Edit Page Template to view list of available props. You can add any number of Sling CMS Props for any Widget from the Widgets section. Once added, the new props will reflect automatically in this section.

    Please refer the image below.

    logo

    Route URLs

    • Sling CMS Routes are URLs that you can be created using any page template.
      A new URL route can either be a Static or a Dynamic URL.

      Please refer sample screenshot below

      logo


    • To add a Dynamic URL Route, Use <> brackets to make a route path dynamic prop variable

      For example, In the URL Route below, city, liCategory and l2Category are the dynamic props.

      /<city>/<l1Category>/<l2Category>/products

      Below URLs will match the above Route pattern:

      /dubai/women/clothing/products
       /pariah/shoes/puma/products
       /london/fashion-week/westminster/products


      Every URL route needs to have a Page Template. You can assign any page template to a route by Editing the Route.

      logo
    • Override Template Props
      • Page Template assigned to each route has set of widget props. These are the default props for every page route that uses it. To override these props, Configure the assigned page template in the routes section/

      • Refer screenshot below
        logo

    Widgets, Blocks & Components

    Every page in Sling CMS is made up of smaller React components called Widgets. Widgets can be combined to form larger Blocks, and a Component is a collection of blocks and widgets. Widgets provide flexibility to control different parts of the UI by passing props dynamically, making them customizable and reusable across different templates.

    Widget Types

    There are different types of widgets available based on the type of data they consume or how their props are defined. Below are the key widget types:

    • Static Widgets:

      These widgets use predefined static values for their properties. For example, labels or static text like a heading (`h1`). The value does not change dynamically.

      {"name": "h1", "propType": "static", "value": "Top watches in town."}

    • Response-Derived Widgets:

      These widgets derive their values from an external API response. They rely on the `responsePath` to map data from the API to the widget properties.

      {"name": "responsePath", "propType": "response-derived", "value": "data.products"}

    • Static-Derived Widgets:

      These are hybrid widgets that use static values derived from logic or concatenation with other values. For example, you can concatenate static strings and dynamic data to form labels.

      {"name": "h2", "propType": "static-derived", "value": "Showing 1 – 41 products of products."}

    • Option Widgets:

      These widgets provide a predefined set of options, which are typically used for dropdowns or selection inputs. For example, a widget may allow users to select between "List" or "Grid" view.

      {"name": "viewType", "propType": "static", "dataType": "option", "options": [{"value": 1, "label": "List"}, {"value": 2, "label": "Grid"}]}

    Widget Structure

    The following is a structured representation of a typical widget in Sling CMS:

    
                    {
                      "name": "Product List",
                      "key": "ProductList",
                      "type": "block",
                      "icon": "account_balance_wallet",
                      "description": "Displays a list of products fetched from the API.",
                      "ownership": "public",
                      "props": [
                        {
                          "name": "responsePath",
                          "propType": "response-derived",
                          "dataType": "string",
                          "default": "data.products"
                        },
                        {
                          "name": "h1",
                          "propType": "static",
                          "dataType": "string",
                          "default": "Top products in store"
                        }
                      ],
                      "component": "ProductListComponent",
                      "availableToAllPages": true
                    }
                        

    Widget Attributes

    • Name: A human-readable name for the widget.
    • Key: A unique identifier used to register the widget.
    • Type: The type of widget, which could be a "widget", "block", or "component".
    • Icon: The icon used to represent the widget in the UI.
    • Description: A short description explaining the widget's functionality.
    • Ownership: Specifies if the widget is "public" or "private".
    • Props: A list of properties (props) passed to the widget. These props can be of different types (static, response-derived, static-derived, or options).
    • Component: The React component that renders the widget.
    • Available to All Pages: Specifies if this widget can be used across all pages.

    Props Structure

    Each widget contains props that determine its behavior. These props can be of the following types:

    • Static: Predefined values (e.g., labels, text).
    • Response-Derived: Values derived from an API response using a path in the response object.
    • Static-Derived: Values derived by applying logic to static values (e.g., string concatenation).
    • Options: A set of predefined options (e.g., dropdowns, select inputs).

    By defining widgets this way, Sling CMS allows for highly customizable pages and layouts, while ensuring consistency and reusability across different parts of the site.

    Registering a Widget

    You can register your custom widgets using the registerWidget method. This allows you to add widgets dynamically and ensures they are available throughout your project. Here’s how to register a widget:

    
                    import { registerWidget } from "./widgetRegistry";
                    import ProductListComponent from "./components/ProductListComponent";
                    
                    // Define widget options
                    const widgetOptions = {
                        description: "Displays a list of products from the API.",
                        ownership: "public",
                        key: "ProductList",
                        icon: "account_balance_wallet",
                        props: [
                            {
                                name: "responsePath",
                                propType: "response-derived",
                                dataType: "string",
                                default: "data.products"
                            },
                            {
                                name: "h1",
                                propType: "static",
                                dataType: "string",
                                default: "Top products in store"
                            }
                        ],
                        availableToAllPages: true,
                        type: "block"  // Can be "widget", "block", or "component"
                    };
                    
                    // Register the widget
                    registerWidget("Product List", ProductListComponent, widgetOptions);
                        

    The registerWidget function takes three arguments:

    • Name: A human-readable name for the widget.
    • Component: The React component that implements the widget.
    • Options: An object containing widget properties such as description, props, ownership, and other metadata.

    Once registered, the widget will be available in the widget registry and can be used across pages or templates based on the configuration provided.

    Gallery

    Gallery is the asset library. Upload images there. Image props on a widget pick a file from Gallery. There is no separate Media Constants list.

    Settings and Theme

    Settings holds Company, Keys, Members, and Audit. Theme is its own rail item at /theme — colors, type, and spacing for the storefront. Header “View site” opens the live storefront.

    logo

    API Reference

    This section provides detailed descriptions of the core API methods in Sling CMS, starting with the Widget Registry APIs. These functions can be imported from the sling-core npm module and used directly in your project.

    registerWidget

    The registerWidget method allows you to add a custom widget to the Sling CMS widget registry, making it available in Sling CMS’s Studio for dynamic frontend rendering.

    Example Usage
                
                import { registerWidget } from 'sling-core';
                import MyCustomComponent from './MyCustomComponent';
                
                registerWidget('CustomWidget', MyCustomComponent, {
                    key: 'CustomWidget',
                    description: 'This widget displays custom data.',
                    ownership: 'public',
                    props: [
                        {
                            name: 'responsePath',
                            propType: 'response-derived',
                            dataType: 'string',
                            default: 'data.results'
                        },
                        {
                            name: 'h1',
                            propType: 'static',
                            dataType: 'string',
                            default: 'Custom Title'
                        }
                    ],
                    availableToAllPages: true,
                    type: 'block'
                });
                                
    Example Output
                
                {
                  "name": "CustomWidget",
                  "key": "CustomWidget",
                  "description": "This widget displays custom data.",
                  "type": "block",
                  "props": [
                    {
                      "name": "responsePath",
                      "propType": "response-derived",
                      "dataType": "string",
                      "default": "data.results"
                    },
                    {
                      "name": "h1",
                      "propType": "static",
                      "dataType": "string",
                      "default": "Custom Title"
                    }
                  ]
                }
                
                                

    initializeWidgetRegistry

    The initializeWidgetRegistry function is responsible for loading widgets into memory from the backend or from the local cache when running in a browser environment. It ensures that all widgets are available for use in Sling CMS Studio.

    Example Usage
                
                import { initializeWidgetRegistry } from 'sling-core';
                
                initializeWidgetRegistry()
                    .then(() => {
                        console.log('Widget registry initialized.');
                    })
                    .catch((error) => {
                        console.error('Error initializing widget registry:', error);
                    });
                
                                

    getAllWidgets

    The getAllWidgets method retrieves all widgets currently registered in the widgetRegistry. Optionally, it can filter widgets by their type (widget, block, or component).

    Example Usage
                
                import { getAllWidgets } from 'sling-core';
                
                const widgets = getAllWidgets();
                console.log('All registered widgets:', widgets);
                
                                

    setWidgets

    The setWidgets function allows you to manually populate the widget registry with an array of widgets fetched from the database or another source.

    Example Usage
                
                import { setWidgets } from 'sling-core';
                
                const widgets = [
                    { key: 'CustomWidget1', ... },
                    { key: 'CustomWidget2', ... }
                ];
                
                setWidgets(widgets);
                console.log('Widgets have been set.');
                
                                

    RenderTree

    The RenderTree method is a key part of Sling CMS’s architecture, responsible for rendering the entire page structure based on the page templates created in Sling CMS Studio. It dynamically attaches local widget code from your registry to the template and renders the page, making the frontend interactive and customizable.

    Typically, users define a page template in Sling CMS Studio and attach it to a Page Route (URL for the page). During server-side rendering (SSR), the page layout is automatically included in the initial rendering phase and passed to the global routes.

    The RenderTree method then works its magic by pulling in all the widgets from the registry, attaching the corresponding local widget code, and rendering the entire page structure as defined in the layout. This powerful mechanism allows Sling CMS to provide a flexible and dynamic frontend framework.

    Example Usage
    
    import React from 'react';
    import {useSelector} from 'react-redux';
    import Box from '@material-ui/core/Box';
    import {makeStyles} from '@material-ui/core/styles';
    import {RenderTree} from 'sling-core';
    import ErrorSling from '../ErrorSling';
    
    const GlobalPage = () => {
      const classes = useStyles();
      const layoutInitial = useSelector(({layout}) => layout);
      const {layoutConfig, pageTemplate} = layoutInitial;
      const layout = layoutConfig[pageTemplate];
    
      if (!layout) {
        return <ErrorSling statusCode={404} >;
      }
    
      return (
        <Box className={classes.appMain}>
          <Box className={classes.bodyMain}>
            <RenderTree
              layout={layout}
            />
          </Box>
        </Box>
      );
    };
    
    export default GlobalPage;
    
    
                

    Architecture

    Architecture Diagram

    Basics

    Sling CMS FE Client is customized NEXTJs web app. The default version uses getInitialProps() in _app.js to fetch initial config and layout for every route change.
    This will make every page render on the server side. _app.js has multiple Context Providers for Theme Settings, Layout Configuration, Route Constants, Language, Sling CMS Provider and Api Response.

    Global Route Handler

    • Sling CMS Fe uses NextJs's 3 dot file syntax[...global].jsto capture all the routes.
      Refer NextJs Dynamic Routes
    • Predefined routes take precedence over dynamic routes, and dynamic routes over catch all routes. Take a look at the following examples:
      pages/post/create.js - Will match /post/create even if a global handler is present.

    • Please Refer screenshot from NextJS official documentation.
    • logo

    SSR

    By Default NextJs supports server side rendering. The default version of Sling CMS uses getInitialProps() inside _app.js which forces every route change to fetch from the server. But this can be changed by using the pro version or by moving getInitialProps() from _app.js to custom pages.

    Head for Headless

    The storefront can call any backend you already have. Put the fetch in the widget, or map a response onto widget props (response-derived).
    • Widget code can call your API directly.
    • Response-derived props read a path on that response, for example data.products.
    • There is no separate Headless APIs rail in Studio. Bind data on the widget.

    Extending Sling CMS

    Customizing Pages & Routes

    Sling CMS uses global handler [...global].js to find all matching routes. To create a custom route which does not use Sling CMS you can just create your page route and NextJS will make sure the static file route you created gets the priority.

    Custom Widgets

    Sling CMS works by connecting widgets with the configuration from the Studio. You can create any number of custom widgets and use them in your pages. To create a new widget create a directory for your widget and add widget.json and export your code in the index.js. Export this widget in the main exported index.js file for all the widgets. Make sure the widget Key matches the key name referring your Widget object.

    Custom Cache

    The Sling CMS FE is dependent on Sling CMS Studio for fetching the initial layout and theme settings. This adds a bit of latency in the frontend website. To avoid this, you can specify your own custom CDN path for the static JSON files.

    FAQs

    Common questions after a first install.

    Install

    Do I need a license key?

    No. Sign up in Studio. Self-host does not ask for a license key.

    Why is localhost:10001 a page now?

    That is the API. It is running. Open Studio or the storefront to use the product. Tools can still request JSON from the same URL.

    The storefront was blank.

    Home should show a first page after signup. Refresh localhost:4087. If you have two companies, paste the key for the one you want from Settings → Keys into sling-fe/.env and restart.

    Create does nothing.

    Add GEMINI_API_KEY to sling-api/.env and restart the API. Hosted Create is 20 pages a day.

    Studio

    Where did Marketplace, AMP, and Analytics go?

    They are not in the product. Use Create, Pages, Routes, Widgets, Theme, Gallery, and Settings.

    Can Create replace the home page?

    No. Generated pages get their own URL. Home stays /.

    Who can invite people?

    Owner and Admin. Roles are Owner, Admin, Publisher, and Member.

    Help

    Where do I ask for help?

    hello@sling.biz or GitHub issues.