Giter VIP home page Giter VIP logo

template-marketing-webapp-nextjs's Introduction

Contentful Marketing Starter Template

A Marketing Starter Template powered by Next.js & Contentful, pre-designed with optimized & adjustable pages, components, and data management.

The homepage of the Marketing Starter Template

$~$

What is Contentful?

Contentful provides content infrastructure for digital teams to power websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management, and delivery APIs, and a customizable web app that enables developers and content creators to ship their products faster.

$~$

DISCLAIMER ⚠️

The Starter Templates experience is currently only available to new users.

To benefit from this experience, please follow this link to create a new account and select the template to install: https://www.contentful.com/starter-templates/marketing-website/sign-up/?action=create_starter_template.

Alternatively, to immediately start the auto installation of this template after creating a new account, please follow this link: https://www.contentful.com/starter-templates/marketing-website/sign-up/?action=create_starter_template&template_name=marketing.

$~$

Begin your journey with Contentful and the Marketing Starter Template

Follow this guide to understand the relationship between Contentful and the Starter Template source code through guided steps:

  • Entry editing, and updates preview in the Starter Template application (online/locally)
  • Content type editing in the Contentful web app, as well as in the Starter Template's code

$~$

Features

  • Composable content through powerful & flexible content modeling.
  • Localization ready.
  • SEO ready.
  • Server-side rendering with Next.js1.
  • Optimized data management with React Query2.
  • Generation of GraphQL3 typed code (schema, types, and React Query hooks), in sync with the content types through graphql-codegen4.
  • Enhanced Developer Experience with TypeScript5.

$~$

Getting started

To get started, read the following guidelines.

$~$

Environment variables

In order to authenticate the requests to the Contentful APIs, the following values are necessary:

Rename the .env.example file to .env and add the necessary values.

$~$

Dependencies

To install the necessary dependencies, run:

yarn

Run the Starter Template in development mode

yarn dev

The Starter Template should be up and running on http://localhost:3000.

All necessary dependencies are installed under node_modules and any necessary tools can be accessed via npm scripts.

$~$

Development

Node

It is recommended to use the Node version listed in the .nvmrc file, we recommend using nvm to easily switch between Node versions.

$~$

Husky & git hooks

This repository makes use of Husky to enforce commit hooks.

The config for both the pre-commit and pre-push hooks can be found in the .husky folder, located in the root of the project.


Pre-commit

Before allowing a commit, we require a successful result from the TypeScript compiler (tsc) and our lint-staged script will be run.

This ensures all ESLint and Prettier rules are enforced on the files that are staged to be committed.

The tsc command is run separately from the lint-staged step because we require the Typescript compiler to sample all files.

This is important to ensure that no deviating types were introduced by the codegen for example.


Pre-push

The same two tasks are run for pre-push and for pre-commit.


Overriding the Husky git hooks

In case of wanting to bypass the pre-commit or pre-push hooks, pass a --noVerify flag to your Git commands.

⚠️ Make sure you only use this if you know why you're using it. ⚠️

$~$

Contentful API & GraphQL

This project makes use of Contentful's GraphQL API.

API calls made to the Contentful GraphQL endpoint are made through React Query useQuery hooks.

The hooks are generated from the .graphql files collocated within the components, the following happens:

  1. [folderName]/[fileName].graphql file, containing a query, is detected by the codegen
  2. [folderName]/__generated/[fileName].generated.ts is generated
  3. Within the generated file, a new hook is generated with the following pattern: use[fileName]
  4. The hook can now be imported and used within the .ts(x) files in the component folder

$~$

GraphQL & code generation

We use graphql-codegen to generate a type-safe API client, utilizing React Query as the "client".

The data for the hooks is pre-fetched on the server-side.

For more information on how this data is hydrated please read the official documentation.


Commands

In order to (re-)generate the GraphQL schema, types and hooks, please use either of the following commands:

  • yarn graphql-codegen:generate generates a schema, types and code to fetch data from the Contentful APIs
  • yarn graphql-codegen:watch similar to the generate command, but it runs as a watch task which will rerun the steps when changes are made in the .graphql files

The first steps of the codegen generate files that contain the GraphQL schema and matching TypeScript types. They're generated to the src/lib/__generated folder and ought to be committed once altered/added to the repository.

Additionally, the codegen watches .graphql files in our src folder, if it runs successfully it generates a __generated folder collocated in the folder where the .graphql file was found.

One exception to this rule is the src/lib/fragments folder which contains shared GraphQL Fragments that are used in several other queries/fragments.

The TS types for these files are generated in the same location, in a __generated folder and like the other files ought to be committed.


