Giter Site home page Giter Site logo

simply007 / kontent-starter-corporate-next-js Goto Github PK

View Code? Open in Web Editor NEW

This project forked from kontent-ai-bot/kontent-starter-corporate-next-js

1.0 0.0 0.0 59.97 MB

Next.js corporate starter site using Kontent.ai as a data source.

Home Page: https://kontent-starter-corporate-next-js.netlify.app

License: MIT License

JavaScript 100.00%

kontent-starter-corporate-next-js's Introduction

Kontent Starter Corporate - Next.js

⚠️ Archival notice

This repository has been archived and is no longer maintained.

Build & Export

GitHub Discussions Stack Overflow

This is a Next.js corporate starter site using Kontent by Kentico as a CMS.

Demo

Screenshot

Deploy your own

Once you have access to the environment variables you'll need, deploy the example using Vercel:

Deploy with Vercel

How to use

Execute create-next-app with npm or Yarn to bootstrap the example:

npx create-next-app --example https://github.com/Kentico/kontent-starter-corporate-next-js kontent-starter-corporate-next-js
# or
yarn create next-app --example https://github.com/Kentico/kontent-starter-corporate-next-js kontent-starter-corporate-next-js

Environment variables

  1. Set up environment variables

    • Copy the .env.template file in this directory to .env (which will be ignored by Git):

      cp .env.template .env
  2. Run the development server

    npm run dev
    # or
    yarn dev

🎉 Open http://localhost:3000 with your browser to see the result.

By default, the content is loaded from a shared Kontent project. If you want to use your own clone of the project so that you can customize it and experiment with Kontent, continue to the next section.

Variable Required Description
KONTENT_PROJECT_ID YES Project identification described in the Setup section
KONTENT_PREVIEW_API_KEY NO Project key allowing to load non-published content described in the Setup and Preview sections
PREVIEW_SECRET NO A key securing the preview content access via application described in Preview entering section
STATIC_EXPORT NO If you choose to Static export of your site

Create your own data source project in Kontent

Create Kontent project

  1. Create an account on Kontent

  2. After signing up, create an empty project.

  3. Go to the "Project Settings", select API keys and copy the following keys for further reference

    • Project ID
    • Management API key
  4. Use the Kontent Backup Manager and import data to the newly created project from kontent-backup.zip file via command line:

     npm i -g @kentico/[email protected]
     # or
     yarn global add @kentico/[email protected]
    
     kbm --action=restore --projectId=<Project ID> --apiKey=<Management API key> --zipFilename=kontent-backup
  5. Go to your Kontent project and publish the imported items.

Connect Kontent project with code base

  1. Set env variables on .env:
    • KONTENT_PROJECT_ID - Should be the Project ID in Project settings > API keys.
    • KONTENT_PREVIEW_API_KEY - Should be the Preview API key in Project settings > API keys. Set this value if you want to see non-published content. If you need a more complex setup, jump to the Preview section.

Content editing development

Run the development server:

npm run dev
# or
yarn dev

🎉 Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying content in Kontent project. The page auto-updates as you edit the content. If you don't have KONTENT_PREVIEW_API_KEY specified, you need to publish the changes in order to see the changes on site.

About

This section describes the application from the data modeling point of view as well as application architecture approach.

Content model

Content is modeled to be ready for being used in the Web Spotlight. Web spotlight is not turned on by default intentionally, because this starter should also serve to the users without the feature on.

Content structure

The screen was taken from Relations tab. For a better idea, check out the content type relationships graph.

Structural types

The structure of the model is defined by linked items element called "Subpages"

  • Homepage - also stores configuration data like color palette, font specification, site logo, or social networks information
    • Navigation Item - mainly for defining the sitemap structure with the slugs.

SEO

SEO information is modeled as a content type snippet called "SEO".

This snippet is placed as a part of structural types. Every sitemap entry (the content item based on structural types and a post) allows specifying SEO metadata. This metadata is used in a custom App components (_app) component to be rendered on the page.

Layout types

Content for these structural wrappers is defined by linked items element called "Content" with limitation to exactly one item of the type:

  • Simple page - This content type is mapped to the simple_page.js. It is a simple page, containing title, subtitle, image and content.
  • Landing page - This content type is mapped to the landing_page.js. The more complex page consists of sections (see /components/sections).
  • Listing page - This content type is mapped to the listing_page.js. This page allows to specify which content types should be listed under it. Currently, the only supported in Post content type.

These types are then using specific layouts for rendering.

Turn on Web Spotlight

When you turn on the Web Spotlight. New content types "Homepage" and "Page" will be generated. In order to accommodate the content types, it is required to:

  • Remove the Page content type, because its responsibilities are handled by "Navigation Item" content type.
  • Transfer content model structure from "old" homepage content type to newly created one. The only difference is the "Subpages" element that will be modeled by Subpages element type. It is important to keep the codenames of the element the same.
  • Transfer the data from old "homepage".
  • Remove the "old" homepage content item and the "old" content type and set the new homepage content item codename to "homepage".

