--- title: Build a mobile storefront description: >- Fetch products, create a cart, and present Shopify checkout in your mobile app using the Storefront API and Checkout Kit. source_url: html: >- https://shopify.dev/docs/storefronts/mobile/build-mobile-storefront?extension=swift md: >- https://shopify.dev/docs/storefronts/mobile/build-mobile-storefront.md?extension=swift --- # Build a mobile storefront Build a mobile app that fetches products from your store, creates a cart, and presents checkout. You'll use the [Storefront API](https://shopify.dev/docs/api/storefront) to fetch products and create a cart, and [Checkout Kit](https://shopify.dev/docs/storefronts/mobile/checkout-kit) to present Shopify's checkout inside your app. **Skip ahead:** If you already have a checkout URL, then go to [Embed Checkout Kit](https://shopify.dev/docs/storefronts/mobile/checkout-kit) for a quick start. ## What you'll learn In this tutorial, you'll: * Query the Storefront API to fetch products and their variant IDs. * Build a native product list with images, prices, and an add-to-cart action. * Get a `checkoutUrl` using the `cartCreate` mutation or a cart permalink. * Install Checkout Kit and present Shopify checkout inside your app. * Test the complete purchase flow from browsing to order confirmation. ## Requirements [Create a development store](https://shopify.dev/docs/apps/build/dev-dashboard/stores/development-stores) A Shopify development store with at least one product. Select **Generate test data** during creation so your store has products to work with. [Storefront API access token](https://shopify.dev/docs/storefronts/headless/building-with-the-storefront-api/getting-started#step-1-enable-storefront-api-access) The Headless channel installed in your store with a public access token. [Set up your development environment](https://developer.apple.com/xcode/) Xcode 14 or later, targeting iOS 13 or later. ## Project [View on GitHub](https://github.com/Shopify/example-mobile--storefront--swift) ## Fetch products Use the Storefront API to fetch products from your store. Each product includes variant IDs that you'll need when creating a cart. ### Query products from the Storefront API Send a GraphQL query to `https://{shop}.myshopify.com/api/{api-version}/graphql.json` with your public access token in the `X-Shopify-Storefront-Access-Token` header. Replace `{shop}` with your store's myshopify.com subdomain. This query fetches the first 10 products with their titles, images, and variant IDs. Each product's variant includes an `id` (for example, `gid://shopify/ProductVariant/44217898279174`) and a `price`. You'll use the variant `id` when creating a cart. *** **Tip:** If you receive a 401 error, then check that your access token is correct and that you're using a public Storefront API token. The token goes in the `X-Shopify-Storefront-Access-Token` header, not the `Authorization` header. [Storefront API](https://shopify.dev/docs/api/storefront) [Products query](https://shopify.dev/docs/api/storefront/latest/queries/products) ## /StorefrontClient.swift ```swift import Foundation class StorefrontClient { let shopDomain: String let accessToken: String let apiVersion: String init(shopDomain: String, accessToken: String, apiVersion: String = "2026-01") { self.shopDomain = shopDomain self.accessToken = accessToken self.apiVersion = apiVersion } func fetchProducts() async throws -> [Product] { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let query = """ query Products { products(first: 10) { edges { node { id title description featuredImage { url } variants(first: 1) { edges { node { id title price { amount currencyCode } } } } } } } } """ let body = ["query": query] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(ProductsResponse.self, from: data) return result.data.products.edges.map { $0.node } } func createCart(variantId: String, quantity: Int = 1) async throws -> Cart { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let mutation = """ mutation CartCreate($input: CartInput!) { cartCreate(input: $input) { cart { id checkoutUrl } userErrors { field message } } } """ let variables: [String: Any] = [ "input": [ "lines": [ ["merchandiseId": variantId, "quantity": quantity] ] ] ] let body: [String: Any] = ["query": mutation, "variables": variables] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(CartCreateResponse.self, from: data) if let error = result.data.cartCreate.userErrors.first { throw CartError.userError(error.message) } guard let cart = result.data.cartCreate.cart else { throw CartError.cartNotCreated } return cart } func buildCartPermalink(variantId: String, quantity: Int = 1) -> URL { let numericVariantId = variantId.split(separator: "/").last.map(String.init) ?? variantId return URL(string: "https://\(shopDomain)/cart/\(numericVariantId):\(quantity)")! } } ``` ### Define response types Create `Decodable` structs to parse the GraphQL JSON response. The Storefront API wraps results in `edges` and `node` objects, so these types unwrap that structure into Swift types you can use throughout your app. ## /Models.swift ```swift import Foundation struct ProductsResponse: Decodable { let data: ProductsData } struct ProductsData: Decodable { let products: ProductConnection } struct ProductConnection: Decodable { let edges: [ProductEdge] } struct ProductEdge: Decodable { let node: Product } struct Product: Decodable, Identifiable { let id: String let title: String let description: String? let featuredImage: FeaturedImage? let variants: VariantConnection var firstVariantId: String? { variants.edges.first?.node.id } } struct FeaturedImage: Decodable { let url: String } struct VariantConnection: Decodable { let edges: [VariantEdge] } struct VariantEdge: Decodable { let node: ProductVariant } struct ProductVariant: Decodable { let id: String let title: String let price: Price } struct Price: Decodable { let amount: String let currencyCode: String } struct CartCreateResponse: Decodable { let data: CartCreateData } struct CartCreateData: Decodable { let cartCreate: CartCreatePayload } struct CartCreatePayload: Decodable { let cart: Cart? let userErrors: [UserError] } struct Cart: Decodable { let id: String let checkoutUrl: String } struct UserError: Decodable { let field: [String]? let message: String } enum StorefrontError: Error { case requestFailed case decodingFailed } enum CartError: Error { case userError(String) case cartNotCreated } ``` ## Display products in your UI Build a product list that renders the fetched products with an **Add to Cart** button for each product. ### Build the product list Create a SwiftUI view that loads products on appear and renders each one with a title, price, image, and **Add to Cart** button. The view model calls `fetchProducts()` from the Storefront client and stores the results. *** Your implementation depends on your app's design, so treat this as a starting point. When the buyer taps **Add to Cart**, the handler pulls the variant ID from the selected product and creates a cart. ## /ProductListView\.swift ```swift import SwiftUI struct ProductListView: View { @StateObject private var viewModel = ProductListViewModel() var body: some View { NavigationView { List(viewModel.products) { product in ProductRow( product: product, onAddToCart: { viewModel.addToCart(product: product) } ) } .navigationTitle("Products") .overlay { if viewModel.isLoading { ProgressView() } } } .task { await viewModel.loadProducts() } } } struct ProductRow: View { let product: Product let onAddToCart: () -> Void var body: some View { HStack { AsyncImage(url: URL(string: product.featuredImage?.url ?? "")) { image in image.resizable().scaledToFit() } placeholder: { Color.gray.opacity(0.3) } .frame(width: 60, height: 60) .cornerRadius(8) VStack(alignment: .leading) { Text(product.title) .font(.headline) if let price = product.variants.edges.first?.node.price { Text("$\(price.amount) \(price.currencyCode)") .font(.subheadline) .foregroundColor(.secondary) } } Spacer() Button("Add to Cart") { onAddToCart() } .buttonStyle(.borderedProminent) } } } @MainActor class ProductListViewModel: ObservableObject { @Published var products: [Product] = [] @Published var isLoading = false private let client = StorefrontClient( shopDomain: "{shop}.myshopify.com", accessToken: "your-storefront-access-token" ) func loadProducts() async { isLoading = true defer { isLoading = false } do { products = try await client.fetchProducts() } catch { print("Failed to load products: \(error)") } } func addToCart(product: Product) { guard let variantId = product.firstVariantId else { return } Task { do { let cart = try await client.createCart(variantId: variantId) print("Checkout URL: \(cart.checkoutUrl)") } catch { print("Failed to create cart: \(error)") } } } } ``` ## Get a checkout URL You need a `checkoutUrl` to present to the buyer. You can create a cart through the Storefront API, or build a URL directly from variant IDs using a cart permalink. ### Create a cart with the Storefront API Send a [`cartCreate`](https://shopify.dev/docs/api/storefront/latest/mutations/cartCreate) mutation with the variant ID as the `merchandiseId` in a [`CartInput`](https://shopify.dev/docs/api/storefront/latest/input-objects/CartInput) line item. The response includes a `checkoutUrl` that you pass to Checkout Kit. *** Build a `checkoutUrl` without the API by using a [cart permalink](https://shopify.dev/docs/apps/build/checkout/create-cart-permalinks). The format is `https://{shop}.myshopify.com/cart/{variant_id}:{quantity}`. Cart permalinks require numeric variant IDs (for example, `12345678901234`), not the GraphQL format (`gid://shopify/ProductVariant/12345678901234`). **Caution:** The cart ID includes a secret key in the format `gid://shopify/Cart/{token}?key={secret}`. Always store the complete ID including the `?key=` parameter. Without it, queries strip buyer data and mutations fail. [cart​Create mutation](https://shopify.dev/docs/api/storefront/latest/mutations/cartCreate) [Manage carts with the Storefront API](https://shopify.dev/docs/storefronts/headless/building-with-the-storefront-api/cart/manage) [Cart permalinks](https://shopify.dev/docs/apps/build/checkout/create-cart-permalinks) ## /StorefrontClient.swift ```swift import Foundation class StorefrontClient { let shopDomain: String let accessToken: String let apiVersion: String init(shopDomain: String, accessToken: String, apiVersion: String = "2026-01") { self.shopDomain = shopDomain self.accessToken = accessToken self.apiVersion = apiVersion } func fetchProducts() async throws -> [Product] { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let query = """ query Products { products(first: 10) { edges { node { id title description featuredImage { url } variants(first: 1) { edges { node { id title price { amount currencyCode } } } } } } } } """ let body = ["query": query] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(ProductsResponse.self, from: data) return result.data.products.edges.map { $0.node } } func createCart(variantId: String, quantity: Int = 1) async throws -> Cart { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let mutation = """ mutation CartCreate($input: CartInput!) { cartCreate(input: $input) { cart { id checkoutUrl } userErrors { field message } } } """ let variables: [String: Any] = [ "input": [ "lines": [ ["merchandiseId": variantId, "quantity": quantity] ] ] ] let body: [String: Any] = ["query": mutation, "variables": variables] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(CartCreateResponse.self, from: data) if let error = result.data.cartCreate.userErrors.first { throw CartError.userError(error.message) } guard let cart = result.data.cartCreate.cart else { throw CartError.cartNotCreated } return cart } func buildCartPermalink(variantId: String, quantity: Int = 1) -> URL { let numericVariantId = variantId.split(separator: "/").last.map(String.init) ?? variantId return URL(string: "https://\(shopDomain)/cart/\(numericVariantId):\(quantity)")! } } ``` ## Present checkout with Checkout Kit Install Checkout Kit and present Shopify checkout inside your app. Your app receives callbacks when checkout completes, fails, or the buyer cancels. ### Install Checkout Kit Add the `checkout-sheet-kit-swift` package to your project using Swift Package Manager, or add it through Xcode by going to **File** > **Add Package Dependencies**. *** ## /Package.swift ```swift // swift-tools-version: 5.7 import PackageDescription let package = Package( name: "MobileStorefront", platforms: [ .iOS(.v15) ], dependencies: [ .package(url: "https://github.com/Shopify/checkout-sheet-kit-swift", from: "3.0.0") ], targets: [ .executableTarget( name: "MobileStorefront", dependencies: [ .product(name: "ShopifyCheckoutSheetKit", package: "checkout-sheet-kit-swift") ] ) ] ) ``` ### Present checkout and handle events Call `present()` with your `checkoutUrl`. Checkout Kit presents the store's checkout, including branding and all configured payment methods. Implement the `CheckoutDelegate` protocol to respond when the buyer completes checkout, cancels, encounters an error, or taps an external link. *** **Tip:** Request the `checkoutUrl` when the buyer is ready to check out. Checkout URLs can go stale, especially for [authenticated checkouts](https://shopify.dev/docs/storefronts/mobile/checkout-kit/authenticate-checkouts). If the URL is stale, then query the cart again to get a new one. [Monitor checkout lifecycle](https://shopify.dev/docs/storefronts/mobile/checkout-kit/monitor-checkout-lifecycle) [Preload checkout](https://shopify.dev/docs/storefronts/mobile/checkout-kit/preloading) ## /CartViewController.swift ```swift import UIKit import ShopifyCheckoutSheetKit class CartViewController: UIViewController { private var checkoutUrl: URL? private let storefrontClient = StorefrontClient( shopDomain: "{shop}.myshopify.com", accessToken: "your-storefront-access-token" ) func addToCart(variantId: String) async { do { let cart = try await storefrontClient.createCart(variantId: variantId) checkoutUrl = URL(string: cart.checkoutUrl) } catch { print("Failed to create cart: \(error)") } } @IBAction func checkoutTapped(_ sender: UIButton) { guard let url = checkoutUrl else { print("No checkout URL available") return } ShopifyCheckoutSheetKit.present( checkout: url, from: self, delegate: self ) } } extension CartViewController: CheckoutDelegate { func checkoutDidComplete(event: CheckoutCompletedEvent) { let orderId = event.orderDetails.id print("Order completed: \(orderId)") checkoutUrl = nil } func checkoutDidCancel() { print("Checkout canceled") } func checkoutDidFail(error: CheckoutError) { print("Checkout failed: \(error.localizedDescription)") let alert = UIAlertController( title: "Checkout Error", message: error.localizedDescription, preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } func checkoutDidClickLink(url: URL) { UIApplication.shared.open(url) } } ``` ## Test the complete flow Verify the full flow by browsing products, completing a purchase, and checking the order in the Shopify admin. ### Run the app and complete a test purchase Run your app on a simulator, emulator, or device. Browse the product list and confirm that titles, prices, and images load from your store. Tap **Add to Cart** on a product, then complete checkout. To process test payments, enable [Shopify's Bogus Gateway](https://help.shopify.com/en/manual/checkout-settings/test-orders/payments-test-mode#bogus-gateway) in your development store by going to **Settings** > **Payments**. After checkout completes, open your Shopify admin and go to **Orders**. The new order appears with the products you selected. *** If products don't load, then check that your Storefront API public access token is correct and that you enabled **Products and Collections** permissions in the Headless channel. If checkout doesn't open, then verify that your `checkoutUrl` is valid and that the cart hasn't expired. ## /StorefrontClient.swift ```swift import Foundation class StorefrontClient { let shopDomain: String let accessToken: String let apiVersion: String init(shopDomain: String, accessToken: String, apiVersion: String = "2026-01") { self.shopDomain = shopDomain self.accessToken = accessToken self.apiVersion = apiVersion } func fetchProducts() async throws -> [Product] { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let query = """ query Products { products(first: 10) { edges { node { id title description featuredImage { url } variants(first: 1) { edges { node { id title price { amount currencyCode } } } } } } } } """ let body = ["query": query] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(ProductsResponse.self, from: data) return result.data.products.edges.map { $0.node } } func createCart(variantId: String, quantity: Int = 1) async throws -> Cart { let url = URL(string: "https://\(shopDomain)/api/\(apiVersion)/graphql.json")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(accessToken, forHTTPHeaderField: "X-Shopify-Storefront-Access-Token") let mutation = """ mutation CartCreate($input: CartInput!) { cartCreate(input: $input) { cart { id checkoutUrl } userErrors { field message } } } """ let variables: [String: Any] = [ "input": [ "lines": [ ["merchandiseId": variantId, "quantity": quantity] ] ] ] let body: [String: Any] = ["query": mutation, "variables": variables] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw StorefrontError.requestFailed } let result = try JSONDecoder().decode(CartCreateResponse.self, from: data) if let error = result.data.cartCreate.userErrors.first { throw CartError.userError(error.message) } guard let cart = result.data.cartCreate.cart else { throw CartError.cartNotCreated } return cart } func buildCartPermalink(variantId: String, quantity: Int = 1) -> URL { let numericVariantId = variantId.split(separator: "/").last.map(String.init) ?? variantId return URL(string: "https://\(shopDomain)/cart/\(numericVariantId):\(quantity)")! } } ``` ## /Models.swift ```swift import Foundation struct ProductsResponse: Decodable { let data: ProductsData } struct ProductsData: Decodable { let products: ProductConnection } struct ProductConnection: Decodable { let edges: [ProductEdge] } struct ProductEdge: Decodable { let node: Product } struct Product: Decodable, Identifiable { let id: String let title: String let description: String? let featuredImage: FeaturedImage? let variants: VariantConnection var firstVariantId: String? { variants.edges.first?.node.id } } struct FeaturedImage: Decodable { let url: String } struct VariantConnection: Decodable { let edges: [VariantEdge] } struct VariantEdge: Decodable { let node: ProductVariant } struct ProductVariant: Decodable { let id: String let title: String let price: Price } struct Price: Decodable { let amount: String let currencyCode: String } struct CartCreateResponse: Decodable { let data: CartCreateData } struct CartCreateData: Decodable { let cartCreate: CartCreatePayload } struct CartCreatePayload: Decodable { let cart: Cart? let userErrors: [UserError] } struct Cart: Decodable { let id: String let checkoutUrl: String } struct UserError: Decodable { let field: [String]? let message: String } enum StorefrontError: Error { case requestFailed case decodingFailed } enum CartError: Error { case userError(String) case cartNotCreated } ``` ## /ProductListView\.swift ```swift import SwiftUI struct ProductListView: View { @StateObject private var viewModel = ProductListViewModel() var body: some View { NavigationView { List(viewModel.products) { product in ProductRow( product: product, onAddToCart: { viewModel.addToCart(product: product) } ) } .navigationTitle("Products") .overlay { if viewModel.isLoading { ProgressView() } } } .task { await viewModel.loadProducts() } } } struct ProductRow: View { let product: Product let onAddToCart: () -> Void var body: some View { HStack { AsyncImage(url: URL(string: product.featuredImage?.url ?? "")) { image in image.resizable().scaledToFit() } placeholder: { Color.gray.opacity(0.3) } .frame(width: 60, height: 60) .cornerRadius(8) VStack(alignment: .leading) { Text(product.title) .font(.headline) if let price = product.variants.edges.first?.node.price { Text("$\(price.amount) \(price.currencyCode)") .font(.subheadline) .foregroundColor(.secondary) } } Spacer() Button("Add to Cart") { onAddToCart() } .buttonStyle(.borderedProminent) } } } @MainActor class ProductListViewModel: ObservableObject { @Published var products: [Product] = [] @Published var isLoading = false private let client = StorefrontClient( shopDomain: "{shop}.myshopify.com", accessToken: "your-storefront-access-token" ) func loadProducts() async { isLoading = true defer { isLoading = false } do { products = try await client.fetchProducts() } catch { print("Failed to load products: \(error)") } } func addToCart(product: Product) { guard let variantId = product.firstVariantId else { return } Task { do { let cart = try await client.createCart(variantId: variantId) print("Checkout URL: \(cart.checkoutUrl)") } catch { print("Failed to create cart: \(error)") } } } } ``` ## /Package.swift ```swift // swift-tools-version: 5.7 import PackageDescription let package = Package( name: "MobileStorefront", platforms: [ .iOS(.v15) ], dependencies: [ .package(url: "https://github.com/Shopify/checkout-sheet-kit-swift", from: "3.0.0") ], targets: [ .executableTarget( name: "MobileStorefront", dependencies: [ .product(name: "ShopifyCheckoutSheetKit", package: "checkout-sheet-kit-swift") ] ) ] ) ``` ## /CartViewController.swift ```swift import UIKit import ShopifyCheckoutSheetKit class CartViewController: UIViewController { private var checkoutUrl: URL? private let storefrontClient = StorefrontClient( shopDomain: "{shop}.myshopify.com", accessToken: "your-storefront-access-token" ) func addToCart(variantId: String) async { do { let cart = try await storefrontClient.createCart(variantId: variantId) checkoutUrl = URL(string: cart.checkoutUrl) } catch { print("Failed to create cart: \(error)") } } @IBAction func checkoutTapped(_ sender: UIButton) { guard let url = checkoutUrl else { print("No checkout URL available") return } ShopifyCheckoutSheetKit.present( checkout: url, from: self, delegate: self ) } } extension CartViewController: CheckoutDelegate { func checkoutDidComplete(event: CheckoutCompletedEvent) { let orderId = event.orderDetails.id print("Order completed: \(orderId)") checkoutUrl = nil } func checkoutDidCancel() { print("Checkout canceled") } func checkoutDidFail(error: CheckoutError) { print("Checkout failed: \(error.localizedDescription)") let alert = UIAlertController( title: "Checkout Error", message: error.localizedDescription, preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } func checkoutDidClickLink(url: URL) { UIApplication.shared.open(url) } } ``` ## Tutorial complete! You've built a mobile storefront that fetches products, creates a cart, and presents Shopify checkout inside your app. This tutorial uses direct HTTP calls to keep things simple. For production apps, we recommend using [Apollo](https://www.apollographql.com/) for typed queries, caching, and `@defer` support. See the sample apps below for production-ready examples. ### Next steps [Example apps\ \ ](https://github.com/Shopify/checkout-sheet-kit-swift/tree/main/Samples) [Sample apps with production-quality UI and Checkout Kit integration.](https://github.com/Shopify/checkout-sheet-kit-swift/tree/main/Samples) [Accelerated checkouts\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/accelerated-checkouts-overview) [Add Shop Pay and Apple Pay buttons for accelerated checkouts.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/accelerated-checkouts-overview) [Authenticate buyers\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/authenticate-checkouts) [Prefill checkout with a signed-in buyer's address and payment methods.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/authenticate-checkouts) [Preload checkout\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/preloading) [Fetch checkout in the background so it's ready when the buyer taps checkout.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/preloading)