sfnext-data-fetching
Implement server-side data fetching in Storefront Next using loaders, actions, and useScapiFetcher. Use when writing loader functions, making SCAPI calls, handling form submissions, or implementing interactive data fetching. Covers synchronous loaders, streaming patterns, createApiClients, and parallel requests. NOT for client-side Zustand state — see sfnext-state-management.
What this skill does
# Data Fetching Skill
This skill covers server-side data fetching patterns in Storefront Next — loaders, actions, and the useScapiFetcher hook.
## Overview
Storefront Next mandates **server-only data loading**. All SCAPI requests execute on the MRT server, never in the browser. Three mechanisms exist:
| Mechanism | When It Runs | Use Case |
|-----------|-------------|----------|
| `loader` | Route navigation | Initial page data |
| `action` | Form submission | Mutations (add to cart, update profile) |
| `useScapiFetcher` | User interaction | On-demand fetching (search suggestions, infinite scroll) |
## Loader Patterns
Loaders can be **synchronous** (returning promises for streaming) or **async** (awaiting critical data). Choose based on what the page needs:
- **Sync loader** — Returns promises directly. Enables streaming SSR: the shell renders immediately while data streams in. Best when all data can render progressively.
- **Async loader** — Awaits critical data before rendering. Use when data is required for SEO or the page shell (e.g., category name in breadcrumbs). Non-critical data can still be returned as promises for streaming.
```typescript
// Sync — full streaming (all data renders progressively)
export function loader({ params, context }: LoaderFunctionArgs): ProductPageData {
const clients = createApiClients(context);
return {
product: clients.shopperProducts.getProduct({
params: { path: { id: params.productId } }
}).then(({ data }) => data),
reviews: clients.shopperProducts.getReviews({
params: { path: { id: params.productId } }
}).then(({ data }) => data),
};
}
// Async — await critical data, stream the rest (mixed strategy)
export async function loader({ params, context }: LoaderFunctionArgs): Promise<CategoryPageData> {
const clients = createApiClients(context);
// Await critical data needed for page shell/SEO
const category = await clients.shopperProducts.getCategory({
params: { path: { id: params.categoryId } }
}).then(({ data }) => data);
return {
category, // Resolved immediately
products: clients.shopperSearch.productSearch({
params: { query: { q: '', refine: { cgid: params.categoryId } } }
}).then(({ data }) => data), // Streamed
};
}
```
## When to Use Each Pattern
| Pattern | When | Example |
|---------|------|---------|
| Sync (full streaming) | All data can render progressively | Product page with reviews |
| Async (await critical) | SEO-critical data needed for page shell | Category page (needs category name) |
| Mixed | Some data critical, some deferrable | Category name (await) + product grid (stream) |
See [Loader Patterns Reference](references/LOADER-PATTERNS.md) for more patterns and data flow diagrams.
## Action Functions
Handle mutations (form submissions, cart updates):
```typescript
import { data, redirect } from 'react-router';
export async function action({ request, context }: ActionFunctionArgs) {
const formData = await request.formData();
const productId = formData.get('productId') as string;
const clients = createApiClients(context);
try {
await clients.shopperBasketsV2.addItemToBasket({
params: {
path: { basketId },
body: { productId, quantity: 1 },
},
});
return data({ success: true });
} catch (error) {
return data({ success: false, error: error.message }, { status: 400 });
}
}
```
## useScapiFetcher — Interactive Data Fetching
For on-demand data fetching triggered by user interactions (after page load):
```typescript
import { useScapiFetcher } from '@/hooks/use-scapi-fetcher';
export function useSearchSuggestions({ q, limit, currency }) {
const parameters = useMemo(
() => ({ params: { query: { q, limit, currency } } }),
[q, limit, currency]
);
const fetcher = useScapiFetcher(
'shopperSearch',
'getSearchSuggestions',
parameters
);
const refetch = useCallback(async () => {
await fetcher.load();
}, [fetcher]);
return {
data: fetcher.data,
isLoading: fetcher.state === 'loading',
refetch,
};
}
```
See [SCAPI Fetcher Reference](references/SCAPI-FETCHER.md) for the complete useScapiFetcher API.
## API Client Usage
Always use `createApiClients(context)` in loaders and actions:
```typescript
import { createApiClients } from '@/lib/api-clients';
export function loader({ context }: LoaderFunctionArgs) {
const clients = createApiClients(context);
clients.shopperProducts.getProduct({...});
clients.shopperCustomers.getCustomer({...});
clients.shopperBasketsV2.getBasket({...});
clients.shopperSearch.productSearch({...});
clients.shopperOrders.getOrder({...});
}
```
## Parallel vs Sequential Requests
```typescript
// GOOD — Parallel requests (all start simultaneously)
export function loader({ context }: LoaderFunctionArgs) {
const clients = createApiClients(context);
return {
product: clients.shopperProducts.getProduct({...}).then(({ data }) => data),
reviews: clients.shopperProducts.getReviews({...}).then(({ data }) => data),
recommendations: clients.shopperProducts.getRecommendations({...}).then(({ data }) => data),
};
}
// AVOID — Sequential awaits of independent requests (unnecessarily slow)
export async function loader({ context }: LoaderFunctionArgs) {
const clients = createApiClients(context);
const product = await clients.shopperProducts.getProduct({...}); // Waits...
const reviews = await clients.shopperProducts.getReviews({...}); // Then waits again
return { product, reviews };
}
```
## Common Pitfalls
| Pitfall | Problem | Solution |
|---------|---------|----------|
| Awaiting all data | Blocks page transition unnecessarily | Only await SEO-critical data; stream the rest |
| Client loaders | Not permitted in Storefront Next | Use server `loader` or `useScapiFetcher` |
| Sequential `await` | Slow data loading | Return promises in parallel |
| Missing `context` in `getConfig()` | Config unavailable | Pass `context` in server loaders: `getConfig(context)` |
## Related Skills
- `storefront-next:sfnext-routing` - Route file conventions and module exports
- `storefront-next:sfnext-components` - Rendering loader data with createPage and Suspense
- `storefront-next:sfnext-state-management` - Client-side Zustand stores (NOT data fetching)
- `storefront-next:sfnext-authentication` - Auth context in loaders
## Reference Documentation
- [Loader Patterns Reference](references/LOADER-PATTERNS.md) - Data flow diagrams and advanced patterns
- [SCAPI Fetcher Reference](references/SCAPI-FETCHER.md) - Complete useScapiFetcher API and examples
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.