Skip to content

Crownpeak Digital Experience Management (DXM) Software Development Kit (SDK) for React has been constructed to assist the Single Page App developer in developing client-side applications that leverage DXM for content management purposes.

License

Crownpeak/DXM-React-SDK

master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
sdk
 
 
 
 
 
 
 
 

Crownpeak Logo

Crownpeak Digital Experience Management (DXM) Software Development Kit (SDK) for React

Crownpeak Digital Experience Management (DXM) Software Development Kit (SDK) for React has been constructed to assist the Single Page App developer in developing client-side applications that leverage DXM for content management purposes.


Upgrading

  • If you're upgrading from a version before 2.1.0, please run the following before installing the new patch.
    yarn crownpeak upgrade
    # or 
    npx crownpeak upgrade
    
  • If you're upgrading to version 3.0.0 or higher, please note the change to asynchronous data loading, and include a check for this.state.isLoaded in your render() method. See the examples below.

Benefits

  • Runtime libraries to handle communication with either Dynamic (DXM Dynamic Content API) or Static (On-disk JSON payload) Data Sources

    As a development team runs their build process, the underlying React Application will be minified and likely packed into a set of browser-compatible libraries (e.g., ES5). We expect any DXM NPM Packages also to be compressed in this manner. To facilitate communication between the React Application and content managed within DXM, a runtime NPM Package is provided. The purpose of this package is:

    • Read application configuration detail from a global environment file (e.g., Dynamic Content API endpoint and credentials, static content disk location, etc.);
    • Making data models available to the React Application, which a developer can map against
      • Dynamic Data - Asynchronously processing data from the DXM Dynamic Content API, using the Search G2 Raw JSON endpoint; and
      • Static Data - Loading JSON payload data directly from local storage.
  • DXM Content-Type Scaffolding

    Developers will continue to work with their Continuous Integration / Delivery and source control tooling to create a React application. However, the purpose of the DXM Content-Type Scaffolding build step is to convert the React Components in a single direction (React > DXM), into the necessary configuration to support CMS operations. At present, the DXM Component Library includes the capability to auto-generate Templates (input.aspx, output.aspx, post_input.aspx) based upon a moustache-style syntax (decorating of editable properties). It is not intended that we re-design this process, as it is fully supported within DXM, and customer-battle-tested - therefore, in order to create Template configuration, the build step:

    • Converts React Components into Crownpeak Components by using the existing Component Builder Process, via the CMS Access API (DXM's RESTful Content Manipulation API), and then existing "post_save" process;
    • Creates Templates for each React Page (One of the DXM React Component Types) by using the existing Template Builder Process, again via the CMS Access API and existing "post_save" process; and
    • Creates a new Model for the React Page Content-Type, via the CMS Access API, so that authors can create multiple versions of a structured Page or Component, without needing to run an entire development/test cycle.

Install

yarn add crownpeak-dxm-react-sdk
# or 
npm install crownpeak-dxm-react-sdk

Usage - Runtime Data Libraries

Review example project at https://github.com/Crownpeak/DXM-SDK-Examples/tree/master/React for complete usage options. The example project includes the following capabilities:

  • Routing using React-Router and JSON payload, delivered from DXM to map AssetId to requested path. Although not part of the SDK itself, the example can be used if desired. For routes.json structure, see example at the foot of this README.
  • CmsStaticPage type to load payload data from JSON file on filesystem, delivered by DXM;
  • CmsDynamicPage type to load payload data from DXM Dynamic Content API.

CmsStaticPage Type

Loads payload data from JSON file on filesystem - expects knowledge of DXM AssetId in order to find file with corresponding name (e.g., 12345.json). CmsStaticPage is the data equivalent of a DXM Asset when used as a page. Example at /examples/bootstrap-blog/pages/blogPage.js:

import React from 'react'
import Header from "../components/header";
import TopicList from "../components/topicList";
import FeaturedPost from "../components/featuredPost";
import SecondaryPost from "../components/secondaryPost";
import BlogPost from "../components/blogPost";
import PostArchives from "../components/postArchives";
import Footer from "../components/footer";
import { CmsStaticPage, CmsDynamicPage } from 'crownpeak-dxm-react-sdk';
import Routing from "../js/routing";

export default class BlogPage extends CmsStaticPage
{
    constructor(props)
    {
        super(props);
        this.cmsWrapper = "";           //insert Wrapper Name from data-cms-wrapper-name in HTML, or don't include property to accept defaults.
        this.cmsUseTmf = false;         //set to true to create templates that use the Translation Model Framework.
        this.cmsUseMetadata = false;    //set to true to create templates that include the standard MetaData component.
        this.cmsSuppressModel = false;  //set to true to suppress model and content folder creation when scaffolding.
        this.cmsSuppressFolder = false; //set to true to suppress content folder creation when scaffolding.
        if(this.props && this.props.location) this.cmsAssetId = Routing.getCmsAssetId(this.props.location.pathname);
    }

    render() {
        super.render();
        return (
            this.state.isLoaded &&
            <div>
                <div className="container">
                    <Header month={this.props.match.params.month}/>
                    <TopicList/>
                    <div className="jumbotron p-3 p-md-5 text-white rounded bg-dark">
                        <FeaturedPost/>
                    </div>
                    <div className="row mb-2">
                        <div className="col-md-6">
                            <SecondaryPost/>
                        </div>
                        <div className="col-md-6">
                            <SecondaryPost/>
                        </div>
                    </div>
                </div>
                <main role="main" className="container">
                    <div className="row">
                        <div className="col-md-8 blog-main">
                            <h3 className="pb-3 mb-4 font-italic border-bottom">
                                From the Firehose
                            </h3>
                            <BlogPost/>
                        </div>
                        <aside className="col-md-4 blog-sidebar">
                            <PostArchives/>
                        </aside>
                    </div>
                </main>
                <Footer/>
            </div>
        )
    }
}

CmsDynamicPage Type

Loads payload data from DXM Dynamic Content API upon request - expects knowledge of DXM AssetId.

import React from 'react'
import Header from "../components/header";
import TopicList from "../components/topicList";
import FeaturedPost from "../components/featuredPost";
import SecondaryPost from "../components/secondaryPost";
import BlogPost from "../components/blogPost";
import PostArchives from "../components/postArchives";
import Footer from "../components/footer";
import { CmsStaticPage, CmsDynamicPage } from 'crownpeak-dxm-react-sdk';
import Routing from "../js/routing";

export default class BlogPage extends CmsDynamicPage
{
   constructor(props)
   {
       super(props);
       this.cmsWrapper = "";           //insert Wrapper Name from data-cms-wrapper-name in HTML, or don't include property to accept defaults.
       this.cmsUseTmf = false;         //set to true to create templates that use the Translation Model Framework.
       this.cmsUseMetadata = false;    //set to true to create templates that include the standard MetaData component.
       this.cmsSuppressModel = false;  //set to true to suppress model and content folder creation when scaffolding.
       this.cmsSuppressFolder = false; //set to true to suppress content folder creation when scaffolding.
       if(this.props && this.props.location) this.cmsAssetId = Routing.getCmsAssetId(this.props.location.pathname);
   }

   render() {
       super.render();
       return (
           this.state.isLoaded &&
           <div>
               <div className="container">
                   <Header month={this.props.match.params.month}/>
                   <TopicList/>
                   <div className="jumbotron p-3 p-md-5 text-white rounded bg-dark">
                       <FeaturedPost/>
                   </div>
                   <div className="row mb-2">
                       <div className="col-md-6">
                           <SecondaryPost/>
                       </div>
                       <div className="col-md-6">
                           <SecondaryPost/>
                       </div>
                   </div>
               </div>
               <main role="main" className="container">
                   <div className="row">
                       <div className="col-md-8 blog-main">
                           <h3 className="pb-3 mb-4 font-italic border-bottom">
                               From the Firehose
                           </h3>
                           <BlogPost/>
                       </div>
                       <aside className="col-md-4 blog-sidebar">
                           <PostArchives/>
                       </aside>
                   </div>
               </main>
               <Footer/>
           </div>
       )
   }
}

If you are using React function components, you must call out to a load() method on the page type, or include a comment containing exactly CmsPage for your page to be recognised and scaffolded correctly.

import React, { useState, useEffect } from 'react';
import { CmsStaticPage } from 'crownpeak-dxm-react-sdk';
// [ ... ]

export default function BlogPage()
{
    let isLoaded = CmsStaticPage.load(12345, useState, useEffect); // Or use CmsDynamicPage
    const cmsWrapper = "";           //insert Wrapper Name from data-cms-wrapper-name in HTML, or don't include property to accept defaults.
    const cmsUseTmf = false;         //set to true to create templates that use the Translation Model Framework.
    const cmsUseMetadata = false;    //set to true to create templates that include the standard MetaData component.
    const cmsSuppressModel = false;  //set to true to suppress model and content folder creation when scaffolding.
    const cmsSuppressFolder = false; //set to true to suppress content folder creation when scaffolding.

    return (
        isLoaded && 
        <div>
            <!-- [...] -->
        </div>
    )
}

export function PageLoadingItsOwnData() {
    // The comment below is required for your page to be recognised by the scaffolding process.
    // CmsPage
    return (
        <etc />
    )
}

Data Timeouts

If you wish to limit the time available for your page to load its data, you can specify a timeout in milliseconds like this:.

this.cmsLoadDataTimeout = 3000; // Timeout after 3 seconds

For React function components, the timeout is an optional fourth argument to the load method on the CmsStaticPage and CmsDynamicPage classes. For example:

let isLoaded = CmsStaticPage.load(12345, useState, useEffect, 3000);

Note that if a timeout occurs when loading dynamic data, it will automatically attempt to fall back to loading static data, with the same timeout value. If this succeeds, you will see a warning in the browser console. If it fails, the cmsDataError event will be triggered as described below, or you will see an error in the browser console.

Data Events

If you want to know when your data has loaded, or whether an error occurred during load, or you wish to modify properties of a request before it is sent, you can use the following:

this.cmsDataLoaded = (data, assetId) => {
    alert(`Loaded ${assetId}, ${JSON.stringify(data)}`);
}; 
this.cmsDataError = (exception, assetId) => {
    alert(`Error ${assetId}, ${exception}`);
};
this.cmsBeforeLoadingData = (options) => {
    // options will be either:
    // * an XmlHttpRequest for synchronous data requests; or
    // * a RequestInit object for asynchronous data requests, which will be passed to the fetch call.
};

Inside cmsDataLoaded it is also possible to modify or replace the loaded data. Return an object from your function to do this.

Inside cmsBeforeLoadingData any modifications you make to the options object will be passed to the data request.

For React function components, these events can be passed to the load method on the CmsStaticPage and CmsDynamicPage classes. For example:

const cmsDataLoaded = (data, assetId) => {
    alert(`Loaded ${assetId}, ${JSON.stringify(data)}`);
}; 
const cmsDataError = (exception, assetId) => {
    alert(`Error ${assetId}, ${exception}`);
};
const cmsBeforeLoadingData = (options) => {
    alert("Before loading data");
};
let isLoaded = CmsStaticPage.load(12345, useState, useEffect, 3000, cmsDataLoaded, cmsDataError, cmsBeforeLoadingData);

As with class-based pages, you can also modify or replace the data inside the cmsDataLoaded event by returning a new object.

Also as with class-based pages, you can modify the options object and these modifications will be passed to the data request.

If you have global changes that you wish to make for all data requests, these can be set directly on the CmsStaticDataProvider and CmsDynamicDataProvider objects via static properties.

CmsStaticDataProvider.beforeLoadingData = (options) => alert("Before loading static data");
CmsDynamicDataProvider.beforeLoadingData = (options) => alert("Before loading dynamic data");

CmsComponent

Includes CmsField references for content rendering from DXM within a React Component.:

import React from 'react';
import { CmsComponent, CmsField, CmsFieldTypes } from 'crownpeak-dxm-react-sdk';
import ReactHtmlParser from 'react-html-parser';

export default class BlogPost extends CmsComponent
{
    constructor(props)
    {
        super(props);
        this.post_title = new CmsField("Post_Title", CmsFieldTypes.TEXT);
        this.post_date = new CmsField("Post_Date", CmsFieldTypes.DATE);
        this.post_content = new CmsField("Post_Content", CmsFieldTypes.WYSIWYG);
        this.post_category = new CmsField("Post_Category", CmsFieldTypes.DOCUMENT);
        this.cmsFolder = ""; //set the subfolder in which the component will be created when scaffolding.
        this.cmsZones = []; //set the zones into which the component is permitted to be dropped.
        this.cmsDisableDragDrop = false; // set to true to hide this component from drag and drop.
    }

    render() {
        return (
            <div className="blog-post">
                <h2 className="blog-post-title">{ this.post_title }</h2>
                <p className="blog-post-meta">Date: { new Date(this.post_date).toLocaleDateString() }</p>
                { ReactHtmlParser(this.post_content) }
                { /*this.post_category*/ }
            </div>
        )
    }
}

If you are using React function components, you must call out to the CmsDataCache.setComponent() method for your component to be recognised and scaffolded correctly.

import React from 'react';
import { CmsField, CmsFieldTypes, CmsDataCache } from 'crownpeak-dxm-react-sdk';
import ReactHtmlParser from 'react-html-parser';

export default function BlogPost(props)
{
    CmsDataCache.setComponent("BlogPost");
    const cmsFolder = ""; //set the subfolder in which the component will be created when scaffolding.
    const cmsZones = []; //set the zones into which the component is permitted to be dropped.
    const cmsDisableDragDrop = false; // set to true to hide this component from drag and drop.

    var heading = new CmsField("Heading", CmsFieldTypes.TEXT);
    var description = new CmsField("Description", CmsFieldTypes.WYSIWYG);

    return (
        <div className="container">
            <h1>{ heading }</h1>
            { ReactHtmlParser(description) }
        </div>
    )
}

CmsDropZoneComponent

Enables implementation of draggable components via DXM. Example usage below:

import { CmsDropZoneComponent } from 'crownpeak-dxm-react-sdk';

import PrimaryCTA from "../components/primaryCta";
import SecondaryCTA from "../components/secondaryCta";

export default class DropZone extends CmsDropZoneComponent {
    constructor(props)
    {
        super(props);
        this.components = {
            "PrimaryCTA": PrimaryCTA,
            "SecondaryCTA": SecondaryCTA
        };
    }
}

Example implementation upon a CmsStaticPage or CmsDynamicPage:

<DropZone name="Test"/>

For further details, see examples/bootstrap-homepage project.

List Items

Enables implementation of list items within DXM. Example usage below (note comment, which is requirement for DXM scaffolding):

import React from 'react';
import {CmsComponent, CmsField, CmsFieldTypes, CmsDataCache } from 'crownpeak-dxm-react-sdk';
import SecondaryContainer from './secondaryContainer';
​
export default class SecondaryList extends CmsComponent
{
    constructor(props)
    {
        super(props);
        this.SecondaryContainers = new CmsField("SecondaryContainer", "Widget", CmsDataCache.get(CmsDataCache.cmsAssetId).SecondaryList);
    }
​
    render () {
        let i = 0;
        return (
            <div className="row">
                {/* <List name="SecondaryContainers" type="Widget" itemName="_Widget"> */}
                {this.SecondaryContainers.value.map(sc => {
                    return <SecondaryContainer data={sc.SecondaryContainer} key={i++}/>
                })}
                {/* </List> */}
            </div>
        )
    }
}

More Complex Replacements

If your application code is too complex for the parser to be able to extract your fields, it is possible to provide your own markup for the Component Library to use instead of your component, page and wrapper code:

{/* cp-scaffold 
<h2>{Heading:Text}</h2>
else */}
<h2>{{ heading.value.length > MAX_LENGTH ? heading.value.substr(0, MAX_LENGTH) + "..." : heading }}</h2>
{/* /cp-scaffold */}

It is also possible to add extra markup that is not used directly in your application, for example to support extra data capture:

{/* cp-scaffold 
{SupplementaryField:Text}
/cp-scaffold */}

When using cp-scaffold on a wrapper, you should use normal HTML comments rather than React comments, for example:

<!-- cp-scaffold {metadata} /cp-scaffold -->

String Replacements

If your application code uses components that are not directly contained with your application, the markup will not be detected during the parsing process. For this (and other) use-cases, you can now supply a list of string replacements that will be made at the end of the parsing process.

To do this, create a .cpscaffold.json file in the root of the project, as follows:

{
    "replacements": {
        "source": "replacement",
        "second_source": "second_replacement"
    }
}

Each key inside the replacements item contains the item to be replaced, and its value contains the replacement.

The source string will be turned into a regular expression, so characters that are meaningful in RegExps should be escaped using \\. This support allows for more complex replacements such as:

"<Col ([a-z]{2})=\\{([0-9]+)\\}>": "<div class=\"col-$1-$2\">"

If the source string contains a well-formed tag declaration, for example <div>, any corresponding element in the source string will match, including those with attributes. The replacement operation also combines duplicate attributes, if present after replacement, using a space to separate the values. So, for example, if the .cpscaffold.json replacements contains:

"<Container>": "<div class=\"container\">",

A source string containing <Container class="medium"> would be replaced with <div class="container medium">.

CmsFieldType

Enumeration containing field types supported within the SDK.

CmsFieldType DXM Mapping
TEXT Text
WYSIWYG Wysiwyg
DATE Date
DOCUMENT Document
IMAGE Src
HREF Href

Indexed Fields

Enables fields to be extracted from content and published as separate fields into Search G2, to support easier sorting and filtering:

this.title = new CmsField("Title", CmsFieldTypes.TEXT, null, CmsIndexedField.STRING);

A number of different values are available in the CmsIndexedField enumerated type to support different data types:

Enum value Search G2 Prefix Comment
STRING custom_s_ String, exact match only.
TEXT custom_t_ Text, substring matches allowed, tokenised so not usefully sortable.
DATETIME custom_dt_ DateTime, must be ISO-8601.
INTEGER custom_i_ 32-bit signed integer, must be valid.
LONG custom_l_ 64-bit signed integer, must be valid.
FLOAT custom_f_ 32-bit IEEE floading point, must be valid.
DOUBLE custom_d_ 64-bit IEEE floating point, must be valid.
BOOLEAN custom_b_ Boolean, must be true or false.
LOCATION custom_p_ Point, must be valid lat,lon.
CURRENCY custom_c_ Currency, supporting exchange rates.
If an invalid value for the specific data type is sent to Search G2, the entire statement is liable to fail silently.

Querying Custom Data from Dynamic Content API

Used to run a one-time dynamic query from DXM's Dynamic Content API.

import React from 'react';
import { Link } from 'react-router-dom';
import { CmsComponent, CmsDynamicDataProvider } from 'crownpeak-dxm-react-sdk';

export default class PostArchives extends CmsComponent
{
    constructor(props)
    {
        super (props);
        const data = new CmsDynamicDataProvider().getDynamicQuery("q=*:*&fq=custom_s_type:\"Blog%20Page\"&rows=0&facet=true&facet.mincount=1&facet.range=custom_dt_created&f.custom_dt_created.facet.range.start=NOW/YEAR-1YEAR&f.custom_dt_created.facet.range.end=NOW/YEAR%2B1YEAR&f.custom_dt_created.facet.range.gap=%2B1MONTH");
        this.months = data.facet_counts.facet_ranges.custom_dt_created.counts.filter((_c, i) => i%2 === 0);
    }

    render() {
        return (
            <div className="p-3">
                <h4 className="font-italic">Archives</h4>
                <ol className="list-unstyled mb-0">
                    {this.months.map((month) => {
                        return <li key={month.substr(0,7)}><Link to={`/posts/months/${month.substr(0,7)}`}>{ [new Date(month).toLocaleString('default', { month: 'long', year: 'numeric' })] }</Link></li>
                    })}
                </ol>
            </div>
        )
    }
}

Using Custom Data from Named JSON Object on Filesystem

Used to load content from a JSON Object on Filesystem and populate fields in CmsComponent.

import React from 'react';
import { CmsComponent, CmsStaticDataProvider } from 'crownpeak-dxm-react-sdk';

export default class TopicList extends CmsComponent
{
    constructor(props)
    {
        super (props);
        this.topics = new CmsStaticDataProvider().getCustomData("topics.json");
    }

    render() {
        return (
            <div className="nav-scroller py-1 mb-2">
                <nav className="nav d-flex justify-content-between">
                    {this.topics.map((topic) => {
                        return <a key={topic.toString()} className="p-2 text-muted" href="#">{ topic }</a>
                    })}
                </nav>
            </div>
        )
    }
}

Content creation options

There are a number of options that can be specified on the constructor of an item that extends CmsPage. These are set as properties on the extending class. For example:

this.cmsUseTmf = true;
Property Description
cmsUseTmf If set, the resulting template will use the Translation Model Framework (TMF). Defaults to false.
cmsUseMetadata If set, the resulting template will include the standard MetaData component. Defaults to false.
cmsSuppressModel If set, no model will be created for the resulting template. Defaults to false.
cmsSuppressFolder If set (or if cmsSuppressModel is set), no content folder will be created for the resulting model. Defaults to false.

Installation - DXM Content-Type Scaffolding (cmsify)

  • Requires update to DXM Component Library, by installing dxm-cl-patch-for-sdk-latest.xml.

  • Requires .env file located in root of the React project to be scaffolded. Values required within .env file are:

Key Description
CMS_INSTANCE DXM Instance Name.
CMS_USERNAME DXM Username with access to create Assets, Models, Templates, etc.
CMS_PASSWORD Pretty obvious.
CMS_API_KEY DXM Developer API Key - Can be obtained by contacting Crownpeak Support.
CMS_SITE_ROOT DXM Site Root Asset Id.
CMS_PROJECT DXM Project Asset Id.
CMS_WORKFLOW DXM Workflow Id (to be applied to created Models).
CMS_SERVER (Optional) Allows base Crownpeak DXM URL to be overridden.
CMS_SCAFFOLD_IGNORE (Optional) One or more paths to ignore during scaffolding, separated by commas. Paths are resolved relative to the application root.
# Crownpeak DXM Configuration
CMS_INSTANCE={Replace with CMS Instance Name}
CMS_USERNAME={Replace with CMS Username}
CMS_PASSWORD={Replace with CMS Password}
CMS_API_KEY={Replace with CMS Developer API Key}
CMS_SITE_ROOT={Replace with Asset Id of Site Root}
CMS_PROJECT={Replace with Asset Id of Project}
CMS_WORKFLOW={Replace with Workflow Id}
CMS_STATIC_CONTENT_LOCATION=/content/json
CMS_DYNAMIC_CONTENT_LOCATION=//searchg2.crownpeak.net/{Replace with Search G2 Collection Name}/select/?wt=json
CMS_SCAFFOLD_IGNORE=build,.cache

Installation instructions:

  1. Create new DXM Site Root and check "Install Component Project using Component Library 2.2"; or
$ yarn crownpeak init --folder <parent-folder-id> --name "New Site Name"
  1. After site creation, set the values for CMS_SITE_ROOT and CMS_PROJECT in your .env file to be the relevant asset IDs from DXM;

  2. Install the manifest (detailed above);

$ yarn crownpeak patch
  1. Verify that all your settings are correct.
$ yarn crownpeak scaffold --verify

Usage - DXM Content-Type Scaffolding

From the root of the project to be React scaffolded:

$ yarn crownpeak scaffold
yarn run v1.22.4
$ ../../sdk/crownpeak scaffold
Uploaded [holder.min.js] as [/Skunks Works/React SDK/_Assets/js/holder.min.js] (261402)
Unable to find source file [/Users/paul.taylor/Documents/Repos/Crownpeak/DXM-React-SDK/examples/bootstrap/js/bundle.js] for upload
Uploaded [blog.css] as [/Skunks Works/React SDK/_Assets/css/blog.css] (261400)
Saved wrapper [Blog] as [/Skunks Works/React SDK/Component Project/Component Library/Nav Wrapper Definitions/Blog Wrapper] (261771)
Saved component [BlogPost] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Blog Post] (261776)
Saved component [FeaturedPost] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Featured Post] (261777)
Saved component [Footer] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Footer] (261778)
Saved component [Header] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Header] (261779)
Saved component [PostArchives] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Post Archives] (261780)
Saved component [SecondaryPost] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Secondary Post] (261781)
Saved component [TopicList] as [/Skunks Works/React SDK/Component Project/Component Library/Component Definitions/Topic List] (261782)
Saved template [BlogPage] as [/Skunks Works/React SDK/Component Project/Component Library/Template Definitions/Blog Page Template] (261370)
Saved model [BlogPage] as [/Skunks Works/React SDK/Component Project/Models/Blog Page Folder/Blog Page] (261784)
Saved content folder [Blog Pages] as [/Skunks Works/React SDK/Blog Pages/] (261376)
✨  Done in 62.61s.