Configuration

The configuration for the codegen can be found in codegen.ts, located in the root of the project.

$~$

Contentful Components

The term Contentful Components (ctf-components for short) is used for React components that have an equivalent Contentful content type.

E.g. all React components needed for rendering the content-type HeroBanner can be found in the folder src/features/ctf-components/ctf-hero-banner.

Usually a ctf-component is composed of 3 files:

  • ctf-[contentypeName].graphql: holding the query strings needed for the GraphQL request to fetch the components data.
  • ctf-[contentypeName]-gql.tsx: React component which executes the GraphQL query and passes the result to a component for rendering.
  • ctf-[contentypeName].tsx: the React component which is actually rendering the content type.

Optionally, a folder with TypeScript interfaces which were generated by GraphQL codegen can also be included:

$~$

Component Resolver and content type mapping

There is a component-resolver (./src/components/component-resolver.tsx) React component, which is used to pick the right React component for rendering a content-type.

It requires as properties the content type id, its __typename (used by live preview), and optionally the content.

The component-resolver then uses a key map to find the right React component (./src/mappings.ts), where the key is the content type name and the value is the React component.

It will check the map componentMap first, and if the content type could be resolved it is assumed all content is available. The content is then passed to the React component.

If the content type could not be resolved, componentGqlMap will be used for resolving. If the React component is found the content type id and __typename will be passed, which is used by the component to fetch its data.

According to this pattern, all ctf-components suffixed with -gql should be added to componentGqlMap and all without a suffix should be added to componentMap.

$~$

Creating new Contentful Components

Creating new ctf-components involve the following steps:

  • Create a folder for the component files (./src/ctf-components/ctf-[contentTypeName])
  • Create the file for the GraphQL query strings (./src/ctf-components/ctf-[contentTypeName].graphql)
  • Optionally, generate TypeScript interfaces for the GraphQL result by calling yarn graphql-codegen:generate ( see GraphQL & code generation).
  • Create the React components for rendering (./src/ctf-components/ctf-[contentTypeName]-gql.tsx and ./src/ctf-components/ctf-[contentTypeName].tsx).
  • Add the component to the componentGqlMap in ./src/mappings.ts.

$~$


$~$

Deployment

The Starter Template can be deployed to your hosting provider of choice.

We offer integrations with Vercel and Netlify to speed up the process by clicking one of the deploy buttons below. The GitHub repository and the necessary environment variables keys are pre-configured in the hosting provider space.

Vercel Netlify
Deploy with Vercel Deploy to Netlify Button
Environment variables docs Environment variables docs

Make sure to add the necessary environment variables values to the hosting provider environment variables.


Content preview & live preview

Once you have the Starter Template deployed on your hosting provider, you can update the Content preview URL in your space settings.

You can follow our guide to learn how to do so: https://www.contentful.com/help/setup-content-preview.

For the live preview the basic field tagging for the inspector mode and live updates are already implemented. For custom components, you can find the instructions at our guide.

$~$


$~$

Support

If you have a problem with this Starter Template, post a message in our Contentful Community Slack.

Can't find your answer there? You can file a feedback issue through this template.

If you have other problems with Contentful not related to the Starter Template, you can contact the Customer Support.

$~$

Contributing

See CONTRIBUTING.md.

$~$

License

MIT License, see LICENSE.

$~$

Footnotes

  1. Next.js docs

  2. React Query

  3. GraphQL docs

  4. graphql-codegen

  5. TypeScript

template-marketing-webapp-nextjs's People

Contributors

adrianlthomas avatar cf-allstar[bot] avatar cf-remylenoir avatar chrishelgert avatar contentfulcormac avatar danwede avatar denkristoffer avatar dependabot[bot] avatar karankohli-cf avatar mattvanvoorst-contentful avatar mayagillilan avatar missating avatar roosterhack avatar stephanleece avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

template-marketing-webapp-nextjs's Issues

🐛 Bug - broken npm run export

Bug report

if you use npm run export it will generate error
Error: i18n support is not compatible with next export.

if you use it without i18n
it comes as
Error: Error serializing '.dehydratedState.queries[0].queryKey[1].locale' returned from 'getStaticProps' in "/404".

Summary

if you use npm run export it will generate error
Error: i18n support is not compatible with next export.

if you use it without i18n
it comes as
Error: Error serializing '.dehydratedState.queries[0].queryKey[1].locale' returned from 'getStaticProps' in "/404".

Environment

node 18.19

Steps to reproduce

it is your repository without .husky hooks
git clone https://github.com/anna-liepina/explore-cwa-next
npm i
npm run export

Expected results

successful export

Actual results

error :(

💬 Feedback - Improve Documentation with step by step guide to create component

First of all, congratulations for this great work on this template! The dev experience is very pleasant!

My first attempt was to create a basic component that I could use on the home page.

Despite the steps described in the README I took some time to understand what steps to follow to create a component.

It would be good to add a step by step guide to create a component from Contentful to React code.

Maybe this guide already exists and I just couldn't find it?

I wrote down the steps I followed to create my first component

Goal

Create a component with a "Title" field that can be inserted on the home page

On Contentful backoffice

  1. Go to Content model → +Add content type
  2. On name field → 💎 Demo component
  3. On Api Identifier → componentDemo
    ( !!! This will be used in the code and it may be difficult to change it later, make sure you use a correct identifier)
  4. Click “Create”
  5. Click “Add a field” → Text (Name: title, field ID: title)
  6. Check “This field represents the Entry title” —> Confirm —> Save
  7. On “Content model” → 📜 Landing page → Top section → click on “Settings”
  8. Add “💎 Demo component” to list bellow Accept only specified entry type → confirm → Save
  9. On “Content” → Add entry → 💎 Demo component
  10. On title → Demo Component Example
  11. Click on Publish
  12. On Content → Homepage → Top Section → Add existing content → Demo Component Example → Insert 1 Entry → “Publish changes”

On Code repository

Run following command

yarn run graphql-codegen:generate

Create component graphql query

src/components/features/ctf-components/ctf-demo/ctf-demo.tsx

Note that componentDemo in the query represent your Api Identifier previously defined

fragment DemoFields on ComponentDemo {
  __typename
  sys {
    id
  }
  title
}

query CtfDemo($id: String!, $locale: String, $preview: Boolean) {
  componentDemo(id: $id, locale: $locale, preview: $preview) {
    ...DemoFields
  }
}

Create Functional components

More detail here

src/components/features/ctf-components/ctf-demo/ctf-demo.tsx

the React component which is actually rendering the content type.

import { makeStyles } from '@mui/styles';
import { Theme } from '@mui/material';
import { DemoFieldsFragment } from './__generated/ctf-demo.generated';

const useStyles = makeStyles((theme: Theme) => ({
  root: {
    marginTop: theme.spacing(8),
    marginBottom: theme.spacing(8),
    textAlign: 'center',
  },
}));

export const CtfDemo = (props: DemoFieldsFragment) => {
  const { title } = props;
  const classes = useStyles();
  return <div className={classes.root}>{title}</div>;
};

src/components/features/ctf-components/ctf-demo/ctf-demo-gql.tsx

React component which executes the GraphQL query and passes the result to a component for rendering.

import { useContentfulLiveUpdates } from '@contentful/live-preview/react';
import React from 'react';

import { useCtfDemoQuery } from './__generated/ctf-demo.generated';
import { CtfDemo } from './ctf-demo';

interface CtfDemoGqlPropsInterface {
  id: string;
  locale: string;
  preview: boolean;
}

export const CtfDemoGql = ({ id, locale, preview }: CtfDemoGqlPropsInterface) => {
  const { data, isLoading } = useCtfDemoQuery({
    id,
    locale,
    preview,
  });

  const componentDemo = useContentfulLiveUpdates(data?.componentDemo, locale);

  if (isLoading || !componentDemo) {
    return null;
  }

  return <CtfDemo {...componentDemo} />;
};

Add component to mapping

on src/mappings.ts

add import to demo component into componetMap and componentGqlMap constants

export const componentMap = {
  ComponentDemo: dynamic(() => 
    import('@src/components/features/ctf-components/ctf-demo/ctf-demo').then(module => module.CtfDemo),
  ),
  ...
}

export const componentGqlMap = {
  ...pageTopicMap,
  ComponentDemo: dynamic(() =>
    import('@src/components/features/ctf-components/ctf-demo/ctf-demo-gql').then(
      module => module.CtfDemoGql,
    ),
  ),
  ...
}

Run your code

yarn dev

You should see your component display on http://localhost:3000/

💬 Question - This is mainly utilising SSR, how can I turn it into SSG instead?

Firs of all amazing work on this template, I find it really nice to use the approach you guys are using with fragments and codegen!

I'm finding it challenging to use SSG instead of SSR in such template, given the fact that each ctf-component ( some of them ) has a graphql.tsx file that does the custom fetching if provided with an id on its own that means it'll always request data from contentful on page reload?

I'm wondering if we have a very complex graphql query in each page, each page then will have nested queries and will take a while until everything loads, is there a guide somewhere to use SSG with this? also, any plans to add the new app directory?

Cheers!

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.