question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[gatsby-plugin-netlify-cms] Enabling preview styles

See original GitHub issue

Summary

I’m not sure how to get Netlify CMS to display custom preview styles.

Relevant information

I am using Netlify CMS with custom preview components that use CSS modules. It’s unclear how to get the styles to be generated and loaded. Particularly, I don’t know what I should be putting in stylesPath in the config. All of the styles are imported in the components, so there is no entry point as such. I tried setting the path to point to one of the base stylesheets, but styles.css is not generated. There is a styles.js file created by mini-css-extract-plugin, but no matching CSS.

import CMS from "netlify-cms";
import "netlify-cms/dist/cms.css";

// import preview templates for the CMS here

import ProjectPagePreview from "./preview-templates/ProjectPagePreview";

// Styles for the CMS
CMS.registerPreviewStyle("styles.css");

// Register preview templates

CMS.registerPreviewTemplate("projects", ProjectPagePreview);

Environment (if relevant)

File contents (if changed)

gatsby-config.js:

const siteConfig = require("./site-config");

module.exports = {
    pathPrefix: siteConfig.pathPrefix,
    siteMetadata: siteConfig.siteMetadata,
    mapping: {
        "ProjectsJson.client": "ClientsJson"
    },
    plugins: [
        `gatsby-plugin-typescript`,
        `gatsby-plugin-react-helmet`,
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                path: `${__dirname}/static/assets`,
                name: "uploads"
            }
        },
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                path: `${__dirname}/src/pages`,
                name: "pages"
            }
        },
        // This plugin identifies file nodes that are images and
        // transforms these to create new “ImageSharp” nodes.
        // With them you can resize images and
        // generate responsive image thumbnails.
        `gatsby-transformer-sharp`,
        // transform JSON file nodes
        `gatsby-transformer-json`,
        // This plugin exposes helper functions for processing
        // images with the NPM package “sharp”. It's used by
        // several plugins.
        `gatsby-plugin-sharp`,
        `gatsby-plugin-sass`,
        // Manifest for AppCache and PWA compatibility
        {
            resolve: `gatsby-plugin-manifest`,
            options: siteConfig.manifest
        },
        {
            resolve: `gatsby-plugin-netlify-cms`,
            options: {
                // One convention is to place your Netlify CMS customization code in a
                // `src/cms` directory.
                modulePath: `${__dirname}/src/cms/cms.ts`,
                stylesPath: `${__dirname}/src/scss/base-theme.scss`
            }
        }
    ]
};

package.json:

