diff --git a/public/images/codesamples.png b/public/images/codesamples.png
new file mode 100644
index 000000000..6df4b9ab3
Binary files /dev/null and b/public/images/codesamples.png differ
diff --git a/public/navigation.json b/public/navigation.json
index 8055429cc..067539f10 100644
--- a/public/navigation.json
+++ b/public/navigation.json
@@ -10060,6 +10060,13 @@
"type": "markdown",
"children": []
},
+ {
+ "name": "Code samples and templates",
+ "slug": "code-samples",
+ "origin": "",
+ "type": "markdown",
+ "children": []
+ },
{
"name": "Getting Started",
"slug": "vtex-io-getting-started",
@@ -14998,4 +15005,4 @@
]
}
]
-}
+}
\ No newline at end of file
diff --git a/src/components/code-sample-card/index.tsx b/src/components/code-sample-card/index.tsx
new file mode 100644
index 000000000..01360f2d3
--- /dev/null
+++ b/src/components/code-sample-card/index.tsx
@@ -0,0 +1,58 @@
+import { Box, Flex, Text, IconCaret, Link } from '@vtex/brand-ui'
+
+import type { CodeSamplesElement } from 'utils/typings/types'
+
+import styles from './styles'
+
+const CodeSampleCard = ({
+ title,
+ description,
+ builders,
+ linkTo,
+ repoLink,
+ category,
+}: CodeSamplesElement) => {
+ return (
+
+
+ {category && {category}}
+
+ {title}
+
+
+ {description}
+
+
+ {builders.map((builder) => (
+ {builder}
+ ))}
+
+
+
+ View GitHub repository
+
+
+
+
+ {linkTo && (
+
+
+
+
+ View documentation
+
+
+
+
+
+ )}
+
+ )
+}
+
+export default CodeSampleCard
diff --git a/src/components/code-sample-card/styles.ts b/src/components/code-sample-card/styles.ts
new file mode 100644
index 000000000..bcd526f05
--- /dev/null
+++ b/src/components/code-sample-card/styles.ts
@@ -0,0 +1,124 @@
+import type { SxStyleProp } from '@vtex/brand-ui'
+
+const container: SxStyleProp = {
+ flexDirection: 'column',
+ justifyContent: 'space-between',
+ fontSize: '14px',
+ mt: '16px',
+ borderRadius: '4px',
+ border: '1px solid #E7E9EE',
+ width: ['100%', '49%'],
+ transition: 'all 0.3s ease-out',
+ ':active, :hover': {
+ borderColor: 'muted.2',
+ boxShadow: '0px 0px 16px rgba(0, 0, 0, 0.1)',
+ transition: 'all 0.3 ease-out',
+
+ '.title, .description': {
+ transition: 'all 0.3s ease-out',
+ color: '#000711',
+ },
+
+ '.link, .caret': {
+ transition: 'all 0.3s ease-out',
+ color: 'muted.0',
+ },
+ },
+}
+
+const innerContent: SxStyleProp = {
+ padding: '16px',
+}
+
+const category: SxStyleProp = {
+ textTransform: 'uppercase',
+ fontWeight: '600',
+ fontSize: '12px',
+ letterSpacing: '0.8px',
+ color: '#a1a8b3',
+ mb: '10px',
+}
+
+const title: SxStyleProp = {
+ mb: '6px',
+ fontSize: '16px',
+ fontWeight: 'bold',
+ lineHeight: '22px',
+ color: 'muted.0',
+}
+
+const description: SxStyleProp = {
+ fontSize: '1.05em',
+ fontWeight: '400',
+ color: 'muted.0',
+ maxHeight: '82px',
+}
+
+const ctaLink: SxStyleProp = {
+ padding: '12px 0',
+ maxHeight: '56px',
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderTop: '1px solid #E7E9EE',
+ borderBottomLeftRadius: '8px',
+ borderBottomRightRadius: '8px',
+ transition: 'all 0.3s ease-out',
+ '.ctaLinkText': {
+ transition: 'all 0.3s ease-out',
+ },
+ ':active, :hover': {
+ backgroundColor: '#F8F7FC',
+ transition: 'all 0.3s ease-out',
+ '.ctaLinkText': {
+ color: '#000711',
+ transition: 'all 0.3s ease-out',
+ },
+ },
+}
+
+const ctaLinkText: SxStyleProp = {
+ fontSize: '1.1em',
+ fontWeight: '400',
+ color: 'muted.0',
+}
+
+const linkContainer: SxStyleProp = {
+ alignItems: 'center',
+}
+
+const link: SxStyleProp = {
+ mt: '10px',
+ color: 'muted.1',
+ textDecoration: 'underline',
+ ':hover': {
+ color: '#e31d58 !important',
+ },
+}
+
+const builderList: SxStyleProp = {
+ display: 'flex',
+ gap: '8px',
+ mt: '10px',
+ flexWrap: 'wrap',
+}
+
+const builderListItem: SxStyleProp = {
+ bg: 'muted.3',
+ px: '6px',
+ borderRadius: '4px',
+ display: 'inline',
+}
+
+export default {
+ container,
+ innerContent,
+ title,
+ description,
+ link,
+ linkContainer,
+ builderList,
+ builderListItem,
+ ctaLink,
+ ctaLinkText,
+ category,
+}
diff --git a/src/components/code-sample-section/index.tsx b/src/components/code-sample-section/index.tsx
new file mode 100644
index 000000000..cf2912ffd
--- /dev/null
+++ b/src/components/code-sample-section/index.tsx
@@ -0,0 +1,40 @@
+import { useState } from 'react'
+import { Box, Flex } from '@vtex/brand-ui'
+
+import { codeSamples } from 'utils/constants'
+
+import styles from 'styles/documentation-landing-page'
+import Multiselect from 'components/multiselect'
+import { SelectOption } from 'utils/typings/types'
+import CodeSampleCard from 'components/code-sample-card'
+
+interface ICodeSamplesSection {
+ builders: SelectOption[]
+}
+
+const CodeSamplesSection = ({ builders }: ICodeSamplesSection) => {
+ const [filter, setFilter] = useState([])
+ const filteredCodeSamples = codeSamples.filter(
+ (codeSampleItem) =>
+ filter.length === 0 ||
+ filter.some((option) => codeSampleItem.builders.includes(option.label))
+ )
+ return (
+
+ {
+ setFilter(selection)
+ }}
+ />
+
+ {filteredCodeSamples.map((codeSample) => (
+
+ ))}
+
+
+ )
+}
+
+export default CodeSamplesSection
diff --git a/src/components/icons/github-icon.tsx b/src/components/icons/github-icon.tsx
index 3e595ada8..95b7baab9 100644
--- a/src/components/icons/github-icon.tsx
+++ b/src/components/icons/github-icon.tsx
@@ -13,7 +13,7 @@ const GithubIcon = (props: IconProps) => (
fillRule="evenodd"
clipRule="evenodd"
d="M14.4 16.7314C10.6667 20.7314 8 26.3314 8 33.5314C8 38.8647 9.86667 43.9314 12.8 47.9314C16.2667 52.4647 21.3333 55.1314 24 56.198V54.3314C24 54.3314 24 50.0647 26.4 46.3314C21.0667 46.0647 16.8 40.998 16.8 35.1314C16.8 32.998 17.6 31.1314 18.9333 29.5314L19.2 24.4647C19.2 23.1314 20.5333 22.3314 21.8667 22.598L27.4667 24.7314C29.0667 24.4647 30.6667 24.198 32.5333 24.198C34.4 24.198 36 24.4647 37.6 24.7314L42.4 22.3314C43.7333 21.798 45.0667 22.8647 45.0667 24.198L45.3333 29.2647C46.6667 30.8647 47.4667 32.998 47.4667 34.8647C47.4667 40.7314 43.2 45.5314 37.8667 46.0647C40.2667 49.798 40.2667 54.0647 40.2667 54.0647V55.9314C42.9333 54.8647 48 52.198 51.4667 47.6647C54.4 43.9314 56.2667 38.598 56.2667 33.2647C56.2667 26.0647 53.6 20.4647 49.8667 16.4647C44.8 11.398 37.8667 8.99805 32 8.99805C26.1333 8.99805 19.2 11.398 14.4 16.7314V16.7314Z"
- stroke="#4A596B"
+ stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
diff --git a/src/components/multiselect/styles.ts b/src/components/multiselect/styles.ts
index a81178ab8..5a02de382 100644
--- a/src/components/multiselect/styles.ts
+++ b/src/components/multiselect/styles.ts
@@ -14,11 +14,12 @@ const multiselect: SxStyleProp = {
}
const input: SxStyleProp = {
- padding: '8px 12px 7px',
+ fontSize: '15px',
+ padding: '8px 12px 4px',
background: '#F4F4F4',
borderRadius: '4px',
justifyContent: 'space-between',
- width: '230px',
+ width: '150px',
cursor: 'pointer',
}
@@ -38,6 +39,9 @@ const dropdown: SxStyleProp = {
const optionsContainer: SxStyleProp = {
flexDirection: 'column',
+ overflowY: 'auto',
+ maxHeight: '35vh',
+ width: '256px',
}
const checkbox: SxStyleProp = {
@@ -48,12 +52,14 @@ const checkbox: SxStyleProp = {
}
const option: SxStyleProp = {
+ fontSize: '15px',
columnGap: '8px',
padding: '8px 0px',
}
const buttonsContainer: SxStyleProp = {
- marginTop: '10px',
+ marginTop: '14px',
+ justifyContent: 'flex-end',
}
export default {
diff --git a/src/pages/docs/guides/code-samples.tsx b/src/pages/docs/guides/code-samples.tsx
new file mode 100644
index 000000000..b2df7fa77
--- /dev/null
+++ b/src/pages/docs/guides/code-samples.tsx
@@ -0,0 +1,89 @@
+import PageHeader from 'components/page-header'
+import { getMessages } from 'utils/get-messages'
+import image from '../../../../public/images/codesamples.png'
+import Head from 'next/head'
+import CodeSamplesSection from 'components/code-sample-section'
+import getNavigation from 'utils/getNavigation'
+import { codeSamples } from 'utils/constants'
+import { CodeSamplesElement, SelectOption } from 'utils/typings/types'
+import { GetStaticProps, NextPage } from 'next'
+import { PreviewContext } from 'utils/contexts/preview'
+import { useContext } from 'react'
+import { DocumentationTitle, UpdatesTitle } from 'utils/typings/unionTypes'
+
+interface Props {
+ sidebarfallback: any //eslint-disable-line
+ sectionSelected?: DocumentationTitle | UpdatesTitle | ''
+ builders: SelectOption[]
+ branch: string
+}
+
+const AppDevelopmentPage: NextPage = ({ builders, branch }) => {
+ const { setBranchPreview } = useContext(PreviewContext)
+ setBranchPreview(branch)
+ const messages = getMessages()
+ return (
+ <>
+
+ Code Samples
+
+
+
+
+ <>
+
+
+ >
+ >
+ )
+}
+
+export const getStaticProps: GetStaticProps = async ({
+ preview,
+ previewData,
+}) => {
+ const sidebarfallback = await getNavigation()
+ const sectionSelected = 'App Development'
+ const previewBranch =
+ preview && JSON.parse(JSON.stringify(previewData)).hasOwnProperty('branch')
+ ? JSON.parse(JSON.stringify(previewData)).branch
+ : 'main'
+ const branch = preview ? previewBranch : 'main'
+
+ function getBuilders(samples: CodeSamplesElement[]) {
+ const uniqueBuilders: Map = new Map()
+
+ for (const sample of samples) {
+ sample.builders.forEach((builder) => {
+ uniqueBuilders.set(builder, builder) // Using Map to ensure uniqueness
+ })
+ }
+
+ return Array.from(uniqueBuilders, ([id, label]) => ({ id, label }))
+ }
+
+ const builders: SelectOption[] = getBuilders(codeSamples)
+
+ return {
+ props: {
+ sidebarfallback,
+ sectionSelected,
+ builders,
+ branch,
+ },
+ }
+}
+
+export default AppDevelopmentPage
diff --git a/src/styles/global.css b/src/styles/global.css
index ce6e44454..b286f7dad 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -178,10 +178,16 @@ hr {
width: 40% !important;
}
-.ch-editor-frame > div{
+.ch-scrollycoding .ch-editor-frame > div{
height: 20px;
}
+@media screen and (max-width: 40em) {
+ .ch-scrollycoding .ch-editor-frame > div{
+ height: auto;
+ }
+}
+
body {
--ch-scrollycoding-sticker-width: 40%;
--ch-scrollycoding-code-min-height: 80vh;
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 829a4545a..09d4f3811 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -21,6 +21,7 @@ import {
DocDataElement,
UpdatesDataElement,
WhatsNextDataElement,
+ CodeSamplesElement,
ResourceDataElement,
AdminDataElement,
} from './typings/types'
@@ -177,3 +178,218 @@ export const resources: ResourceDataElement[] = [
link: getSupportURL(),
},
]
+
+export const codeSamples: CodeSamplesElement[] = [
+ {
+ title: 'React app',
+ description:
+ 'Create custom React-based apps for your Store Theme with internationalization support.',
+ builders: ['react', 'messages'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-1-developing-storefront-apps-using-react-and-vtex-io',
+ category: 'Frontend',
+ repoLink: 'https://github.com/vtex-apps/react-app-template',
+ },
+ {
+ title: 'Service',
+ description: 'Leverage Node.js to implement custom route handling logic.',
+ builders: ['node'],
+ linkTo:
+ 'https://learn.vtex.com/docs/course-calling-commerce-apis-step01introduction-lang-en',
+ category: 'Backend',
+ repoLink: 'https://github.com/vtex-apps/service-example',
+ },
+ {
+ title: 'Pixel app',
+ description:
+ 'Run scripts in your store website to integrate with third-party solutions and services.',
+ builders: ['react', 'store', 'pixel'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-1-developnativeintegrationswithpixelapps',
+ category: 'Scripts',
+ repoLink: 'https://github.com/vtex-apps/pixel-app-template',
+ },
+ {
+ title: 'Scripts app',
+ description:
+ 'Run VTEX IO scripts in Legacy CMS stores using a custom Scripts app.',
+ builders: ['scripts'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-running-io-scripts-in-non-io-vtex-stores#step-1-developing-your-app',
+ category: 'Scripts',
+ repoLink: 'https://github.com/vtex-apps/app-scripts-example',
+ },
+ {
+ title: 'Store Theme',
+ description:
+ 'Jumpstart the development of Store Themes with this predefined template.',
+ builders: ['styles', 'store', 'sitemap'],
+ linkTo: 'https://developers.vtex.com/docs/guides/getting-started-3',
+ category: 'Store Framework',
+ repoLink: 'https://github.com/vtex-apps/store-theme',
+ },
+ {
+ title: 'Minimum Store Theme',
+ description:
+ 'Jumpstart the development of Store Themes with this minimum template.',
+ builders: ['styles', 'store'],
+ linkTo: 'https://learn.vtex.com/docs/course-basic-blocks-lang-en',
+ category: 'Store Framework',
+ repoLink: 'https://github.com/vtex-apps/minimum-boilerplate-theme',
+ },
+ {
+ title: 'Store Theme robots',
+ description: "Customize your cross-border store's robots.txt files.",
+ builders: ['sitemap'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-creating-robots-files-for-cross-border-stores',
+ category: 'Store Framework',
+ repoLink: 'https://github.com/vtex-apps/store-theme-robots',
+ },
+ {
+ title: 'Edition App',
+ description:
+ 'Streamline the setup of a group of VTEX accounts by creating your own Edition App.',
+ builders: ['edition'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-configuring-an-edition-app',
+ category: 'Edition App',
+ repoLink: 'https://github.com/vtex-apps/edition-hello',
+ },
+ {
+ title: 'Carrier Hubs - Tracking',
+ description: 'Obtain tracking events from custom carriers.',
+ builders: ['node', 'vtex.carrier-tracking'],
+ linkTo: 'https://developers.vtex.com/docs/guides/tracking-1',
+ category: 'Fulfillment',
+ repoLink:
+ 'https://github.com/vtex-apps/carrier-hubs-examples/tree/main/carrier-tracking-example',
+ },
+ {
+ title: 'Carrier Hubs - Notifier',
+ description: 'Notify custom carriers about a dispatch order.',
+ builders: ['node', 'vtex.carrier-notifier'],
+ linkTo: 'https://developers.vtex.com/docs/guides/notification-1',
+ category: 'Fulfillment',
+ repoLink:
+ 'https://github.com/vtex-apps/carrier-hubs-examples/tree/main/carrier-notifier-example',
+ },
+ {
+ title: 'Payment app',
+ description:
+ "Provide an additional verification step in your store's checkout process.",
+ builders: ['react', 'pages', 'messages'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/payments-integration-payment-app',
+ category: 'Payments',
+ repoLink: 'https://github.com/vtex-apps/example-payment-authorization-app',
+ },
+ {
+ title: 'Payment Provider Framework',
+ description: 'Integrate custom payment providers into your VTEX store.',
+ builders: ['paymentProvider', 'node'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/payments-integration-payment-provider-framework',
+ category: 'Payments',
+ repoLink: 'https://github.com/vtex-apps/payment-provider-example',
+ },
+ // {
+ // title: 'Service Worker',
+ // description:
+ // 'Offload network requests to a service worker for improved performance.',
+ // builders: ['service-worker'],
+ // repoLink: 'https://github.com/vtex-apps/service-worker-example',
+ // },
+ // {
+ // title: 'React app',
+ // description:
+ // 'Create custom React and GraphQL-based apps for your Store Theme.',
+ // builders: ['store', 'react', 'messages'],
+ // linkTo: 'https://learn.vtex.com/docs/course-store-block-lang-en',
+ // linkTitle: 'See guide',
+ // repoLink: 'https://github.com/vtex-trainings/store-block-template',
+ // },
+ {
+ title: 'Search Segment resolver',
+ description:
+ 'Segment the search result page to present custom results for each shopper.',
+ builders: ['node'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/vtex-io-documentation-segmenting-the-search-result',
+ category: 'Search',
+ repoLink: 'https://github.com/vtex-apps/search-segment-resolver',
+ },
+ {
+ title: 'Search GraphQL Resolver',
+ description:
+ 'Extend VTEX search capabilities with external search providers.',
+ builders: ['node'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/external-search-provider-recipe',
+ category: 'Search',
+ repoLink: 'https://github.com/vtex-apps/search-resolver',
+ },
+ {
+ title: 'External Marketplace Integration app',
+ description: 'Integrate with external marketplaces.',
+ builders: ['react', 'messages', 'node', 'admin', 'graphql'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/external-marketplace-integration-app-template',
+ category: 'Marketplace',
+ repoLink: 'https://github.com/vtex/mkp-app-template',
+ },
+ {
+ title: 'Orders Feed',
+ description: 'Handle status updates from the Orders Feed.',
+ builders: ['node'],
+ linkTo:
+ 'https://developers.vtex.com/docs/guides/how-to-receive-order-notifications-on-vtex-io',
+ category: 'Orders',
+ repoLink: 'https://github.com/vtex-apps/orders-feed-example',
+ },
+ {
+ title: 'Events service',
+ description: 'Trigger events based on specific actions.',
+ builders: ['node'],
+ repoLink: 'https://github.com/vtex-apps/events-example',
+ category: 'Backend',
+ },
+
+ {
+ title: 'GraphQL app',
+ description: 'Jumpstart the development of a GraphQL service.',
+ builders: ['node', 'graphql'],
+ repoLink: 'https://github.com/vtex-apps/graphql-example',
+ category: 'Backend',
+ },
+
+ {
+ title: 'Admin app',
+ description:
+ 'Build a tailored frontend app for the VTEX Admin using React.',
+ builders: ['admin', 'messages', 'react'],
+ repoLink: 'https://github.com/vtex/admin-ui-example',
+ category: 'Admin',
+ },
+ {
+ title: 'Checkout UI Settings',
+ description: "Customize the user interface of your store's Checkout.",
+ builders: ['checkout-ui-custom'],
+ repoLink: 'https://github.com/vtex-apps/checkout-ui-settings',
+ category: 'Checkout',
+ },
+ {
+ title: 'Buyer Organization Supplier app',
+ description: 'Save custom data from a Buyer Organization to Master Data.',
+ builders: ['node'],
+ repoLink: 'https://github.com/vtex-apps/buyer-org-supplier',
+ category: 'B2B',
+ },
+ // {
+ // title: 'Delivery Theme',
+ // description: 'DESC',
+ // builders: ['store', 'styles'],
+ // linkTo: 'https://developers.vtex.com/',
+ // repoLink: 'https://github.com/vtex-apps/delivery-theme',
+ // },
+]
diff --git a/src/utils/typings/types.ts b/src/utils/typings/types.ts
index 21e9a355b..479981838 100644
--- a/src/utils/typings/types.ts
+++ b/src/utils/typings/types.ts
@@ -50,6 +50,15 @@ export type WhatsNextDataElement = {
linkTo: string
}
+export type CodeSamplesElement = {
+ title: string
+ description: string
+ builders: string[]
+ category: string
+ linkTo?: string
+ repoLink: string
+}
+
export type ResourceDataElement = {
title: ResourceTitle
description: string