GithubHelp home page GithubHelp logo

zesty-io / website Goto Github PK

View Code? Open in Web Editor NEW
17.0 4.0 2.0 32 MB

Marketing Website using NextJS and Zesty.io Headless CMS

Home Page: https://www.zesty.io

License: The Unlicense

JavaScript 99.50% Dockerfile 0.01% CSS 0.09% Shell 0.05% HTML 0.36%
nextjs cms react zesty-io

website's Introduction

Zesty.io NextJS Marketing Website

Marketing Website using NextJS and Zesty.io Headless CMS

Stars Badge Pull Requests Badge Issues Badge GitHub contributors License Badge License Badge

License Badge

โšก Getting Started

Requires node version ^16.x.x and npm version ^8.x.x

Create a file at the root .env.local with PRODUCTION=false as the file contents

git clone [email protected]:zesty-io/website.git

cd website

npm install

npm run dev

## open browser to http://localhost:3000/

๐Ÿ’ก Syncing Zesty.io Content Models to Next JS

From the command line at the root of the project run:

node scripts/zesty-nextjs.js

This will create new files where needed, but will not overwrite existing files.

๐Ÿ’ก AutoDeploy

Any push or merge to the dev,stage, or production branch will kickoff an auto build script which will update the stage preview in Zesty.io manager and WebEngine preview.

dev is intended for testing, use as you wish, overwrite at needed. stage should be ready to review and test before pre-prod (beta) accounts pre production branch (beta) same config as production production should only be merged from accounts, after stage is verified good to deploy

dev: https://zesty-dev-website-m3rbwjxm5q-uc.a.run.app/ stage: https://kfg6bckb-dev.webengine.zesty.io OR https://zesty-website-m3rbwjxm5q-uc.a.run.app/ accounts: https://beta.zesty.io production: https://www.zesty.io OR https://zesty-website-production-m3rbwjxm5q-uc.a.run.app/

๐Ÿ’ก Contribution

  1. Create a branch
  2. Make change locally commit
  3. Test your changes with npm run build
  4. If build succeeds, create pull request against stage (our stage)

๐Ÿ’ก Deployment to Production

After a successfull deploy to stage create PR from stage to production, upon merge a production build will trigger.

๐Ÿ’ก CTA Components and Forms

Please use these core CTA components through your views. These forms already have validation setup and connect to our remote services.

๐Ÿ’ก Try Button

A button that trigger a dropdown guiding both a developer and marketers option

<TryFreeButton> View Try Free Button Component

Standard Form

A Form that posts to our CRM and has many option to controls inputs

<StandardFormWithSelect> View Standard Form Component

Subscribe Form

A simple form that asks for user email

<SubscribeCTA> View Subscribe Component

Developer Codeblock Starter

A one-line code block that shows developer how to start from the command line

<CodeBlock> View Code Block Component

Lead Capture

All lead capture funnels from the above components into one of two cloud functions which connect to ZOHO CRM.

  1. Marketing Subscribe: GCP Link Github Link Trigger Both Gisele and Randy have access to deploy this.
  2. Lead Capture: GCP Link Github Link Trigger Only Randy or the egneinerr team has access to deploy this.

Marketing URL Parameters

Marketers may collect campaign data through the website by using UTM values as outlined in this document

URL Query Parameter Options

Append to the end of a URL after a ? like ?utm_campaign=promocodeX

  • utm_campaign (explicit name of the campaign e.g. NextJSWordpress, promocodeX)
  • utm_medium (e.g. cpc, banner, email newsletter)
  • utm_source (e.g. google, newsletter17, billboard)
  • utm_term (keywords used in paid search)
  • persona (e.g. Developer, Marketer)

Usage

Not parameters must be all lowercase, one or more or none can be used. persona will always default to "marketer"

Material Icons

Using Icons in the WYSIWYG

The icons set we use is Google Material Icons https://fonts.google.com/icons

To use the icons in a WHYSIWYG editor, type in plain text ICON_icon_name e.g ICON_check use the link to the icons font aboe to learn icon names.

Using icons in React

For static icons main in the design

import LoginIcon from '@mui/icons-material/Login';

<LoginIcon>

Replace Login with the icon name.

For dynamic icons that come from the content editor

import Icon from '@mui/material/Icon';

<Icon>{icon_name}</Icon>;

For SEO renaming of component

variant = 'h4'; // Inherit Styles component = 'h2'; // DOM Element

Production VS Stage Logic

The content object has access to content.zestyProductionMode, a boolean value, true for prod, false for stage/dev.

Examples

Determining our bases domain for fetch

let zestyURL = content.zestyProductionMode
  ? process.env.zesty.production
  : process.env.zesty.stage;

Using our zesty custom useFetch command

const { data: latestArticles, isPending: latestPending } = useFetch(
  '/-/all-articles-hydrated.json?limit=5',
  content.zestyProductionMode,
);

Making template level decision (to show things like GTM or scripts)

{
  props.content.zestyProduction !== false && (
    <script
      dangerouslySetInnerHTML={{
        __html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});
      var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-MSPH3C8');`,
      }}
    />
  );
}

Working with Content from Zesty

Defaulting missing to content

See this example for loading dyanmic content and not breaking https://github.com/zesty-io/nextjs-website/blob/869acdd08836c74fd9f6a602eddd01a9073dcc11/src/views/zesty/About.js#L51

Using theme colors for custom styles

Example usage

import { useTheme } from '@mui/material';

const App = () => {
  const theme = useTheme();

  return <div style={{ color: theme.palette.primary.main }}>Hello World</div>;
};

using Styled Components or Emotion js

import styled from '@emotion/styled';
import { useTheme } from '@mui/material';

const CustomButton = styled.button`
  width: 100%;
  border-radius: 5px;
  background: ${(props) => props.theme.palette.primary.main};
  border: 1px solid ${(props) => props.theme.palette.zesty.zestyOrange};
`;

const App = () => {
  const theme = useTheme();

  return <CustomButton theme={theme}>Hello World</CustomButton>;
};

For more details you can browse to src/theme directory for complete list of themes.

โ”‚ย ย      โ””โ”€โ”€ PhoneSkeleton.js
โ”œโ”€โ”€ theme
โ”‚ย ย  โ”œโ”€โ”€ index.js
โ”‚ย ย  โ”œโ”€โ”€ palette.js
โ”‚ย ย  โ””โ”€โ”€ shadows.js
โ”œโ”€โ”€ utils
โ”‚ย ย  โ”œโ”€โ”€ index.js

Marketplace

To auto set the instance zuid, you can pass the query param ?instanceZUID=8-xyz-xyz to any page in the zesty.io website. This will auto set ZESTY_WORKING_INSTANCE and overwrite.

Available cookies

  • ZESTY_WORKING_INSTANCE - instance zuid for checking support, marketplace, docs, etc.
  • APP_SID - auth token

Github Data Fetching For Roadmap

Requirements

Must create .env file and add GITHUB_AUTH

GITHUB_AUTH="Personal Auth Token"

Github Personal Auth Token can be generated from https://github.com/settings/tokens

  • Make sure to set token to no expiration
  • Set Token scope to public_repo read:org read:discussion

Settings

settings can be found on pages/[...slug]

const settings = {
  organization: `"Zesty-io"`,
  projectNumber: data.project_number,
  columns: data.max_column,
  cards: data.max_card,
  discussions: data.max_discussion,
};
  • organization: Organization where the data should be pulled
  • ProjectNumber: Github Project ID
  • columns: Number of columns that can be shown to the page
  • cards: Number of cards that can be shown to the columns
  • discussion: Number of discussion can be shown to the discussion columns

These data can be updated or set from the CMS roadmap model

Updating Email Signature

To update the image and link of the email signature:

  1. Update the image in this repository located at public/assets/images/email-banner.png and push that through main (stage) and production branches
  2. Update the link in zesty manager under globals https://8-aaeffee09b-7w6v22.manager.zesty.io/content/6-984410-xnfd99/7-d60cd0-64nw39 there is a field named Email Announcement URL link: email_announcement_url save and publish the change

How it works is the image in the signature is pointed to a static image url reference which on zesty.io next site, which is https://www.zesty.io/assets/images/email-banner.png and the URL in the points to a custom parsley file that setups up a 301 redirect to the link edited in globals, this is the file https://8-aaeffee09b-7w6v22.manager.zesty.io/code/file/views/11-f49eb1abdb-h0nt9b https://www.zesty.io/email/annoucement-link.html

State Management

We use Zustand as state management. We wrap this in /src/store/index.js in function called useZestyStore. This is accessed by importing to the component, here is the example of the import:

import { useZestyStore } from 'store';

Currently, we store constants that allow us to engage in API and make decisions in the interface based upon user status. This includes user Auth state and user preferences.

  • isUser(boolean) checks if the visitor is the zesty user
  • isAuthenticated (boolean) check if the user has an active verified session
  • ZestyAPI(Object) is a global window object

Example of how we access the isUser in store

// isUser use to determined if the visitor is zesty user

import { useZestyStore } from 'store';

// this is how isUser is set
  setisUser: (data) => set((state) => ({ isUser: data })),
// how isUser is access
   const {  isUser } = useZestyStore((state) => state);

Using the ZestyAPI, a global Object that instantiates fetchwrapper

ZestyAPI is global and can be accessed through global state management, here is the example :

import { useZestyStore } from 'store';

const ZestyAPI = useZestyStore((state) => state.ZestyAPI);

console.log(ZestyAPI.verify(token));

ZestyAPI has two modes (development and production) which can be access using the .env file

Example for dev

PRODUCTION = false;

Working in this repo

Folder and file structure

  • Components should live in their specifics application folders
  • Shared or common component should live in the blocks folders
  • All images should be uploaded to the CDN with the exception of image-banner.png. SVG's may be committed to the repository, but it's suggested to upload them into CDN

Branch Deployment Flow

  • Any merge to main will auto deploy to stage (webengine)
  • Any merge to production will deploy to production (zesty.io)
  • Only the main branch when approved should be merge to production

Tests

Tests are located test, tests use the jest package. Tests are run like

npm run test

Jest is recommended testing tool for unit / integration testing by facebook , support async out of the box , has snapshot testing / coverage report , detect file with *.test.js/ *.spec.js and great community. Jest is implemented by installing the npm packages jest and react testing library then Jest has two file configuration which are jest.config.js and jest.setup.js. To begin testing with jest just run npm run test and it will find all files inside this directory that has filename matching this *.test.js/ *.spec.js and it will start the tests and after each test it will provide a summary in the console log whether the test is passed or failed.

Auto Deployment

  • Build time takes about 5 minutes
  • Auto deployment run through cloud run and cloud build integration with github
  • This occurs in the zesty-dev google cloud project

Component Error Handling

Given that our website receives data from a Zesty CMS, the marketing team or developer may occasionally attempt to make changes and might unintentionally delete content. This will fail reaching the specific object data from the CMS and the TypeError is born.

Server Error

TypeError: Cannot read property 'title' of undefined

Letโ€™s take a look of ways how can we avoid a webpage from crashing in production?

Ternary Operator Checks + Fallback Content

A best practice when attempting to retrieve object data from Zesty CMS is to carry out tests before to rendering the data and add fallback content in the event that the data is undefined or missing from Zesty CMS.

Example

content.title ? content.title : 'fallback title';

Here, we're attempting to determine whether the content.title object is empty; if it is, "fallback title" will be displayed on the screen.

Another way of writing the above statement is to use logical OR operator

content.title || 'fallback title';

Test against production environment

Zesty CMS gives you the option to work on stage and production endpoints when you are developing locally. You may switch between the two endpoints by changing your local env file.

Example Env

Production=true - Only returns data from the production endpoint that have been published by the zesty CMS

Production=false - only receives data that is saved or in a draft state but has not yet been published when using the staging endpoint

Most of the time when developing a website, you will use the staging endpoint and consume data that has not yet been published or in draft state. This will allow you to test the general functionality of the website using the CMS data without breaking the live or production site.

