Caching, utilities, preview behavior, and runtime differences
The base delivery migration is only part of the story. Many production apps also rely on cache policies, rich text rendering utilities, Live Preview, Visual Builder behavior, plugins, or runtime-specific imports. Move those pieces deliberately.
What you'll learn
How caching changes in the TypeScript Delivery SDK
When to install the persistence plugin
When to install the utilities package
How to think about Live Preview and Visual Builder during migration
What runtime behavior to check before shipping
Cache policies
In the JavaScript SDK, cache policy is commonly set directly on the stack or query:
Stack.setCachePolicy(Contentstack.CachePolicy.NETWORK_ELSE_CACHE);In the TypeScript Delivery SDK, caching uses a separate persistence plugin:
npm install @contentstack/persistance-plugin@latestThen configure cache options when creating the stack:
import contentstack, { Policy } from '@contentstack/delivery-sdk';
import PersistanceStore from '@contentstack/persistance-plugin';
export const stack = contentstack.stack({
apiKey: process.env.CONTENTSTACK_API_KEY,
deliveryToken: process.env.CONTENTSTACK_DELIVERY_TOKEN,
environment: process.env.CONTENTSTACK_ENVIRONMENT,
cacheOptions: {
policy: Policy.CACHE_THEN_NETWORK,
persistanceStore: new PersistanceStore({
storeType: 'localStorage',
}),
},
});If your app does not use caching, or if your policy is Policy.IGNORE_CACHE, you do not need the persistence plugin.
Utilities
If your JavaScript SDK code uses utility helpers for rich text, embedded entries, or rendering support, install the utilities package separately:
npm install @contentstack/utils@latestThen import it where rendering or transformation happens:
import * as Utils from '@contentstack/utils';Keep utilities out of your low-level stack client unless every request needs them. Rich text rendering and embedded item transformation usually belong close to rendering code or content normalization helpers.
Live Preview and Visual Builder
Live Preview and Visual Builder integrations often combine SDK configuration, preview tokens, host settings, URL handling, and frontend rendering behavior.
During migration, verify these flows separately from published delivery:
a normal published page load
a draft entry opened from the editorial interface
a locale-specific preview
a page that includes references
a page with rich text embedded items
a page composed from modular blocks
Do not assume that a successful published fetch() proves preview is working. Published delivery and preview behavior use different credentials and runtime conditions.
Plugins
If your JavaScript SDK setup uses custom plugins, move plugin setup into the new contentstack.stack() call:
class RequestPlugin {
onRequest(request) {
return request;
}
async onResponse(request, response) {
return response;
}
}
export const stack = contentstack.stack({
apiKey: process.env.CONTENTSTACK_API_KEY,
deliveryToken: process.env.CONTENTSTACK_DELIVERY_TOKEN,
environment: process.env.CONTENTSTACK_ENVIRONMENT,
plugins: [new RequestPlugin()],
});Use plugins for cross-cutting request behavior. Avoid hiding content modeling decisions or page-specific query logic inside plugins.
Browser and server runtimes
A delivery SDK can run in browser-based apps and server-rendered apps, but credentials and caching choices still matter.
Check these runtime details before shipping:
Are delivery credentials intentionally exposed to the browser?
Are preview tokens only exposed where preview actually needs them?
Does localStorage caching run only in browser contexts?
Does server-side rendering create one stack client safely?
Are environment variables available in the runtime that calls the SDK?
Does your bundler handle ESM imports from @contentstack/delivery-sdk?
If the app renders on both server and client, keep stack creation predictable and avoid accessing browser-only APIs while the server is importing modules.
Key takeaways
Caching is no longer only a stack method; use @contentstack/persistance-plugin when needed.
Install @contentstack/utils separately when your rendering code needs Contentstack utilities.
Verify preview flows separately from published delivery flows.
Keep browser-only cache stores out of server-only code paths.
Move custom plugins into the new contentstack.stack() configuration.
Frequently asked questions
How does caching change in the TypeScript Delivery SDK?
Caching is configured via the stack's cacheOptions and typically requires the @contentstack/persistance-plugin. Policies like Policy.CACHE_THEN_NETWORK are set during stack creation.
When do I need to install @contentstack/persistance-plugin?
Install it when you use caching with a persistence store (for example, localStorage). If you do not use caching or use Policy.IGNORE_CACHE, you do not need it.
When should I install @contentstack/utils?
Install @contentstack/utils when your app relies on utility helpers for rich text rendering, embedded entries, or content transformations. Keep it near rendering/normalization code rather than the low-level stack client.
What should I verify for Live Preview and Visual Builder during migration?
Test preview flows separately from published delivery, including draft opens, locale-specific previews, referenced content, rich text embedded items, and modular blocks. Preview uses different credentials and runtime conditions than published fetches.
What runtime issues should I check before shipping?
Ensure tokens are exposed only where intended, localStorage caching runs only in browsers, SSR creates stack clients safely, env vars exist at runtime, and your bundler supports ESM imports from @contentstack/delivery-sdk.