The scaffolding can be run multiple times as additional capabilities are added to the React project. Asset data within DXM will not be destroyed by future runs.

The crownpeak scaffold script supports a number of optional command-line parameters:

Parameter Effect
--dry-run Report on the items that would be imported into the CMS, but do not import them.
--verbose Show verbose output where applicable.
--verify Verify that the Crownpeak DXM environment is configured correctly.
--no-components Do not import any components.
--no-pages Do not import any pages, templates, or models.
--no-uploads Do not import any uploads; for example CSS, JavaScript or images.
--no-wrappers Do not import any wrappers.
--only <name> Only import items matching the specified name. Can be used multiple times.
--ignore <name> Ignore a single unmet dependency with the specified name. Can be used multiple times.

These are intended to improve performance for multiple runs, and you should expect to see errors if the items being skipped have not already been created within the CMS; for example, if you provide the --no--components parameter where the components have not previously been imported.

routes.json File Structure Example

[
  {
    "path": "/",
    "exact": true,
    "component": "BlogPage",
    "cmsassetid": "261377"
  },
  {
    "path": "/posts/months/:month",
    "component": "BlogPage",
    "cmsassetid": "23456"
  }
]

Videos & Tutorials

Walk through of creating Crownpeak's Demo Site (Procam) from scratch, starting with an empty folder. Crownpeak DXM SDK for React Video

Credit

Thanks to:

License

MIT License

Copyright (c) 2022 Crownpeak Technology, inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

Crownpeak Digital Experience Management (DXM) Software Development Kit (SDK) for React has been constructed to assist the Single Page App developer in developing client-side applications that leverage DXM for content management purposes.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •