{"id":28273187,"url":"https://github.com/zesty-io/website","last_synced_at":"2025-07-19T06:06:30.898Z","repository":{"id":37087748,"uuid":"459407974","full_name":"zesty-io/website","owner":"zesty-io","description":"Marketing Website using NextJS and Zesty.io Headless CMS","archived":false,"fork":false,"pushed_at":"2025-06-11T15:06:40.000Z","size":33885,"stargazers_count":18,"open_issues_count":33,"forks_count":3,"subscribers_count":5,"default_branch":"stage","last_synced_at":"2025-06-17T21:45:38.477Z","etag":null,"topics":["cms","nextjs","react","zesty-io"],"latest_commit_sha":null,"homepage":"https://www.zesty.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zesty-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-15T03:06:21.000Z","updated_at":"2025-06-10T19:15:24.000Z","dependencies_parsed_at":"2023-09-22T08:44:24.128Z","dependency_job_id":"2e4953e6-ca1a-4a8a-af41-104ceba58cd0","html_url":"https://github.com/zesty-io/website","commit_stats":null,"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/zesty-io/website","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesty-io%2Fwebsite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesty-io%2Fwebsite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesty-io%2Fwebsite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesty-io%2Fwebsite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zesty-io","download_url":"https://codeload.github.com/zesty-io/website/tar.gz/refs/heads/stage","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesty-io%2Fwebsite/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265896112,"owners_count":23845426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","nextjs","react","zesty-io"],"created_at":"2025-05-21T00:17:31.885Z","updated_at":"2025-07-19T06:06:30.887Z","avatar_url":"https://github.com/zesty-io.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://brand.zesty.io/zesty-io-logo.svg\" width=\"150\"\u003e\n\u003ch1\u003e\nZesty.io NextJS Marketing Website\n\u003c/h1\u003e\n\u003ci\u003e\n\nMarketing Website using NextJS and Zesty.io Headless CMS\n\n\u003c/i\u003e\n\n\u003ca href=\"https://github.com/zesty-io/website/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/zesty-io/website?style=flat-square\u0026\u0026color=F4CE01\" alt=\"Stars Badge\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/zesty-io/website/pulls\"\u003e\u003cimg src=\"https://img.shields.io/github/issues-pr/zesty-io/website?style=flat-square\u0026\u0026color=4DC71F\" alt=\"Pull Requests Badge\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/zesty-io/website/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/zesty-io/website?style=flat-square\u0026\u0026color=F88304\" alt=\"Issues Badge\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/zesty-io/website/graphs/contributors\"\u003e\u003cimg alt=\"GitHub contributors\" src=\"https://img.shields.io/github/contributors/zesty-io/website?color=9B1FE9\u0026\u0026style=flat-square\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/zesty-io/website/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/package-json/dependency-version/zesty-io/website/react?style=flat-square\u0026\u0026color=5ED3F3\" alt=\"License Badge\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/zesty-io/website/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/package-json/dependency-version/zesty-io/website/next?style=flat-square\" alt=\"License Badge\"/\u003e\u003c/a\u003e\n\n\u003ca href=\"https://github.com/zesty-io/website/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/MUI-%230081CB.svg?style=flat-square\u0026logo=mui\u0026logoColor=white\" alt=\"License Badge\"/\u003e\u003c/a\u003e\n\n\u003c/div\u003e\n\n## ⚡ Getting Started\n\nRequires `node version ^18.x.x` and `npm version ^8.x.x`\n\nCreate a file at the root `.env.local` with `PRODUCTION=false` as the file contents\n\n```bash\ngit clone git@github.com:zesty-io/website.git\n\ncd website\n\nnpm install\n\nnpm run dev\n\n## open browser to http://localhost:3000/\n\n```\n\n## 💡 Syncing Zesty.io Content Models to Next JS\n\nFrom the command line at the root of the project run:\n\n```jsx\nnode scripts/zesty-nextjs.js\n```\n\nThis will create new files where needed, but will not overwrite existing files.\n\n## 💡 AutoDeploy Overview\n\n### Branch Deployment Behavior:\n\n- **`dev` Branch:** Use for testing purposes; feel free to modify as needed.\n- **`stage` Branch:** Review and thoroughly test changes before moving to `pre-prod (beta)`.\n- **`accounts` Branch (pre-production, beta):** Configuration mirrors `production`.\n- **`production` Branch:** Merge from `accounts` after confirming stage readiness.\n\n### Preview Links:\n\n- **`dev`:** [Zesty.dev](https://zesty-dev-website-m3rbwjxm5q-uc.a.run.app/)\n- **`stage`:** [WebEngine Stage](https://kfg6bckb-dev.webengine.zesty.io) OR [Zesty Stage](https://zesty-website-m3rbwjxm5q-uc.a.run.app/)\n- **`accounts` (beta):** [Beta Zesty.io](https://beta.zesty.io)\n- **`production`:** [Zesty.io](https://www.zesty.io) OR [Zesty Production](https://zesty-website-production-m3rbwjxm5q-uc.a.run.app/)\n\nThis setup automates deployment upon any push or merge to `dev`, `stage`, or `production` branches. Each branch serves a specific purpose, with accessible preview links for respective environments.\n\n## 💡 Contribution Process\n\n1. **Create a Branch:** Start by creating a new branch for your changes.\n2. **Make Local Changes:** Edit and commit your changes locally.\n3. **Test Changes:** Verify your changes locally using `npm run build`.\n4. **Create Pull Request:** If the local build succeeds, create a pull request targeting the `stage` branch (our staging environment).\n\n## 💡 Deployment to Production Workflow\n\nAfter successfully deploying changes to the `stage` branch, follow these steps:\n\n1. **Create PR to `production`:** Initiate a pull request from `stage` to `production`.\n2. **Merge to Trigger Production Build:** Upon merging the pull request, an automatic production build will be triggered.\n\nThis workflow ensures that changes are thoroughly tested in the staging environment (`stage` branch) before being merged into the production environment (`production` branch). It maintains a structured process for contributing changes and deploying them to production.\n\n## 💡 CTA Components and Forms\n\nPlease use these core CTA components through your views. These forms already have validation setup and connect to our remote services.\n\n### 💡 Try Button\n\nA button that trigger a dropdown guiding both a developer and marketers option\n\n`\u003cTryFreeButton\u003e` [View Try Free Button Component](src/components/cta/TryFreeButton.js)\n\n### Standard Form\n\nA Form that posts to our CRM and has many option to controls inputs\n\n`\u003cStandardFormWithSelect\u003e` [View Standard Form Component](src/components/cta/StandardFormWithSelect.js)\n\n### Subscribe Form\n\nA simple form that asks for user email\n\n`\u003cSubscribeCTA\u003e` [View Subscribe Component](src/components/cta/SubscribeCTA.js)\n\n### Developer Codeblock Starter\n\nA one-line code block that shows developer how to start from the command line\n\n`\u003cCodeBlock\u003e` [View Code Block Component](src/components/cta/CodeBlock.js)\n\n## Lead Capture\n\nAll lead capture funnels from the above components into one of two cloud functions which connect to ZOHO CRM.\n\n1. Marketing Subscribe: [GCP Link](https://console.cloud.google.com/functions/details/us-central1/zohoEmailSubscribe?env=gen1\u0026project=zesty-dev) [Github Link](https://github.com/zesty-io/gcp-cf/blob/940b2d71144feb66dffe3b405137c334c595f869/zoho/index.js#L65) [Trigger](https://us-central1-zesty-dev.cloudfunctions.net/zohoEmailSubscribe) Both Gisele and Randy have access to deploy this.\n2. Lead Capture: [GCP Link](https://console.cloud.google.com/functions/details/us-central1/zoho?env=gen1\u0026project=zesty-prod) [Github Link](https://github.com/zesty-io/gcp-cf/blob/master/zoho/index.js) [Trigger](https://us-central1-zesty-prod.cloudfunctions.net/zoho) Only Randy or the egneinerr team has access to deploy this.\n\n## Marketing URL Parameters\n\nMarketers may collect campaign data through the website by using `UTM` values as outlined [in this document](https://support.google.com/analytics/answer/1033863?hl=en#zippy=%2Cin-this-article)\n\n**URL Query Parameter Options**\n\nAppend to the end of a URL after a `?` like `?utm_campaign=promocodeX`\n\n- `utm_campaign` (explicit name of the campaign e.g. NextJSWordpress, promocodeX)\n- `utm_medium` (e.g. cpc, banner, email newsletter)\n- `utm_source` (e.g. google, newsletter17, billboard)\n- `utm_term` (keywords used in paid search)\n- `persona` (e.g. Developer, Marketer)\n\n**Usage**\n\nNot parameters must be all lowercase, one or more or none can be used. `persona` will always default to \"marketer\"\n\n- https://www.zesty.io/?utm_campaign=NextJSWordpress\u0026persona=developer\u0026utm_source=nextjswebsite\u0026utm_medium=paid%20advertising\n- https://www.zesty.io/?utm_campaign=NextJSWordpress\u0026persona=developer\u0026utm_source=adwords\u0026utm_medium=ppc\u0026utm_term=nextjs\n- https://www.zesty.io/?persona=developer\n- https://www.zesty.io/?utm_term=jquery\u0026persona=developer\n\n## Material Icons\n\n### Using Icons in the WYSIWYG\n\nThe icons set we use is Google Material Icons https://fonts.google.com/icons\n\nTo 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.\n\n### Using icons in React\n\n**For static icons main in the design**\n\n```jsx\nimport LoginIcon from '@mui/icons-material/Login';\n\n\u003cLoginIcon\u003e\n```\n\nReplace Login with the icon name.\n\n**For dynamic icons that come from the content editor**\n\n```jsx\nimport Icon from '@mui/material/Icon';\n\n\u003cIcon\u003e{icon_name}\u003c/Icon\u003e;\n```\n\n**For SEO renaming of component**\n\n```jsx\nvariant = 'h4'; // Inherit Styles component = 'h2'; // DOM Element\n```\n\n# Production VS Stage Logic\n\nThe `content` object has access to `content.zestyProductionMode`, a boolean value, true for prod, false for stage/dev.\n\n## Examples\n\n### Determining our bases domain for fetch\n\n```jsx\nlet zestyURL = content.zestyProductionMode\n  ? process.env.zesty.production\n  : process.env.zesty.stage;\n```\n\n### Using our zesty custom useFetch command\n\n```jsx\nconst { data: latestArticles, isPending: latestPending } = useFetch(\n  '/-/all-articles-hydrated.json?limit=5',\n  content.zestyProductionMode,\n);\n```\n\n### Making template level decision (to show things like GTM or scripts)\n\n```jsx\n{\n  props.content.zestyProduction !== false \u0026\u0026 (\n    \u003cscript\n      dangerouslySetInnerHTML={{\n        __html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});\n      var f=d.getElementsByTagName(s)[0],\nj=d.createElement(s),dl=l!='dataLayer'?'\u0026l='+l:'';j.async=true;j.src=\n'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n})(window,document,'script','dataLayer','GTM-MSPH3C8');`,\n      }}\n    /\u003e\n  );\n}\n```\n\n# Working with Content from Zesty\n\n## Defaulting missing to content\n\nSee this example for loading dyanmic content and not breaking\nhttps://github.com/zesty-io/nextjs-website/blob/869acdd08836c74fd9f6a602eddd01a9073dcc11/src/views/zesty/About.js#L51\n\n# Using theme colors for custom styles\n\n## Example usage\n\n```jsx\nimport { useTheme } from '@mui/material';\n\nconst App = () =\u003e {\n  const theme = useTheme();\n\n  return \u003cdiv style={{ color: theme.palette.primary.main }}\u003eHello World\u003c/div\u003e;\n};\n```\n\nusing Styled Components or Emotion js\n\n```jsx\nimport styled from '@emotion/styled';\nimport { useTheme } from '@mui/material';\n\nconst CustomButton = styled.button`\n  width: 100%;\n  border-radius: 5px;\n  background: ${(props) =\u003e props.theme.palette.primary.main};\n  border: 1px solid ${(props) =\u003e props.theme.palette.zesty.zestyOrange};\n`;\n\nconst App = () =\u003e {\n  const theme = useTheme();\n\n  return \u003cCustomButton theme={theme}\u003eHello World\u003c/CustomButton\u003e;\n};\n```\n\nFor more details you can browse to `src/theme` directory for complete list of themes.\n\n```\n│       └── PhoneSkeleton.js\n├── theme\n│   ├── index.js\n│   ├── palette.js\n│   └── shadows.js\n├── utils\n│   ├── index.js\n\n```\n\n# Marketplace\n\nTo 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.\n\n_Available cookies_\n\n- ZESTY_WORKING_INSTANCE - instance zuid for checking support, marketplace, docs, etc.\n- APP_SID - auth token\n\n# Github Data Fetching For Roadmap\n\n## Requirements\n\nMust create `.env` file and add `GITHUB_AUTH`\n\n```\nGITHUB_AUTH=\"Personal Auth Token\"\n```\n\nGithub `Personal Auth Token` can be generated from https://github.com/settings/tokens\n\n- Make sure to set token to no expiration\n- Set Token scope to `public_repo` `read:org` `read:discussion`\n\n### Settings\n\nsettings can be found on `pages/[...slug]`\n\n```jsx\nconst settings = {\n  organization: `\"Zesty-io\"`,\n  projectNumber: data.project_number,\n  columns: data.max_column,\n  cards: data.max_card,\n  discussions: data.max_discussion,\n};\n```\n\n- `organization`: Organization where the data should be pulled\n- `ProjectNumber`: Github Project ID\n- `columns`: Number of columns that can be shown to the page\n- `cards`: Number of cards that can be shown to the columns\n- `discussion`: Number of discussion can be shown to the discussion columns\n\nThese data can be updated or set from the CMS `roadmap` model\n\n# Updating Email Signature\n\nTo update the image and link of the email signature:\n\n1. Update the image in this repository located at [public/assets/images/email-banner.png](https://github.com/zesty-io/nextjs-website/blob/main/public/assets/images/email-banner.png) and push that through main (stage) and production branches\n2. 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\n\nHow 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\n\n# State Management\n\nWe use [Zustand](https://github.com/pmndrs/zustand) as state management. We wrap this in [/src/store/index.js](/src/store/index.js) in function called `useZestyStore`. This is accessed by importing to the component, here is the example of the import:\n\n```jsx\nimport { useZestyStore } from 'store';\n```\n\nCurrently, 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.\n\n- `isUser`(boolean) checks if the visitor is the zesty user\n- `isAuthenticated` (boolean) check if the user has an active verified session\n- `ZestyAPI`(Object) is a global window object\n\n## Example of how we access the `isUser` in store\n\n```jsx\n// isUser use to determined if the visitor is zesty user\n\nimport { useZestyStore } from 'store';\n\n// this is how isUser is set\n  setisUser: (data) =\u003e set((state) =\u003e ({ isUser: data })),\n// how isUser is access\n   const {  isUser } = useZestyStore((state) =\u003e state);\n```\n\n## Using the ZestyAPI, a global Object that instantiates fetchwrapper\n\n[ZestyAPI](https://github.com/zesty-io/fetch-wrapper) is global and can be accessed through global state management, here is the example :\n\n```jsx\nimport { useZestyStore } from 'store';\n\nconst ZestyAPI = useZestyStore((state) =\u003e state.ZestyAPI);\n\nconsole.log(ZestyAPI.verify(token));\n```\n\nZestyAPI has two modes (development and production) which can be access using the .env file\n\nExample for dev\n\n```jsx\nPRODUCTION = false;\n```\n\n# Working in this repo\n\n## Folder and file structure\n\n- Components should live in their specifics application folders\n- Shared or common component should live in the blocks folders\n- 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\n\n## Branch Deployment Flow\n\n- Any merge to `main` will auto deploy to stage (webengine)\n- Any merge to `production` will deploy to `production` (zesty.io)\n- Only the `main` branch when approved should be merge to `production`\n\n### Tests\n\nTests are located `test`, tests use the jest package. Tests are run like\n\n```\nnpm run test\n```\n\n[Jest](https://github.com/facebook/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.\n\n## Auto Deployment\n\n- Build time takes about 5 minutes\n- Auto deployment run through cloud run and cloud build integration with github\n- This occurs in the zesty-dev google cloud project\n\n# Component Error Handling\n\nGiven 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.\n\n##### Server Error\n\n`TypeError: Cannot read property 'title' of undefined`\n\nLet’s take a look of ways how can we avoid a webpage from crashing in production?\n\n### Ternary Operator Checks + Fallback Content\n\nA 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.\n\n##### Example\n\n`content.title ? content.title : 'fallback title';`\n\nHere, we're attempting to determine whether the `content.title` object is empty; if it is, \"fallback title\" will be displayed on the screen.\n\nAnother way of writing the above statement is to use logical OR operator\n\n`content.title || 'fallback title';`\n\n### Test against production environment\n\nZesty 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.\n\n##### Example Env\n\n`Production=true` - Only returns data from the production endpoint that have been published by the zesty CMS\n\n`Production=false` - only receives data that is saved or in a draft state but has not yet been published when using the staging endpoint\n\nMost 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.\n\nHowever, 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.\n\n# Accounts\n\nAccounts is instances, profile, teams, dashboard. To working on the accounts apps locally, follow these steps.\n\n1. 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 https://github.com/zesty-io/manager-ui/discussions/1240\n2. Run `npm run dev` check your `test.zesty.io` domain, if that resolves to your next.js page, great, if not, googlefu\n3. Log into accounts.dev.zesty.io, refresh your localhost or test.zesty.io site\n\n# End to end test using Cypress\n\nCypress test files are located in `root/cypress/integration/*.spec.js`\n\n## Running Cypress Tests\n\nCreate `cypress.json` in root directory with the ff config\n\n\u003cdetails\u003e\n\u003csummary\u003e\nsample cypress config\n\u003c/summary\u003e\n\n```jsx\n\n{\n  {\n  \"defaultCommandTimeout\": 20000,\n  \"video\": false,\n  \"env\": {\n    \"user\": {\n      \"email\": \"your_email@zesty.io\",\n      \"password\": \"your_password\"\n    },\n    \"cypress-plugin-snapshots\": {\n      \"autoCleanUp\": false,\n      \"autopassNewSnapshots\": true,\n      \"diffLines\": 3,\n      \"excludeFields\": [],\n      \"ignoreExtraArrayItems\": false,\n      \"ignoreExtraFields\": false,\n      \"normalizeJson\": true,\n      \"prettier\": true,\n      \"imageConfig\": {\n        \"createDiffImage\": true,\n        \"resizeDevicePixelRatio\": true,\n        \"threshold\": 0.01,\n        \"thresholdType\": \"percent\"\n      },\n      \"screenshotConfig\": {\n        \"blackout\": [],\n        \"capture\": \"fullPage\",\n        \"clip\": null,\n        \"disableTimersAndAnimations\": true,\n        \"log\": false,\n        \"scale\": false,\n        \"timeout\": 30000\n      },\n      \"serverEnabled\": true,\n      \"serverHost\": \"localhost\",\n      \"serverPort\": 2121,\n      \"updateSnapshots\": false,\n      \"backgroundBlend\": \"difference\"\n    }\n  },\n  \"ignoreTestFiles\": [\"**/__snapshots__/*\", \"**/__image_snapshots__/*\"],\n  \"viewportWidth\": 1280,\n  \"viewportHeight\": 720\n}\n}\n\n```\n\n\u003c/details\u003e\n\n### Headlessly\n\n`npm run test:e2e:ci`\n\n### Visually\n\n`npm run dev` in 1st terminal and `npm run cy:open` in 2nd terminal then click the test you want to run.\n\n## Uploading Assets\n\nTo 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\n\n## Adding Data to Algolia Search\n\n- open `algolia.js` file in `src/pages/api/algolia.js`\n- specify the `data` and `index`\n- pass it in `algoliaFunc`\n- run the app `npm run dev`\n- perform a `GET` request in this url `http://localhost:3000/api/algolia`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzesty-io%2Fwebsite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzesty-io%2Fwebsite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzesty-io%2Fwebsite/lists"}