{"id":25190244,"url":"https://github.com/sucodev/vtex-faststore","last_synced_at":"2025-04-04T11:26:00.232Z","repository":{"id":186037536,"uuid":"584930609","full_name":"sucodev/vtex-faststore","owner":"sucodev","description":"VTEX Fast Store","archived":false,"fork":false,"pushed_at":"2023-01-03T22:09:18.000Z","size":1119,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-09T21:19:32.323Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/github/sucodev/vtex-faststore","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sucodev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-01-03T22:09:10.000Z","updated_at":"2023-01-16T20:05:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"7a7dad76-b00a-4678-8c8f-b2ae9c80f3ff","html_url":"https://github.com/sucodev/vtex-faststore","commit_stats":null,"previous_names":["sucodev/vtex-faststore"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sucodev%2Fvtex-faststore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sucodev%2Fvtex-faststore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sucodev%2Fvtex-faststore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sucodev%2Fvtex-faststore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sucodev","download_url":"https://codeload.github.com/sucodev/vtex-faststore/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247168020,"owners_count":20895038,"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":[],"created_at":"2025-02-09T21:19:38.032Z","updated_at":"2025-04-04T11:26:00.203Z","avatar_url":"https://github.com/sucodev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/vtex/faststore\"\u003e\n    \u003cimg alt=\"Store Framework\" src=\"https://emoji.slack-edge.com/T02BCPD0X/store-framework/7547b127e929c376.png\" width=\"75\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003ch1 align=\"center\"\u003e\n  A starter powered by FastStore and NextJS\n\u003c/h1\u003e\n\nKickoff your store with this boilerplate. This starter ships with the main FastStore configuration files you might need to get up and running blazing fast with the blazing-fast store for React.\n\n## ⚠️ Before you start\n\nAs of Dec, 22, 2021, this starter is still far from covering most basic cases found on VTEX. To summarize what we still do not support that is considered basic on the VTEX commerce platform, we prepared the list below. If the feature you want is listed, you can either wait for us to add support to the feature, or fork the repo and implement on your own. Note that, by forking the repo, you will miss new features and improvements we do in this repo and you will need a developer to backport the feature to your store. Finally, this list is a work in progress, so some features may be missing from both base.store starter and this list.\n\n1. Multiple CMS Previews. Only one user is allowed to preview content from the CMS at a time. If two users preview any content from any page at the CMS, the previews are not consistent and one user may see data from the other.\n2. Price Table\n3. Regionalization\n4. Internationalization\n5. Shared Cart (Carrinho compartilhado)\n6. Clear products that are our of stock from cart\n7. GDPR (LGDP)\n8. Shipping simulation\n9. Sitemap\n10. Sku selector on PDP\n11. Promotions via utm\n12. Product specifications\n\n## 🚀 Quick start\n\n0. **Clone this repo**\n\n   Get up and running by cloning this repo.\n\n   ```shell\n   # Clone this repo into your machine\n   npx degit vtex-sites/nextjs.store awesome.store\n   ```\n\n1. **Install dependencies**\n\n   Install dependencies with yarn\n\n   ```shell\n   cd awesome.store/\n   yarn\n   ```\n\n2. **Setup store.config.js**\n\n   Choose the ecommerce platform provider of your choice in the `store.config` file and set the corresponding options. For instance, to connect to the VTEX platform on the store `fashioneurope`:\n\n   ```js\n   module.exports = {\n     platform: 'vtex',\n\n     api: {\n       storeId: 'fashioneurope'\n       environment: 'vtexcommercestable'\n     }\n   }\n   ```\n\n3. **Start developing**\n\n   Navigate into your new site’s directory and start it up.\n\n   ```shell\n   yarn develop\n   ```\n\n4. **Open the source code and start editing!**\n\n   Your site is now running at `http://localhost:3000`!\n\n    Open the `awesome.store` directory in your code editor of choice and edit `src/pages/index.tsx`. Save your changes and the browser will update in real-time!\n\n## :technologist: Contributing\n\n1. **Keep the CHANGELOG updated**\n   We use a CHANGELOG to keep the history of all notable changes made to this repository.\n   Each PR must have at least one entry on the `[UNRELEASED]` section of the `CHANGELOG.md` file.\n\n## 🧐 What's inside?\n\nA quick look at the top-level files and directories you'll see in a NextJS project.\n\n    ./\n    ├── node_modules\n    ├── src\n    ├── .gitignore\n    ├── .eslintignore\n    ├── .prettierignore\n    ├── .prettierrrc\n    ├── .eslintrc\n    ├── LICENSE\n    └── yarn.lock\n    ├── package.json\n    ├── tsconfig.json\n    ├── store.config.js\n    ├── README.md\n    ├── CHANGELOG.md\n    ├── __generated__\n    ├── babel.config.js\n    ├── cypress\n    ├── cypress.json\n    ├── lighthouserc.js\n    ├── public\n    ├── pull_request_template.md\n    ├── renovate.json\n\n1.  **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.\n\n2.  **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.\n\n3.  **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.\n\n4.  **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.\n\n5.  **`.eslintrc.js`**: This is a configuration file for [ESLint](https://eslint.org/). ESlint is a tool to find and fix problems in your JavaScript code.\n\n6.  **`LICENSE`**: NextJS is licensed under the MIT license.\n\n7.  **`yarn.lock`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).**\n\n8. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project.\n\n9. **`tsconfig.json`**: The configuration file for the typescript compiler. This will statically analyze your code for errors and bugs before releasing them into production\n\n10. **`store.config.js`**: Configure your e-commerce platform, default sales channel etc.\n\n11. **`README.md`**: A text file containing useful reference information about your project.\n\n12. **`CHANGELOG.md`**: A text file containing all notable changes to the project.\n\n13. **`__generated__`**: Where TypeScript typings are generated for your GraphQL queries. You can use these files for strongly typing your App\n\n14. **`babel.config.js`**: [Babel configurations](https://babeljs.io/docs/en/configuration#babelrcjson) for you app. This is where you can change the targeted browsers.\n\n15. **`cypress`**: End to End(e2e) tests using Cypress. Most of the scenarios are covered here. Add your custom flows to avoid regressions\n\n16. **`cypress.json`**: [Cypress configuration file](https://docs.cypress.io/guides/references/configuration)\n\n17. **`lighthouserc.js`**: Configures [Google Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci). This is where you can turn on/off lighthouse assertions to be used by Lighthouse CI Bot/hook\n\n18. **`pull_request_template.md`**: Template used when creating your Pull Requests\n\n19. **`renovate.json`**: Renovate configuration file to keep your store always fresh with FastStore's latest versions\n\n20. **`.prettierignore`**: Ignore listed files when applying prettier rules\n\n21. **`.eslintignore`**: Ignore listed files when applying eslint rules\n\n## 💻 Code Structure\n\nAll code is inside the `src` folder. The code is split into folders that implement an MVC-like architecture.\n\nThe `controller` is inside the `src/sdk` folder. This is where you will find most logic for the application. This folder contains hooks for adding items to cart, making graphql queries, resizing images, etc. If you need to write a custom business logic this is probably the place to put this logic.\n\nThe `views` are written in the `src/components` folder and are subdivided into domain-specific components. Cart related items are inside the `src/components/cart` folder. Search and Product related components like facets, product summary, and search results are in their respective folders. Basic building blocks components are inside the UI folder. Components like button, checkbox, and modal are good candidates for the UI folder.\nSection components are those components that occupy a whole slice on the webpage and are desirable to be changed by a CMS. Section components are Product Gallery, Carousel, Shelf and Product description.\n\nThe `model`, in a website, is where the data fetching occurs. Since this project uses Jamstack, a crucial design decision was made to explicitly split where Static and Dynamic data are fetched. The files inside the `src/pages` folder use [NextJS's File System Route API](https://nextjs.org/docs/routing/introduction) to declare routes and fetch static data.\n\nTo summarize:\n\n1. `src/pages`: Routes are declared and static data is fetched.\n2. `src/views`: Receives static data from `src/pages`, enriches this data with dynamic attributes, and render section components along with SEO tags.\n3. `src/components/sections`: Receives necessary data and use domain-specific components (cart/product/search/ui) for rendering a slice on the web page.\n\n## ✏️ Adding Components\n\nWhat better than an example for learning the best practices while adding components? In this example, we will add a button component.\nComponents live on the `src/components` folder. Each component may have, at most, 3 files: a component file, an export file, and a styling file.\nFirst, let's create a folder and the files.\n\n```sh\nmkdir src/components/ui/Button\ntouch src/components/ui/Button/Button.tsx\ntouch src/components/ui/Button/index.tsx\n```\n\nThe `index.tsx` is just an export file, so its content is simple:\n\n```tsx\nexport { default } from './Button'\n```\n\nThe real thing happens on `Button.tsx`. On this file let's define the component like:\n\n```tsx\ninterface Props {}\n\nfunction Button(props: Props) {\n  return \u003cbutton {...props} /\u003e\n}\n\nexport default Button\n```\n\nAnd, that's it! Now you have a working button that you can use anywhere on your project. FastStore, however, brings a handy library called `@faststore/ui` with built-in components to help you speed up your development. To use it, just change `Button.tsx` to:\n\n```tsx\nimport { Button as UIButton } from '@faststore/ui'\nimport type { ButtonProps } from '@faststore/ui'\n\ninterface Props extends ButtonProps {}\n\nfunction Button(props: Props) {\n  return \u003cUIButton {...props} /\u003e\n}\n\nexport default Button\n```\n\nNow, your Button component is powered by Store UI. However, if you try to use this on your app you will see that the button is lacking styles. To add styles, we will use CSS modules because they allow us to target data attributes. On your terminal, type:\n\n```sh\ntouch src/components/ui/Button/button.scss\n```\n\nNow, on `button.scss`:\n\n```css\n[data-store-button] {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n}\n```\n\nThis `data-store-button` is a CSS data attribute selector. To know which selectors are available, check [FastStore UI docs](https://faststoreui.netlify.app/).\n\nNow, include the component's CSS into the Store's CSS. Open `src/styles/global/components.scss` and import this CSS with:\n\n```scss\n// ...\n@import \"src/components/ui/Button/button.scss\";\n// ...\n```\n\nFor most components, you would stop here. However, buttons can have different variants. For instance, suppose you want to have a button component with primary and secondary variants. To add variants to the component, update `Button.tsx`:\n\n```tsx\nimport { Button as UIButton } from '@faststore/ui'\nimport type { ButtonProps } from '@faststore/ui'\n\ninterface Props extends ButtonProps {\n  variant: 'secondary' | 'primary'\n}\n\nfunction Button({ variant, ...props }: Props) {\n  return \u003cUIButton data-button-variant={variant} {...props} /\u003e\n}\n\nexport default Button\n```\n\nand then, on `button.scss`:\n\n```css\n[data-store-button][data-button-variant='primary'] {\n  background: blue;\n}\n\n[data-store-button][data-button-variant='secondary'] {\n  background: pink;\n}\n```\n\nYou can also use classes, if you wanted to:\n\n```tsx\nfunction Button({ variant, ...props }: Props) {\n  return \u003cUIButton className={variant} {...props} /\u003e\n}\n```\n\n```css\n.primary[data-store-button] {\n  background: blue;\n}\n\n.secondary[data-store-button] {\n  background: pink;\n}\n```\n\nNow we have a styled Button component that accepts different variants!! 🎉\nThe aforementioned guide works well for UI components. However, components like `Navbar` and `Footer` are more complex and usually don't have variants, since they usually serve a single responsibility on the page. For these cases, you can use [BEM-Style CSS Syntax in SCSS](https://en.bem.info/methodology/) like:\n\n```tsx\n // components/common/Navbar/Navbar.tsx\n ...\n function Navbar {\n   return (\n      \u003cheader className=\"navbar\"\u003e\n        \u003cdiv className=\"navbar__header\"\u003e\n         \u003csection className=\"navbar__row\"\u003e\n           \u003cButton\n               className=\"navbar__menu\"\n               aria-label=\"Open Menu\"\n           \u003e\n             \u003cListIcon size={32} /\u003e\n           \u003c/Button\u003e\n         \u003c/section\u003e\n        \u003c/div\u003e\n      \u003c/header\u003e\n   )\n```\n\n### Managing SVG Icons\nIcons help build web pages by illustrating concepts and improving website navigation. However, using icons can decrease the page's performance. One option to avoid the decrease of the page's performance is to use SVGs from a single SVG file, located in `/static/icons.svg`, and load them with the `ui/Icon` component.\n\nIn the following steps, learn how to add and use a new SVG icon and avoid decreasing page performance while using an icon.\n\n\u003e ⚠️ Warning\n\u003e\n\u003e This is a recommendation while using icons on a web page. Evaluate if this fits in your project.\n\n#### Adding an SVG icon\n1. In the SVG file, change the `svg` tag to `symbol`.\n2. Add an `id` to the symbol. Remember to use an unique `id` and do not replicate it.\n3. Remove unnecessary HTML/SVG properties to allow you to style and decrease the final file size, such as `fill`, `stroke-width`, `width`, `height`, and `color`.\n\nAn example adding Bell icon:\n\n```svg\n\u003csvg style=\"display:none\"\u003e\n\u003csymbol id=\"Bell\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"\u003e\u003crect width=\"256\" height=\"256\" fill=\"none\"\u003e\u003c/rect\u003e\u003cpath d=\"M56.2,104a71.9,71.9,0,0,1,72.3-72c39.6.3,71.3,33.2,71.3,72.9V112c0,35.8,7.5,56.6,14.1,68a8,8,0,0,1-6.9,12H49a8,8,0,0,1-6.9-12c6.6-11.4,14.1-32.2,14.1-68Z\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003c/path\u003e\u003cpath d=\"M96,192v8a32,32,0,0,0,64,0v-8\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003c/path\u003e\u003c/symbol\u003e\n\u003c/svg\u003e\n```\n\n#### Using an SVG icon\n\n1. Get the icon's `id` that you created in the SVG icon file.\n2. Add the `id` in the React component that you desire to use the SVG icon. For example\n\n```tsx\n// src/components/ui/MyIconButton/MyIconButton.tsx\nimport Icon from 'src/components/ui/Icon' // this path can be outdated.\n\nfunction ButtonIcon() {\n  return (\n    \u003cbutton\u003e\n      \u003cIcon name=\"\u003c\u003csymbol_id\u003e\u003e\" weight=\"thin\" /\u003e\n    \u003c/button\u003e\n  )\n}\n\nexport default ButtonIcon\n```\n\nThis project uses SVGs from [Phosphor icons](https://phosphoricons.com/).\n\n## 🖊️ Styling Components\n\nOur customized themes are based on [Design Tokens](https://css-tricks.com/what-are-design-tokens/) using [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) or a CSS class for each token. Today, we have the following files in the `src/styles` folder:\n\n### `tokens.scss`\n\nHere you'll find the basic structure to build your theme (font base, color palette, spacing, color-text, body background color...), feel free to update it with your brand guidelines.\n\n#### \u003cb\u003eColors\u003c/b\u003e\n\nWe suggest using a color palette of 3 colors and its gradation: `primary`, `secondary` and `neutral`.\n\nWe also listed a couple of customizable tokens so you can easily change your body background, for example.\n\nIf you feel the need to edit some of the color decisions, you can enter `tokens.scss` and update the semantical tokens. E.g.:\n\n```scss\n--fs-border-color: var(--fs-color-neutral-4); // Current\n--fs-border-color: var(--fs-color-neutral-5); // Updated\n```\n\n#### \u003cb\u003eTypography\u003c/b\u003e\n\nWe use the [Modular Scale](https://www.modularscale.com/) setting to create our text-sizes. If you want to change it, just set the `--fs-text-size-base` and the `scale` ratio.\n\n#### \u003cb\u003eSpacing\u003c/b\u003e\n\nThe spacing scale is based on `rem` sizes, so it will remain consistent if you change the `--fs-text-size-base`.\n\n### `layout.scss`\n\nList of classes used to create default page grid.\n\n```scss\n.layout__content-full // Should be used for sections that are side to side, generally with a colored background.\n.layout__content // Should be used for sections that fit centered on the grid.\n.layout__section // This class only adds default vertical margins for page sections.\n```\n\n![grid-example-image](https://user-images.githubusercontent.com/3356699/150801221-4027dc6a-1cc4-40a7-a323-8be7a148458d.png)\n\n### `typography.scss`\n\nFor the typography-related styles, we decided to use classes to add extra stylings like `font-weight` and `line-height`. In this file, you'll see all the classes for titles, paragraphs, and default settings on the body. You can create new ones here if needed.\n\n## 🍒 Adding queries\n\nWe use [graphql-codegen](https://www.graphql-code-generator.com/) to pre-process GraphQL queries. This compilation generates TypeScript typings and configurations for our graphql server under the folder `@generated/graphql`.\nThis means we can statically analyse your code in search of bugs and secure your graphql server before each deploy. If, however you need to change any GraphQL Fragment, Query or Mutation, you will need to regenerate the whole thing. To do this, open your terminal and type\n\n```sh\n$ yarn develop\n```\n\nNow, after the nextjs development server is up and running, open another terminal and run\n\n```sh\n$ yarn generate\n```\n\nThat's it! you have just regenerated all graphql queries/fragments for your application and the new data you requested should be available to your component.\n\n\u003e Pro tip: Pass `-w` to the `yarn generate` command so it watches for changes and you don't need to run this command multiple times\n\n## 🎓 Learning the Frameworks\n\nLooking for more guidance? Full documentation for FastStore lives [on this GitHub repository](https://github.com/vtex/faststore). Also, for learning NextJS, take a look at the [NextJS Website](https://nextjs.org/docs/getting-started), they have plenty of tutorials and examples in there.\n\n## ⚡ Performance \u0026 QA\n\nThis project has strict performance budgets. Right out of the box, this project performs around 95 on Google's Page Speed Insights website, which usually is way more strict than your laptop's chrome lighthouse. Every time you commit to the repository, our QA bots will run and evaluate your code quality. We recommend you NEVER put in production a code that breaks any of the bots. If a bot breaks and still you need to put the code into production, change the bot config (`lighthouserc.js`, `cypress.json`) to make it pass and merge. This way you ensure your website will keep performing well during the years to come.\n\n## Adding third party scripts\n\nAdding third-party scripts to a webpage usually makes it slow. To maintain great performance while third-party scripts are added, this project uses [Partytown](https://github.com/BuilderIO/partytown/), a lazy-load library that helps relocate intensive scripts into a web worker and off of the main thread.\n\nTo add scripts using Partytown, add the `type=\"text/partytown\"` to the script tag and make sure to add it before the Partytown script or component.\nSome third-party scripts execute expensive computations that may require some time to run, making pages few slow. If that's the case, wrap those in a function and reference it on the Partytown `forward` prop. By doing this, Partytown will run this function on a web worker so it doesn't block the main thread.\n\n```tsx\nexport const onRenderBody = ({ setHeadComponents }) =\u003e {\n  // ...\n  setHeadComponents([\n    \u003cscript type=\"text/partytown\"\u003e\n      window.expensiveFunction = function() {/* expensive computation used by custom-script */}\n    \u003c/script\u003e\n    \u003cscript key=\"custom-script\" src=\"*://domain/path\" type=\"text/partytown\" /\u003e,\n    \u003cPartytown key=\"partytown\" forward={[\"expensiveFunction\"]} /\u003e\n  ])\n  // ...\n}\n```\n\nFor more information about integrating third-party scripts: [Partytown Wiki](https://github.com/BuilderIO/partytown/wiki)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsucodev%2Fvtex-faststore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsucodev%2Fvtex-faststore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsucodev%2Fvtex-faststore/lists"}