These steps are easily scriptable by creating a migration using Kontent CLI. To see the progress of including it to this starter, follow this issue.

Code

The application is using Next.js Catch all route to handle all of the routes. The logic is centralized in pages/[[...slug]].js.

Data loading

Data fetching structure

⚠ Benefits and drawbacks

Benefits

Described sitemap construction and configuration loading from Home Page structural type suits better for projects being built from scratch. In these situations, you need to have the sitemap and configuration (pallette, font, etc.) flexible and easily manageable from the headless CMS without necessity to change the code. This gives you flexibility to spin up the website and configure the project with No Code.

How to Spin Up a Next.js Project with No Code

Preview initial configuration

Drawbacks

This approach requires to make 2 requests per route to reload Mappings and Config objects. This additional work takes a couple of seconds for the development environment to spin up. For the production build, the results are still fast enough.

If you already know the configuration values and the sitemap structure, it is better to use Next.js dynamic routes showcased in Next.js Kontent blog repository, but the approach used for RichText links resolution, Preview URLs and Web Spotlight setup has to be adjusted to respect this new way of routing.

Sitemap construction

To define the sitemap and its mapping to specific content items there is getContentPaths method in lib/api.js. Internally it uses getSitemapMappings method which loads "homepage" item and its child items to the specific depth and then traverses down. This process creates a mapping between the sitemap (routes) and the content items storing data for the specific route.

One example item from the sitemap mappings:

{
  params: {
    slug: ["about", "more_information"],
    navigationItem: {
      id: "ABC",
      codename: "lorem",
      type: "navigation_item",
      language: "default",
      collection: "default",
      // whole system information
    },
    contentItem: { // could be same i.e. for blog posts
      id: "XYZ",
      codename: "ipsum",
      type: "simple_page",
      language: "default",
      collection: "default",
      // whole system information
    },
  }
}

Specific route data

For every single route, Next.js is loading data using the getPageStaticPropsForPath method. Internally, it reloads the site structure via getSitemapMappings method and then identifies the content items to load the data. Then loads the data using Delivery client and passes them as the Next.js props to the Next.js processing.

Static props returned from getPageStaticPropsForPath:

{
  // seo title, description, ....
  seo,
  // URL -> CONTENT ITEM mapping from above
  mappings,

 // RAW DATA FROM KONTENT
  data: {
    // data for layout (font, header logo, color palette, ...)
    config,
    // main content of the page
    page,
    // if the `page` is a `listing_page` type - linked items are passed in this item
    listingItems,
    // if any section of the page is a `listing_section` related items are stored there in the dictionary under the codename of the listing section content item
    listingSections
  },
};

The data passed as Next.js props are then populated in _app.js and other components in the component tree.

Currently, the sitemap is reloaded for every request. The following approach was selected because there is currently no way to pass more information than just a path from getStaticPaths to getStaticProps. See the official Next.js GitHub discussion comment for more information. It is possible to extend the implementation with the caching, this approach is about to be application specific, so it is not part of the starter.

Content types - React components mapping

Application is using the codename of the content type to load proper react component and render it. If the application does not find the proper component, it fails or displays special UnknownComponent in case of development environment.

const componentName = upperFirst(camelCase(get(section, "system.type", null)));

const Component = sections[componentName];

if (process.env.NODE_ENV === "development" && !Component) {
  console.error(
    `Unknown section component for section content type: ${contentType}`
  );
  return (
    <UnknownComponent key={section_idx} {...this.props}>
      <pre>{JSON.stringify(section, undefined, 2)}</pre>
    </UnknownComponent>
  );
}

return <Component key={section_idx} {...props} section={section} />;

Reference:

Preview

Next.js offers embedded possibility to preview unpublished content - the preview mode. This feature is integrated with Kontent preview in this starter. Once the preview is enabled, all api calls are performed to the Kontent Preview endpoints.

There are two Next API routes - /api/preview and /api/exit-preview - that works as described in Next.js docs.

Enter the preview

To enter the preview, just access /api/preview API route with the preview secret you set in your environment variables.

http://localhost:3000/api/preview?secret=PREVIEW_SECRET

If you don't have your PREVIEW_SECRET environment variable set, your preview is not secured and could be accessed by anybody. Read more on Official Next.js docs.

Once your secret is verified, you will be redirected to home page and you could see non-published content and the toolbar that allows you to exit the preview.

Preview bar

Preview URLs

Kontent offers a possibility to set the preview URLs for the content types. The starter (/api/preview route) is already prepared to consume this preview URLs for structural types and for the Post content type.

To allow that for your project, just set the Preview URLs for Navigation item, Homepage, and Post content type to (fill values in angle brackets):

https://<YOUR-HOST-DOMAIN>/api/preview?secret=<PREVIEW_SECRET>&redirectItemCodename={Codename}

Exit the preview

Once the preview is enabled a new toolbar pops up on the top of the page. This allows to close the preview (the "EXIT PREVIEW" button leads to the /api/exit-preview API route).

Publish process and data fetching

Next.js provides multiple ways to fetch the data. This starter is mainly focused to be used in two of these modes. Incremental static regeneration and static export.

Incremental Static regeneration (ISR)

This approach serves well for most of the use cases. Application is generated as static HTML and then re-hydrating React components with JSON data objects. It supports Preview functionality. The publishing process with incremental static regeneration ensures that the new content is propagated in the background and once it is ready, the application starts to serve it instead of the stale content. Revalidation period is set to 5s as you can see on getStaticProps method in [[...slug]].js component.

This deployment requires a place to run Node.js code. Since the starter target configuration is set to serverless (see next.config.js file information), it is possible to use lambda functions to run this server code. This fits the Next.js recommended provider Vercel. But you could use i.e. Netlify in combination with the netlify-plugin-next-js, or any other cloud provider and configure lambdas the same way as Netlify plugin does. The second option is to switch the target to the server and use a Node.js server deployed to any of your cloud providers.

To run this locally, run following commands:

yarn build
yarn start

Static

It is possible to pre-generate all site and deploy it right to the CDN without the necessity to have a place to run Node.js code (lambda function/server). This removes the option of having the content up-to-date out-of-the-box when your content changes as well as preview functionality. You need to set up the webhooks and their handlers, that regenerate the site and re-deploy the generated content to your CDN for both released and preview content.

⚠ To be able to run the export, the site has to be built without fallback pages. The starter is turning the fallback pages on unless the STATIC_EXPORT environment variable is set to true.

To generate the site locally, run fun following command:

yarn static-export

Server-side rendering

It is also possible to use this starter for server-side rendering, it requires you to implement getServerSideProps in Next.js Page component, but as the Next.js documentation states - "You should use getServerSideProps only if you need to pre-render a page whose data must be fetched at request time" - and that is not the primary requirement for this starter.

If you want to see the example checkout What’s the best place to host Next.js site? by Ondřej Polesný.

Rich text element resolution

A Rich text element could carry more than just a text. It could contain links, images, components, and inline linked items. The starter offers a /style-guide section to showcase the options to resolve complex structure into the React components.

The /style-guide is a page based on the simple_page layout containing title, sub, and the content in a form of a rich text element. This rich text element contains a showcase of various typographical examples (headlines, lists, tables) and also images, components, and links to other content items. To parse and resolve them, there is a pair of components. The first one is RichTextComponent containing the parsing logic (using html-react-parser library) and offering the possibility to implement the resolution. And the second one defining the resolution logic from rich text blocks to React Components - the RichText component.

The usage is simple. To resolve the rich text element, you place the RichText component and provide a rich text element object and then propagate all other props used to load appropriate data (linked items data, information about mapping to be able to resolve URL to specific content item).

<RichText
  {...props} // Used to load mappings and linked items data
  richTextElement={get(page, "content", null)}
/>

In /style-guide, you can see these results.

Rich Text Component

Rich text component resolution

Rich Text Image

Rich text image resolution

Rich Text Component

Rich text link resolution

💡 You could use a different approach to resolve the rich text element blocks. It is possible to use the embedded support in Javascript SDK that allows resolving blocks into the string objects and then utilize library react-jsx-parser to transform this string representation to React components This approach however requires the recreation of the model classes when you need them from the JSON object form because Next.js/React does not allow passing class objects via props of a React Component. If you want to get more detailed information about this topic, feel free to raise the question issue.

Design

The application is using Material Design. The main theme is configured in _app.js. Components are styled using makeStyles method to ensure isolation.

import React from "react";
import get from "lodash.get";
import { Container, makeStyles } from "@material-ui/core";

/*styles
const useStyles = makeStyles((_theme) => ({
  section: {
    background: "red",
  },
}));
*/
function FeaturesSection(props) {
  const section = get(props, "section", null);
  const classes = {};

  return (
    <section
      id={get(section, "system.codename", null)}
      className={classes.section}
    >
      <Container>Section: {get(section, "system.codename", null)}</Container>
    </section>
  );
}

export default FeaturesSection;

There are some additional steps done to allow Server rendering. The concept of the app was used from Official Next.js example for material design.

Follow this issue to see how to use configurable theme definition in Next.js app.

Learn More

To learn more about Next.js, take a look at the following resources:

Related content

kontent-starter-corporate-next-js's People

Contributors

simply007 avatar makma avatar strizr avatar tomtyack avatar kontent-ai-bot avatar

Stargazers

Davs Howard avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.