Sky’s the limit: Headless eCommerce with Next.js

A presentation at JSWorld in February 2021 in by Lisi Linhart

Slide 1

Slide 1

Sky’s the limit: Headless eCommerce with Next.js @Storyblok @lisi_linhart

Slide 2

Slide 2

Lisi Linhart Developer Experience @storyblok

Slide 3

Slide 3

What is headless eCommerce

Slide 4

Slide 4

eCommerce options headless systems Marketshare today Wordpress (2003) Drupal (2001) Shopify (2006) Joomla (1998) Squarespace (2004) Wix (2006) Magento (2008) Typo3 (1998) Blogger (1999) First Website (1991) 1990 2000 ButterCMS (2015) Prestashop (2008) Contentful (2013) Storyblok (2017) CraftCMS (2011) 2010 2020 @Storyblok @lisi_linhart

Slide 5

Slide 5

Wordpress (2003) Marketshare today headless eCommerce Drupal (2001) Shopify (2006) Joomla (1998) Squarespace (2004) Wix (2006) Magento (2008) Typo3 (1998) Blogger (1999) First Website (1991) 1990 2000 ButterCMS (2015) Prestashop (2008) Contentful (2013) Storyblok (2017) CraftCMS (2011) 2010 2020 @Storyblok @lisi_linhart

Slide 6

Slide 6

! Unicorn Dash

Slide 7

Slide 7

Developer Manager Client “#$% !!!! Editor

Slide 8

Slide 8

! I want a fast, good looking store, that works with my logisitics

Slide 9

Slide 9

!

Slide 10

Slide 10

! I want to create something that we can reuse for other stores to quickly develop new stores

Slide 11

Slide 11

!

Slide 12

Slide 12

! I want to be able to quickly & easily make changes and be able to discuss those changes

Slide 13

Slide 13

!

Slide 14

Slide 14

! If you want it to be quick and reusable, I want to use my own tech stack.

Slide 15

Slide 15

!

Slide 16

Slide 16

! Unicorn Dash JAMStack

Slide 17

Slide 17

! Unicorn Dash Content Management

Slide 18

Slide 18

! Unicorn Dash eCommerce

Slide 19

Slide 19

! “

Slide 20

Slide 20

! Excellent performance Internationalization Component Based Next.js Commerce Integrations for eCommerce providers Typescript Support Incremental Builds https://nextjs.org/commerce Integrates perfectly with Vercel @Storyblok @lisi_linhart

Slide 21

Slide 21

!

Slide 22

Slide 22

! shell git clone https://github.com/vercel/commerce.git cd commerce yarn && yarn dev .env.local BIGCOMMERCE_STOREFRONT_API_URL=https://demo-store.mybigcommerce.com/graphql BIGCOMMERCE_STOREFRONT_API_TOKEN=ey…yA BIGCOMMERCE_STORE_API_URL=https://api.bigcommerce.com/stores/.. BIGCOMMERCE_STORE_API_TOKEN=8….n BIGCOMMERCE_STORE_API_CLIENT_ID=d…..4 STORYBLOK_TOKEN=r….t

Slide 23

Slide 23

!

Slide 24

Slide 24

” !

Slide 25

Slide 25

! Real-time Visual Editor Selection and arrangement of products through integration plugins Storyblok Storefront storyblok.com/docs/guide/integrations/ecommerce Flexibility & Reusability Decouple store presentation from store logisitics Localization / Review Features @Storyblok @lisi_linhart

Slide 26

Slide 26

! This Example github.com/storyblok/nextjsbigcommerce-starter/ storyblok.com/tp/storefront-nextbigcommerce

Slide 27

Slide 27

! Use Template jane@unicorn-dash.com

Slide 28

Slide 28

! jane@unicorn-dash.com 2 1 token to connect to Storyblok basic component setup

Slide 29

Slide 29

! jane@unicorn-dash.com 1 connection to BigCommerce

Slide 30

Slide 30

! ” #

Slide 31

Slide 31

! Sales Integration Integration with multiple services BigCommerce Store Shipping Providers Storefront & Managment APIs Stock Management https://developer.bigcommerce.com/ @Storyblok @lisi_linhart

Slide 32

Slide 32

! adds a! the products

Slide 33

Slide 33

! Steps to connect Storyblok to Next.js 1. Add Storyblok to Next.js 2. Create Dynamic Components 3. Add Products in Storyblok 4. Live Edit in Storyblok

Slide 34

Slide 34

! Add Storyblok to Next.js storyblok.com/tp/add-a-headless-cms-tonext-js-in-5-minutes

  1. Install Storyblok Packages 2. Create a Storyblok Client 3. Create Update Hook & Bridge shell yarn add storyblok-js-client storyblok-react

Slide 35

Slide 35

! 1. Install Storyblok Packages 2. Create a Storyblok Client 3. Create Update Hook & Bridge storyblok.js Add Storyblok to Next.js import StoryblokClient from ‘storyblok-js-client’ const Storyblok = new StoryblokClient({ accessToken: ‘your-preview-token’, cache: { clear: ‘auto’, storyblok.com/tp/add-a-headless-cms-to- type: ‘memory’ } next-js-in-5-minutes }) export default Storyblok preview token from Storyblok

Slide 36

Slide 36