However, switching the env variable from staging to production is another excellent way to guarantee that your website won't break when you publish it to production. This will give you the ability to test the website using the production data, and if everything works perfectly, you're good to send your site to live.

Accounts

Accounts is instances, profile, teams, dashboard. To working on the accounts apps locally, follow these steps.

  1. You need to edit your ETC hosts files to use a domain like test.zesty.io to avoid CORS errors. To access your localhost see this thread for windows users zesty-io/manager-ui#1240
  2. Run npm run dev check your test.zesty.io domain, if that resolves to your next.js page, great, if not, googlefu
  3. Log into accounts.dev.zesty.io, refresh your localhost or test.zesty.io site

End to end test using Cypress

Cypress test files are located in root/cypress/integration/*.spec.js

Running Cypress Tests

Create cypress.json in root directory with the ff config

sample cypress config
{
  {
  "defaultCommandTimeout": 20000,
  "video": false,
  "env": {
    "user": {
      "email": "[email protected]",
      "password": "your_password"
    },
    "cypress-plugin-snapshots": {
      "autoCleanUp": false,
      "autopassNewSnapshots": true,
      "diffLines": 3,
      "excludeFields": [],
      "ignoreExtraArrayItems": false,
      "ignoreExtraFields": false,
      "normalizeJson": true,
      "prettier": true,
      "imageConfig": {
        "createDiffImage": true,
        "resizeDevicePixelRatio": true,
        "threshold": 0.01,
        "thresholdType": "percent"
      },
      "screenshotConfig": {
        "blackout": [],
        "capture": "fullPage",
        "clip": null,
        "disableTimersAndAnimations": true,
        "log": false,
        "scale": false,
        "timeout": 30000
      },
      "serverEnabled": true,
      "serverHost": "localhost",
      "serverPort": 2121,
      "updateSnapshots": false,
      "backgroundBlend": "difference"
    }
  },
  "ignoreTestFiles": ["**/__snapshots__/*", "**/__image_snapshots__/*"],
  "viewportWidth": 1280,
  "viewportHeight": 720
}
}

Headlessly

npm run test:e2e:ci

Visually

npm run dev in 1st terminal and npm run cy:open in 2nd terminal then click the test you want to run.

Uploading Assets

To upload assets for your projects put them on the CDN, do not put them in the repository. Assets can be uploaded at https://console.cloud.google.com/storage/browser/assets.zesty.io?project=zesty-prod , upload to the respective folder that match your project name, for example, the SVGs and PNG that are being commited to website should be moved into this storage bucket under the website folder, once they are uploaded they accessible from https://assets.zesty.io e.g. https://assets.zesty.io/website/assets/images/dxp_bottom_bg.svg

  • open algolia.js file in src/pages/api/algolia.js
  • specify the data and index
  • pass it in algoliaFunc
  • run the app npm run dev
  • perform a GET request in this url http://localhost:3000/api/algolia

website's People

Contributors

allenpigar avatar ardeay avatar bltarkany avatar d88naimi avatar darwin808 avatar giseleblair avatar glespinosa avatar jeromezestyio avatar jomarmontuya avatar shrunyan avatar smserpa avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

website's Issues

Blog - pagination

Blog pagination should sort newest --> oldest, so newest articles show first.

blog/mindshare - case studies

Need to only show 2 case studies when selecting and then "view all" needs to display all articles tagged to "customer stories"

image

Developer Resources

  • Links need to open in new tab
  • Make links text that says something like "see more" or "learn more" (editable) that are hyperlinked, instead of showing full URL

image

Why Zesty - proof in numbers

  • Remove boundary boxes from each card and spread out so that the margins match the text margins of the rest of the page.
  • Make sure icons pull through

image

blog/mindshare - pagination

Can we make pagination sticky to the top of the "latest articles" section so that when you click from page 1 to 2, etc., you end up at the top of that section instead of the bottom (having to scroll back up is annoying).

Homepage - case studies

I want to be able to customize the image & copy on these cards instead of just pulling exactly what's on the article. Can we change how these are pulling?

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.