{
    "name": "aerian-site-rebuild",
    "description": "Aerian Studios.",
    "version": "0.0.1",
    "dependencies": {
        "@babel/preset-env": "^7.0.0-beta.54",
        "@fortawesome/fontawesome-svg-core": "^1.2.0-14",
        "@fortawesome/free-brands-svg-icons": "^5.1.0-11",
        "@fortawesome/free-solid-svg-icons": "^5.1.0-11",
        "@fortawesome/react-fontawesome": "^0.1.0-11",
        "@researchgate/react-intersection-observer": "^0.7.3",
        "classnames": "^2.2.6",
        "deep-map": "^1.5.0",
        "extract-text-webpack-plugin": "^3.0.2",
        "gatsby": "2.0.0-beta.45",
        "gatsby-image": "^2.0.0-beta.6",
        "gatsby-plugin-manifest": "^2.0.2-beta.2",
        "gatsby-plugin-netlify-cms": "^2.0.0-beta.6",
        "gatsby-plugin-offline": "next",
        "gatsby-plugin-react-helmet": "^3.0.0-beta.3",
        "gatsby-plugin-sass": "^2.0.0-beta.5",
        "gatsby-plugin-sharp": "^2.0.0-beta.5",
        "gatsby-plugin-typescript": "^2.0.0-beta.5",
        "gatsby-source-filesystem": "^2.0.1-beta.5",
        "gatsby-transformer-json": "^2.1.1-beta.2",
        "gatsby-transformer-sharp": "^2.1.1-beta.5",
        "leaflet": "^1.3.1",
        "netlify-cms": "^1.9.2",
        "react": "^16.4.1",
        "react-dom": "^16.4.1",
        "react-helmet": "^5.2.0",
        "react-leaflet": "^2.0.0",
        "react-markdown": "^3.3.4"
    },
    "keywords": [
        "gatsby"
    ],
    "license": "MIT",
    "scripts": {
        "build": "gatsby build",
        "start": "gatsby develop",
        "test": "jest",
        "updateSnapshot": "jest --updateSnapshot",
        "storybook": "start-storybook -p 9001 -c .storybook",
        "storybook-build": "build-storybook -c .storybook -o docs",
        "precommit": "lint-staged",
        "prepush": "jest --ci",
        "test-ci": "jest --coverage --coverageReporters=text-lcov --maxWorkers=2 > coverage.lcov && codecov"
    },
    "devDependencies": {
        "@babel/core": "^7.0.0-beta.54",
        "@babel/plugin-proposal-class-properties": "^7.0.0-beta.54",
        "@babel/plugin-proposal-optional-chaining": "^7.0.0-beta.54",
        "@babel/plugin-syntax-dynamic-import": "^7.0.0-beta.51",
        "@babel/preset-react": "^7.0.0-beta.54",
        "@storybook/addon-actions": "^3.4.8",
        "@storybook/addon-info": "^3.4.8",
        "@storybook/react": "^4.0.0-alpha.10",
        "@types/classnames": "^2.2.4",
        "@types/jest": "^23.1.1",
        "@types/leaflet": "^1.2.8",
        "@types/node": "^10.5.2",
        "@types/react-helmet": "^5.0.6",
        "@types/react-leaflet": "^1.1.5",
        "@types/react-test-renderer": "^16.0.1",
        "@types/storybook__addon-actions": "^3.0.3",
        "@types/storybook__addon-info": "^3.2.3",
        "@types/storybook__react": "^3.0.7",
        "autoprefixer": "^8.6.5",
        "babel-core": "^7.0.0-bridge.0",
        "babel-jest": "^23.4.0",
        "codecov": "^3.0.4",
        "css-loader": "^0.28.11",
        "extract-text-webpack-plugin": "^3.0.2",
        "gh-pages": "^1.2.0",
        "husky": "^0.14.3",
        "hygen": "^1.6.2",
        "hygen-react-typescript": "^1.0.2",
        "identity-obj-proxy": "^3.0.0",
        "intersection-observer": "^0.5.0",
        "jest": "^23.1.0",
        "lint-staged": "^7.2.0",
        "node-sass": "^4.9.0",
        "prettier": "^1.13.5",
        "react-docgen-typescript-loader": "^2.1.1",
        "react-docgen-typescript-webpack-plugin": "^1.1.0",
        "react-test-renderer": "^16.4.1",
        "regenerator-runtime": "^0.12.0",
        "ts-jest": "^22.4.6",
        "ts-loader": "^4.4.1",
        "tslint": "^5.10.0",
        "tslint-config-aerian": "^1.0.2",
        "typescript": "^2.9.2",
        "typings-for-css-modules-loader": "^1.7.0"
    },
    "lint-staged": {
        "*.{js,jsx,css,md,scss}": [
            "prettier --write",
            "git add",
            "jest --ci --findRelatedTests"
        ],
        "*.{ts,tsx}": [
            "tslint --fix",
            "git add",
            "jest --ci --findRelatedTests"
        ]
    },
    "repository": {
        "type": "git",
        "url": "git+https://github.com:aerian-studios/aerian-site-rebuild.git"
    },
    "jest": {
        "transform": {
            "^.+\\.tsx?$": "ts-jest",
            "^.+\\.jsx?$": "<rootDir>/jestPreprocess.js"
        },
        "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(tsx?)$",
        "moduleFileExtensions": [
            "ts",
            "tsx",
            "js",
            "jsx",
            "json",
            "node"
        ],
        "moduleNameMapper": {
            "^.+\\.(css|less|scss|png)$": "identity-obj-proxy",
            "^./pages.json$": "<rootDir>/__mocks__/pages.json"
        },
        "transformIgnorePatterns": [
            "node_modules/(?!(gatsby)/)"
        ]
    }
}

gatsby-node.js:

const path = require("path");
const { createFilePath } = require("gatsby-source-filesystem");
const deepMap = require("deep-map");
// Implement the Gatsby API “createPages”. This is
// called after the Gatsby bootstrap is finished so you have
// access to any information necessary to programmatically
// create pages.
exports.createPages = ({ actions, graphql }) => {
    const { createPage } = actions;

    /**
     * Work out the necessary to generate disntinct pages
     * @param {object} edge - The data for the distinct page
     */
    const generateDistinctPage = data => {
        const template = data.path && data.path.replace("/", "");
        const { id, sections, staff } = data;

        // for the time being we can just assume that there are different teplates for each of the pages, but we can add logic here to reuse page templates
        createPage({
            path: template,
            component: path.resolve(`src/templates/${String(template)}.tsx`),
            // additional data can be passed via context
            context: {
                id
            }
        });
    };

    /**
     *
     * @param {string} id - JSON id, generally a path to the file
     * @param {string} template - the string name of the template without the `.tsx`
     * @param {string} slug - generally the unique name of the JSON file (without path or file type)
     */
    const generatePage = (id, template, slug) => {
        createPage({
            path: slug,
            component: path.resolve(`src/templates/${String(template)}.tsx`),
            // additional data can be passed via context
            context: {
                id
            }
        });
    };

    /**
     * Run queries to get all the types of pages for which we need to make static pages
     *
     * `allPagesJson` needs a bit more information if we want to control how they are
     * processed in the future
     */
    return graphql(
        `
            {
                allProjectsJson(limit: 1000) {
                    edges {
                        node {
                            id
                            slug
                        }
                    }
                }
                allPagesJson(limit: 1000) {
                    edges {
                        node {
                            id
                            path
                            staff {
                                name
                            }
                            sections {
                                title
                            }
                        }
                    }
                }
            }
        `
    ).then(result => {
        if (result.errors) {
            result.errors.forEach(e => console.error(e.toString()));
            return Promise.reject(result.errors);
        }

        // Gatsby uses Redux to manage its internal state.
        // Plugins and sites can use functions like "createPage"
        // to interact with Gatsby.
        result.data.allProjectsJson.edges.forEach(edge => {
            const id = edge.node.id;
            const template = "project";
            const slug = `our-work/project/${edge.node.slug}`;

            generatePage(id, template, slug);
        });

        result.data.allPagesJson.edges.forEach(edge => {
            generateDistinctPage(edge.node);
        });
        return Promise.resolve();
    });
};

const excluded = new Set(["internal", "children", "parent", "id"]);

exports.onCreateNode = ({ node, getNode, getNodes }) => {
    if (node.internal.owner === "gatsby-transformer-json") {
        const parent = getNode(node.parent);
        const makeRelative = value => {
            if (typeof value === "string") {
                const pathToFile = path.join(__dirname, "static", value);
                const foundFileNode = getNodes().find(
                    n => n.absolutePath === pathToFile
                );

                if (foundFileNode) {
                    const p = path.relative(
                        parent.dir,
                        foundFileNode.absolutePath
                    );
                    if (p) {
                        return p;
                    }
                }
            }
            return value;
        };
        Object.keys(node).forEach(key => {
            if (excluded.has(key)) {
                return;
            }

            if (typeof node[key] === "string") {
                node[key] = makeRelative(node[key]);
            }
            deepMap(node[key], makeRelative, {
                inPlace: true
            });
        });
    }
};

gatsby-browser.js: N/A gatsby-ssr.js: N/A

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:16 (16 by maintainers)

github_iconTop GitHub Comments

1reaction
erquhartcommented, Jul 30, 2018

Can you test out #6871 and see if it works for you? With that, any imported styles in your modulePath module or any of the modules it imports down the chain will all be output to cms.css, which is automatically registered to the preview pane. (So no more stylesPath.)

1reaction
ascorbiccommented, Jul 23, 2018

The bit in gatsby-node.js just sets NETLIFY_CMS_PREVIEW_STYLES_SET to true if stylesPath is set to anything. Then cms.js calls CMS.registerPreviewStyle("styles.css") if that is set to true.

Read more comments on GitHub >

github_iconTop Results From Across the Web

gatsby-plugin-netlify-cms
If you need to customize Netlify CMS, e.g. registering custom widgets or styling the preview pane, you'll need to do so in a...
Read more >
Gatsby + SCSS = no Netlify CMS preview styles
Hi,. I'm working on a Gatsby site that uses gatsby-plugin-sass with the globImporter() option. The issue is that the Netlify CMS preview ......
Read more >
How to customize a Gatsby Netlify CMS starter
In this post we'll build upon a website which uses Gatsby for the end user facing part of the website and NetlifyCMS for...
Read more >
How to style Netlify CMS Preview Pane - Faith Morante
It's easy to see your preview pane with styles with these steps: npm install --save netlify-cms gatsby-plugin-netlify-cms; Add these:.
Read more >
talves/gatsby-plugin-netlify-cms - npm package
Learn more about @talves/gatsby-plugin-netlify-cms: package health ... CMS, e.g. registering custom widgets or styling the preview pane, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found