! 1. Install Storyblok Packages 2. Create a Storyblok Client 3. Create Update Hook & Bridge storyblok.js Add Storyblok to Next.js export function useStoryblok(originalStory) { let [story, setStory] = useState(originalStory); function initEventListeners() { // adds the event listeners // and calls setStory } function addBridge(callback) { // adds the bridge <script> tag } storyblok.com/tp/add-a-headless-cms-tonext-js-in-5-minutes useEffect(() => { // first load the bridge, then initialize the event listeners addBridge(initEventListeners); }); return story; }

Slide 37

Slide 37

! index.ts import { Layout } from ‘@components/common’ import { getConfig } from ‘@framework/api’ import Storyblok from ‘@lib/storyblok’ get data from Storyblok API export async function getStaticProps({ preview, locale, }) { const config = getConfig({ locale }) const { data: { story }} = await Storyblok(‘cdn/stories/home’, {}) Add Storyblok to Next.js storyblok.com/tp/add-a-headless-cms-tonext-js-in-5-minutes initizalize visual editor via hook return { props: { story, }, revalidate: 14400, } } export default function Home({ story }) { const story = useStoryblok(props.story) return ( <div>…</div> ) } Home.Layout = Layout

Slide 38

Slide 38

! index.ts import { ProductCard } from ‘@components/product’ import { Grid, Marquee, Hero } from ‘@components/ui’ import HomeAllProductsGrid from ‘@components/common/HomeAllProductsGrid’ Steps to connect Storyblok to Next.js 1. Add Storyblok to Next.js 2. Create Dynamic Components 3. Add Products in Storyblok 4. Live Edit in Storyblok 2

Slide 39

Slide 39

! DynamicComponent.ts match Storyblok component to React component Add Dynamic Components return the correct component based on the blok name const Components = { ‘product-feature’: Grid, ‘product-slider’: Marquee, ‘hero’: Hero, ‘product-grid’: HomeAllProductsGrid, } const DynamicComponent = ({ blok }) => { if (blok) { const componentName = dashify(blok.component) if(typeof Components[componentName] !== ‘undefined’) { const FoundComponent = Components[componentName] return ( <SbEditable content={blok} key={blok._uid} > <FoundComponent blok={blok} /> </SbEditable>) ) } else { return (<p>{componentName} is not yet defined.</p>) } } return null } export default DynamicComponent

Slide 40

Slide 40

! DynamicComponent.ts match Storyblok component to React component Add Dynamic Components const Components = { ‘product-feature’: Grid, ‘product-slider’: Marquee, ‘hero’: Hero, ‘product-grid’: HomeAllProductsGrid, } const DynamicComponent = ({ blok }) => { draft.json if (blok) { const componentName = dashify(blok.component) if(typeof Components[componentName] !== ‘undefined’) { const FoundComponent = Components[componentName] return (<FoundComponent blok={blok} />) } else { return (<p>{componentName} is not yet defined.</p>) } } return null } export default DynamicComponent name in the Storyblok Api

Slide 41

Slide 41

! index.ts export default function Home({ story, }) { const liveStory = useStoryblok(story); Add Dynamic Components const components = liveStory.content.body.map((blok) => { return (<DynamicComponent blok={blok} key={blok._uid} />) }) return ( <div> { components } </div> ) components are dynamica!y loaded via Storyblok } Home.Layout = Layout

Slide 42

Slide 42

! components/Hero.ts interface Props { add the blok className?: string headline: string !eld to the dynamic component description: string blok?: SbEditableContent } const Hero: FC<Props> = ({ headline, description, blok }) => { Add Dynamic Components return ( <div className=”bg-black”> <Container> <div className={s.root}>

<h2 className=”text-4xl leading-10 font-extrabold text-white sm sm:leading-none sm:tracking-tight lg:text-6xl”> {blok?.headline || headline } </h2> <div className=”flex flex-col justify-between”> use the content received from Storyblok <p className=”mt-5 text-xl leading-7 text-accent-2 text-white {blok?.description || description } </p> <Link href=”/blog”> <a className=”text-white pt-3 font-bold hover:underline fle cursor-pointer w-max-content”> Read it here <RightArrow width=”20” heigh=”20” className=”ml-1” /> </a>

Slide 43

Slide 43

! Steps to connect 1. Add Storyblok to Next.js 2. Create Dynamic Components 3. Add Products in Storyblok 4. Live Edit in Storyblok 1

Slide 44

Slide 44

! eCommerce integrations storyblok.com/docs/guide/integrations/ecommerce @Storyblok @lisi_linhart

Slide 45

Slide 45

” ! Live Demo Unicorn Dash

  1. Add Storyblok to Next.js 2. Create Dynamic Components 3. Add Products in Storyblok 4. Live Edit in Storyblok @Storyblok @lisi_linhart

Slide 46

Slide 46

! Unicorn Dash

Slide 47

Slide 47

simple review features

Slide 48

Slide 48

!”#$ ☕☕☕☕

Slide 49

Slide 49

! It’s great the components are already set up and can easily be adapted in Storyblok

Slide 50

Slide 50

! We have another client that needs a similar setup, we wi! reuse the same components

Slide 51

Slide 51

! I can easily prepare & discuss the campaign for the next big launch

Slide 52

Slide 52

! This meets our requirements. We wi! se! globa!y in no time

Slide 53

Slide 53

Pick headless eCommerce … to manage your storefront on multiple channels to use the technology you feel comfortable with to increase the performance & security to offer a nice UI & visual editor to customers to build flexible, custom storefronts to focus on the solution your customers sees @Storyblok @lisi_linhart

Slide 54

Slide 54

A sneak peak into the future headless eCommerce Friday February 26 Samuel Snopko, Head of DevRel @storyblok

Slide 55

Slide 55

Where to start? BigCommerce & Next.js Tutorial storyblok.com/tp/storefront-next-bigcommerce @Storyblok @lisi_linhart

Slide 56

Slide 56

Developer community Mike Penz Check our discord and join the ranks of our ambassadors @Storyblok @lisi_linhart

Slide 57

Slide 57

Thank you !