Forked from matheusps/gist:57d7f943c53c724949d027f3f807c459
Created
March 2, 2026 14:51
-
-
Save vmarcosp/0872a83fba0d1fa4e4842c8341da801a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: FastCheckout to FastStore Migration | |
| overview: Migrate the entire FastCheckout application (NestJS BFF + Next.js/Relay client + UI libraries) into a set of FastStore pages, sections, API extensions, and custom components, preserving all checkout features (cart, delivery, payment, review, order placed, sign-in, payment loading). | |
| todos: | |
| - id: bff-typedefs | |
| content: Create all GraphQL type definitions (.graphql files) in src/graphql/vtex/typeDefs/ for each checkout domain (cart, auth, payment, shipping, order, summary, coupon, customer, delivery, pickup, simulation, account-settings, store-preferences, custom-fields, dynamic-fields, one-click-checkout, budget, permissions) | |
| status: pending | |
| - id: bff-clients | |
| content: "Create VTEX API client modules for services not covered by FastStore's native clients: VtexIdentityClient, VtexPaymentsClient, VtexWalletHubClient, VtexMasterDataClient, VtexBudgetClient, GoogleMapsClient" | |
| status: pending | |
| - id: bff-resolvers | |
| content: Convert all 25 NestJS resolver classes to plain GraphQL resolver objects in src/graphql/vtex/resolvers/, wiring them to the new client modules and FastStore's existing ctx.clients | |
| status: pending | |
| - id: api-route | |
| content: Modify FastStore's /api/graphql route to forward checkout-specific headers (x-order-form-id, x-fastcheckout-user-date-time) and handle checkout cookie management | |
| status: pending | |
| - id: checkout-pages | |
| content: Create all checkout pages under pages/checkout/ (index, cart, delivery, payment, review, order-placed/[orderId], payment-loading, sign-in) using getServerSideProps and RenderSections | |
| status: pending | |
| - id: sdk-hooks | |
| content: Create SWR-based checkout hooks in src/sdk/checkout/ (useCheckoutCart, useCheckoutShipping, useCheckoutPayment, useCheckoutOrder, useCheckoutAuth, useCheckoutSummary, useCheckoutCoupon, useCheckoutCustomer) replacing Relay queries/mutations | |
| status: pending | |
| - id: shared-components | |
| content: Build shared checkout components (Summary, Breadcrumb/StepIndicator, AddressForm, CardForm, PaymentOptionIcon) using FastStore UI components and SCSS modules | |
| status: pending | |
| - id: cart-screen | |
| content: "Migrate Cart screen: convert Cart.tsx and subcomponents to FastStore section, replacing FC UI components with FastStore equivalents, Vanilla Extract with SCSS modules" | |
| status: pending | |
| - id: delivery-screen | |
| content: "Migrate Delivery screen: convert to FastStore section with address forms, shipping SLA selectors, pickup point search, using FastStore components" | |
| status: pending | |
| - id: payment-screen | |
| content: "Migrate Payment screen: convert payment option selector, credit card form, saved cards, gift cards, installments to FastStore sections" | |
| status: pending | |
| - id: review-screen | |
| content: "Migrate Review screen: convert order review display with delivery, payment, and cart summaries to FastStore section" | |
| status: pending | |
| - id: order-placed-screen | |
| content: "Migrate OrderPlaced screen: convert order confirmation page to FastStore section" | |
| status: pending | |
| - id: remaining-screens | |
| content: "Migrate remaining screens: SignIn, PaymentLoading, CartPunchout (B2B) to FastStore sections" | |
| status: pending | |
| - id: form-libs | |
| content: "Migrate address-form and card-ui libraries: create react-hook-form wrapper components that integrate with FastStore InputField, SelectField, CheckboxField" | |
| status: pending | |
| - id: utils-migration | |
| content: Copy utility libraries (validators, input-mask, constants, i18n) into src/customizations/src/utils/ | |
| status: pending | |
| - id: styling-migration | |
| content: Convert all Vanilla Extract styles (*.css.ts) to SCSS modules (*.module.scss) using FastStore design tokens (--fs-*) and component data attributes | |
| status: pending | |
| - id: config-update | |
| content: Update discovery.config to point checkoutUrl to /checkout/cart, update redirectToCheckout to use internal navigation, and add checkout-specific configuration | |
| status: pending | |
| - id: cms-sections | |
| content: Create CMS section definitions in cms/faststore/sections.json for all checkout sections and sync with Headless CMS | |
| status: pending | |
| isProject: false | |
| --- | |
| # FastCheckout to FastStore Full Migration | |
| ## Architecture Overview | |
| The FastCheckout app is a standalone checkout with a **NestJS BFF** (GraphQL via Mercurius, ~25 resolver modules, ~10 VTEX API clients) and a **Next.js/Relay client** (8 checkout screens, 20+ UI components, Vanilla Extract styling). It must become a native part of FastStore using FastStore's extension points. | |
| ```mermaid | |
| flowchart TB | |
| subgraph currentArch [Current Architecture] | |
| FC_Client["FastCheckout Client\n(Next.js + Relay)"] | |
| FC_BFF["FastCheckout BFF\n(NestJS + Mercurius)"] | |
| VTEX["VTEX APIs"] | |
| FC_Client -->|"GraphQL\n/api/checkout-bff/graphql"| FC_BFF | |
| FC_BFF --> VTEX | |
| end | |
| subgraph targetArch [Target Architecture] | |
| FS_Pages["FastStore Checkout Pages\n(/checkout/cart, /delivery, etc.)"] | |
| FS_BFF["FastStore API Route\n(/api/graphql)"] | |
| FS_Resolvers["VTEX Extension Resolvers\n(src/graphql/vtex/)"] | |
| VTEX2["VTEX APIs"] | |
| FS_Pages -->|"SWR + GraphQL\n/api/graphql"| FS_BFF | |
| FS_BFF --> FS_Resolvers | |
| FS_Resolvers --> VTEX2 | |
| end | |
| currentArch -.->|"Migration"| targetArch | |
| ``` | |
| ## 1. BFF Migration Strategy | |
| The NestJS BFF (`fastcheckout/packages/apps/server/`) must be converted to FastStore's VTEX API extension system. FastStore supports extending its GraphQL schema via: | |
| - **TypeDefs**: `.graphql` files in `src/graphql/vtex/typeDefs/` | |
| - **Resolvers**: `.ts` files in `src/graphql/vtex/resolvers/` | |
| ### 1.1 TypeDefs Migration | |
| Create `.graphql` files in `[faststore/packages/core/src/customizations/src/graphql/vtex/typeDefs/](faststore/packages/core/src/customizations/src/graphql/vtex/typeDefs/)` for each domain: | |
| | FastCheckout Module | New TypeDef File | Key Types | | |
| | ------------------- | ------------------------------------ | ------------------------------------------------------------------------------ | | |
| | Cart | `checkout-cart.graphql` | `CheckoutCart`, `CheckoutCartItem`, mutations for add/remove/update items | | |
| | Auth | `checkout-auth.graphql` | `CheckoutAuth`, `AuthProvider`, login/logout mutations | | |
| | Payment | `checkout-payment.graphql` | `CheckoutPayment`, `PaymentOption`, `SavedCard`, `GiftCard`, installment types | | |
| | Shipping | `checkout-shipping.graphql` | `CheckoutShipping`, `DeliveryOption`, `PickupPoint`, address types | | |
| | Order | `checkout-order.graphql` | `CheckoutOrder`, place order mutations, transaction types | | |
| | Summary | `checkout-summary.graphql` | `CheckoutSummary`, totals | | |
| | Coupon | `checkout-coupon.graphql` | `CheckoutCoupon`, add/remove coupon mutations | | |
| | Customer | `checkout-customer.graphql` | `CheckoutCustomer`, profile data | | |
| | Delivery | `checkout-delivery.graphql` | Delivery-specific types, SLA selection | | |
| | Pickup | `checkout-pickup.graphql` | Pickup point search, selection | | |
| | Simulation | `checkout-simulation.graphql` | Shipping simulation types | | |
| | AccountSettings | `checkout-account-settings.graphql` | Store checkout settings | | |
| | StorePreferences | `checkout-store-preferences.graphql` | Store preferences | | |
| | CustomFields | `checkout-custom-fields.graphql` | Custom field definitions and values | | |
| | DynamicFields | `checkout-dynamic-fields.graphql` | Dynamic fields | | |
| | OneClickCheckout | `checkout-one-click.graphql` | One-click checkout options | | |
| | GiftCard | (in payment) | Gift card add/remove | | |
| | Budget | `checkout-budget.graphql` | Budget allocation (B2B) | | |
| | Permissions | `checkout-permissions.graphql` | Permission checks (B2B) | | |
| All new types should be prefixed with `Checkout` to avoid collisions with existing FastStore types. Extend `Query` and `Mutation` with new root fields prefixed with `checkout_` (e.g., `checkout_cart`, `checkout_placeOrder`). | |
| ### 1.2 Resolvers Migration | |
| Create resolver files in `[faststore/packages/core/src/customizations/src/graphql/vtex/resolvers/](faststore/packages/core/src/customizations/src/graphql/vtex/resolvers/)`: | |
| **VTEX API Clients**: The NestJS client services (`[fastcheckout/packages/apps/server/src/client/](fastcheckout/packages/apps/server/src/client/)`) must be rewritten as plain functions or classes that can be instantiated within FastStore resolver context. FastStore resolvers receive a `ctx` with `ctx.clients.commerce` (which has `checkout`, `session`, `profile`, `oms` sub-clients). For APIs not covered by FastStore's native clients (e.g., Payments, WalletHub, MasterData, Identity, LicenseManager), create new client modules. | |
| **Resolver structure**: Each NestJS resolver class becomes a plain resolver object: | |
| ```typescript | |
| // src/graphql/vtex/resolvers/checkoutCart.ts | |
| const checkoutCartResolver = { | |
| Query: { | |
| checkout_cart: async (_, args, ctx) => { /* ... */ }, | |
| }, | |
| Mutation: { | |
| checkout_addProduct: async (_, args, ctx) => { /* ... */ }, | |
| checkout_removeProduct: async (_, args, ctx) => { /* ... */ }, | |
| checkout_changeQuantity: async (_, args, ctx) => { /* ... */ }, | |
| }, | |
| } | |
| export default checkoutCartResolver | |
| ``` | |
| **Key client mappings**: | |
| | NestJS Client | FastStore Equivalent | | |
| | ------------------------------ | ------------------------------------------------------------------------------------- | | |
| | `CheckoutClientService` | `ctx.clients.commerce.checkout` (partial) + new custom client for remaining endpoints | | |
| | `SessionClientService` | `ctx.clients.commerce.session` | | |
| | `CatalogClientService` | `ctx.clients.commerce.catalog` | | |
| | `IdentityClientService` | New `VtexIdentityClient` | | |
| | `PaymentsClientService` | New `VtexPaymentsClient` | | |
| | `WalletHubClientService` | New `VtexWalletHubClient` | | |
| | `MasterDataClientService` | New `VtexMasterDataClient` | | |
| | `AccountSettingsClientService` | New custom client | | |
| | `LicenseManagerClientService` | `ctx.clients.commerce.licenseManager` (if available) or new client | | |
| | `BudgetClientService` | New `VtexBudgetClient` | | |
| | `GoogleMapsClientService` | New `GoogleMapsClient` | | |
| **Context handling**: The NestJS BFF extracts `accountName`, `orderFormId`, `requestId`, `userDateTime` from request headers/cookies. In FastStore, this context must be extracted in the API route handler (`[faststore/packages/core/src/pages/api/graphql.ts](faststore/packages/core/src/pages/api/graphql.ts)`) and passed through the GraphQL context. The API route will need modifications to forward checkout-specific headers. | |
| ### 1.3 Cookie and Authentication Handling | |
| The FastCheckout BFF manages VTEX auth cookies (`VtexIdclientAutCookie`, `checkout.vtex.com`, `vtex_session`, etc.). In FastStore, the API route at `/api/graphql` already handles session cookies. Checkout-specific cookie management (especially for Identity login flows) will need to be added to the API route or handled via a middleware. | |
| ## 2. Page Structure | |
| Create the following pages under `[faststore/packages/core/src/pages/checkout/](faststore/packages/core/src/pages/checkout/)`: | |
| | Route | File | Purpose | | |
| | ---------------------------------- | ---------------------------- | ------------------------------------------------- | | |
| | `/checkout` | `index.tsx` | Redirects to `/checkout/cart` | | |
| | `/checkout/cart` | `cart.tsx` | Cart with items, summary, coupons | | |
| | `/checkout/delivery` | `delivery.tsx` | Address selection, shipping options | | |
| | `/checkout/payment` | `payment.tsx` | Payment method selection, credit card, gift cards | | |
| | `/checkout/review` | `review.tsx` | Order review before placing | | |
| | `/checkout/order-placed/[orderId]` | `order-placed/[orderId].tsx` | Order confirmation | | |
| | `/checkout/payment-loading` | `payment-loading.tsx` | Payment processing status | | |
| | `/checkout/sign-in` | `sign-in.tsx` | Authentication for checkout | | |
| Each page will: | |
| - Use `getServerSideProps` (not `getStaticProps`) since checkout is dynamic/personalized | |
| - Render global sections (header/footer) via `RenderSections` | |
| - Render checkout-specific sections as custom components | |
| ## 3. Component Migration | |
| ### 3.1 Direct Mappings (use FastStore components) | |
| | FastCheckout | FastStore | Import | | |
| | --------------------- | ------------------ | --------------- | | |
| | `Button` | `Button` | `@faststore/ui` | | |
| | `TextInput` | `InputField` | `@faststore/ui` | | |
| | `Checkbox` | `CheckboxField` | `@faststore/ui` | | |
| | `SelectInput` | `SelectField` | `@faststore/ui` | | |
| | `IconButton` | `IconButton` | `@faststore/ui` | | |
| | `Tag` | `Tag` | `@faststore/ui` | | |
| | `Link` | `Link` | `@faststore/ui` | | |
| | `Spinner` | `Loader` | `@faststore/ui` | | |
| | `Breadcrumb` | `Breadcrumb` | `@faststore/ui` | | |
| | `SearchInput` | `SearchInputField` | `@faststore/ui` | | |
| | `Modal` (various) | `Modal` | `@faststore/ui` | | |
| | `Accordion` (if used) | `Accordion` | `@faststore/ui` | | |
| | `Skeleton` | `Skeleton` | `@faststore/ui` | | |
| | `Table` | `Table` | `@faststore/ui` | | |
| ### 3.2 Custom Components (must be built as new FastStore sections/components) | |
| These have no FastStore equivalent and must be created in `[faststore/packages/core/src/customizations/src/components/](faststore/packages/core/src/customizations/src/components/)`: | |
| - **CheckoutCart** - Cart item list with quantity controls, item removal | |
| - **CheckoutSummary** - Order summary with totals, discounts | |
| - **CheckoutCoupon** - Coupon input and applied coupons | |
| - **AddressForm** - Address form with country-specific fields (BRA, USA) | |
| - **CardForm** - Credit card form with masking, Luhn validation | |
| - **PaymentOptions** - Payment method selector with saved cards, gift cards | |
| - **DeliveryOptions** - Shipping SLA selector, delivery windows | |
| - **PickupPointSelector** - Pickup point search and selection | |
| - **ReviewOrder** - Order review display | |
| - **OrderPlacedConfirmation** - Order confirmation with details | |
| - **PaymentLoadingScreen** - Payment processing indicator | |
| - **CheckoutBreadcrumb** - Step progress indicator | |
| - **CheckoutSignIn** - Login form with VTEX Identity integration | |
| - **OneClickCheckout** - One-click purchase flow | |
| ### 3.3 Checkout Sections for CMS | |
| Create CMS section definitions in `cms/faststore/sections.json` for each checkout section so they can be managed in Headless CMS: | |
| ```json | |
| [ | |
| { "name": "CheckoutCart", "schema": { ... } }, | |
| { "name": "CheckoutDelivery", "schema": { ... } }, | |
| { "name": "CheckoutPayment", "schema": { ... } }, | |
| { "name": "CheckoutReview", "schema": { ... } }, | |
| { "name": "CheckoutOrderPlaced", "schema": { ... } }, | |
| { "name": "CheckoutSummary", "schema": { ... } } | |
| ] | |
| ``` | |
| ## 4. State Management Migration | |
| | FastCheckout | FastStore | | |
| | ------------------- | ---------------------------------------------------------- | | |
| | Relay Environment | SWR + custom GraphQL `request()` function | | |
| | `usePreloadedQuery` | `useQuery` (SWR-based, from `src/sdk/graphql/useQuery.ts`) | | |
| | `useFragment` | Inline field selection in queries (no fragments needed) | | |
| | `useMutation` | Custom `useMutation` hook using `fetch` to `/api/graphql` | | |
| | Relay Store | Zustand stores + SWR cache | | |
| | `loadQuery` | SWR `prefetch` or `getServerSideProps` data | | |
| Create new SDK hooks in `src/sdk/checkout/`: | |
| - `useCheckoutCart()` - fetches and manages cart state | |
| - `useCheckoutShipping()` - shipping/delivery state | |
| - `useCheckoutPayment()` - payment state | |
| - `useCheckoutOrder()` - order placement | |
| - `useCheckoutAuth()` - authentication state | |
| - `useCheckoutSummary()` - order summary | |
| - `useCheckoutCoupon()` - coupon management | |
| - `useCheckoutCustomer()` - customer data | |
| Each hook will use SWR for queries and a custom mutation helper for mutations, all hitting `/api/graphql`. | |
| ## 5. Styling Migration | |
| - **From**: Vanilla Extract (`*.css.ts`, `styleVariants`, `sprinkles`, `assignInlineVars`) | |
| - **To**: SCSS Modules (`*.module.scss`) with FastStore design tokens (`var(--fs-*)`) | |
| **Strategy**: For each screen component, create a `.module.scss` file that: | |
| 1. Imports relevant `@faststore/ui` component styles | |
| 2. Maps FastCheckout theme tokens to FastStore CSS custom properties | |
| 3. Preserves the layout and visual design | |
| **Token mapping** (FastCheckout theme -> FastStore tokens): | |
| - `theme.colors.`* -> `var(--fs-color-*)` | |
| - `theme.spacers.`* -> `var(--fs-spacing-*)` | |
| - `theme.typography.`* -> `var(--fs-text-size-*)` | |
| - `theme.border.`* -> `var(--fs-border-*)` | |
| ## 6. i18n Migration | |
| FastCheckout uses `react-intl` with locales `en-US`, `es-MX`, `pt-BR` (`[fastcheckout/packages/libs/i18n/](fastcheckout/packages/libs/i18n/)`). FastStore doesn't have built-in i18n for custom sections. Options: | |
| - Keep `react-intl` as a dependency and wrap checkout pages with `IntlProvider` | |
| - This is the pragmatic approach since the translation files and `FormattedMessage` usage throughout the checkout are extensive | |
| ## 7. Form Libraries Migration | |
| The `[address-form](fastcheckout/packages/libs/address-form/)` and `[card-ui](fastcheckout/packages/libs/card-ui/)` libraries use `react-hook-form`. Since FastStore components are uncontrolled by default, create wrapper components that integrate `react-hook-form` with FastStore form fields (`InputField`, `SelectField`, `CheckboxField`). | |
| ## 8. Utility Libraries Migration | |
| - `[validators](fastcheckout/packages/libs/validators/)` - Copy as-is into `src/customizations/src/utils/validators/` | |
| - `[input-mask](fastcheckout/packages/libs/input-mask/)` - Copy as-is into `src/customizations/src/utils/input-mask/` | |
| - `[constants](fastcheckout/packages/libs/constants/)` - Copy as-is into `src/customizations/src/utils/constants/` | |
| ## 9. Configuration Changes | |
| Update `[discovery.config.default.js](faststore/packages/core/discovery.config.default.js)`: | |
| - Change `checkoutUrl` to `/checkout/cart` (internal route instead of external redirect) | |
| - Add checkout-specific configuration (payment options, address formats, etc.) | |
| Update the `redirectToCheckout` function in `[faststore/packages/core/src/sdk/cart/redirectToCheckout.ts](faststore/packages/core/src/sdk/cart/redirectToCheckout.ts)` to navigate to `/checkout/cart` instead of an external URL. | |
| ## 10. API Route Modifications | |
| Modify `[faststore/packages/core/src/pages/api/graphql.ts](faststore/packages/core/src/pages/api/graphql.ts)` to: | |
| - Forward checkout-specific headers (`x-order-form-id`, `x-fastcheckout-user-date-time`) | |
| - Handle checkout cookie management (auth cookies, session cookies) | |
| - Support the additional checkout mutations (place order, payment, etc.) | |
| ## File Structure (Target) | |
| ``` | |
| faststore/packages/core/src/ | |
| ├── customizations/src/ | |
| │ ├── components/ | |
| │ │ ├── checkout/ | |
| │ │ │ ├── Cart/ | |
| │ │ │ ├── Delivery/ | |
| │ │ │ ├── Payment/ | |
| │ │ │ ├── Review/ | |
| │ │ │ ├── OrderPlaced/ | |
| │ │ │ ├── SignIn/ | |
| │ │ │ ├── PaymentLoading/ | |
| │ │ │ ├── shared/ (Summary, Breadcrumb, AddressForm, CardForm, etc.) | |
| │ │ │ └── index.tsx | |
| │ │ └── index.tsx | |
| │ ├── graphql/vtex/ | |
| │ │ ├── typeDefs/ | |
| │ │ │ ├── checkout-cart.graphql | |
| │ │ │ ├── checkout-auth.graphql | |
| │ │ │ ├── checkout-payment.graphql | |
| │ │ │ ├── checkout-shipping.graphql | |
| │ │ │ ├── checkout-order.graphql | |
| │ │ │ ├── checkout-summary.graphql | |
| │ │ │ ├── checkout-coupon.graphql | |
| │ │ │ ├── checkout-customer.graphql | |
| │ │ │ └── ... (remaining domains) | |
| │ │ └── resolvers/ | |
| │ │ ├── index.ts | |
| │ │ ├── checkoutCart.ts | |
| │ │ ├── checkoutAuth.ts | |
| │ │ ├── checkoutPayment.ts | |
| │ │ ├── checkoutShipping.ts | |
| │ │ ├── checkoutOrder.ts | |
| │ │ └── ... (remaining resolvers) | |
| │ └── utils/ | |
| │ ├── validators/ | |
| │ ├── input-mask/ | |
| │ ├── constants/ | |
| │ └── i18n/ | |
| ├── pages/ | |
| │ └── checkout/ | |
| │ ├── index.tsx | |
| │ ├── cart.tsx | |
| │ ├── delivery.tsx | |
| │ ├── payment.tsx | |
| │ ├── review.tsx | |
| │ ├── payment-loading.tsx | |
| │ ├── sign-in.tsx | |
| │ └── order-placed/ | |
| │ └── [orderId].tsx | |
| └── sdk/ | |
| └── checkout/ | |
| ├── useCheckoutCart.ts | |
| ├── useCheckoutShipping.ts | |
| ├── useCheckoutPayment.ts | |
| ├── useCheckoutOrder.ts | |
| ├── useCheckoutAuth.ts | |
| ├── useCheckoutSummary.ts | |
| ├── useCheckoutCoupon.ts | |
| ├── useCheckoutCustomer.ts | |
| └── clients/ | |
| ├── VtexIdentityClient.ts | |
| ├── VtexPaymentsClient.ts | |
| ├── VtexWalletHubClient.ts | |
| ├── VtexMasterDataClient.ts | |
| └── VtexBudgetClient.ts | |
| ``` | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment