Skip to main content
Our docs redesign is live!

AI agent migration playbook

5 min read

This chapter is written for AI coding agents. Developers can point an agent at this page when they want help migrating a project from the Contentstack JavaScript Delivery SDK to the TypeScript Delivery SDK.

Use it as an execution guide, not just a reference. Inspect the user's codebase first, make small scoped changes, preserve existing behavior, and verify the app with the project's own commands.

Agent instruction block

When a user asks you to migrate a project from the Contentstack JavaScript Delivery SDK to the TypeScript Delivery SDK:

  1. Read the repository before editing.

  2. Find all imports from contentstack.

  3. Identify the central Contentstack client or create one if SDK calls are scattered.

  4. Replace contentstack with @contentstack/delivery-sdk.

  5. Convert SDK chains from the JavaScript SDK API to the TypeScript Delivery SDK API.

  6. Do not convert the whole project to TypeScript unless the user explicitly asks.

  7. If files are JavaScript, keep examples and edits valid JavaScript.

  8. Preserve environment variable names unless a change is required.

  9. Preserve published, preview, locale, reference, asset, and cache behavior.

  10. Run the project's build, typecheck, lint, and tests when available.

  11. Summarize changed files, behavioral risks, and verification results.

The most important rule: this is an SDK migration, not a mandatory language migration.

Initial repository scan

Before editing, inspect the project shape:

rg "from ['\"]contentstack['\"]|require\\(['\"]contentstack['\"]\\)"
rg "Contentstack|contentstack|\\.ContentType\\(|\\.Entry\\(|\\.Query\\(|\\.Assets?\\("
rg "setCachePolicy|CachePolicy|language\\(|ascending\\(|descending\\(|toJSON\\("

Then inspect package scripts:

npm pkg get scripts

Use the repository's existing package manager if it is obvious. Prefer npm when installing dependencies unless the project clearly uses another package manager.

Package migration

Replace the old package:

npm uninstall contentstack
npm install @contentstack/delivery-sdk@latest

Install optional packages only when the existing app needs them:

npm install @contentstack/persistance-plugin@latest
npm install @contentstack/utils@latest

Use @contentstack/persistance-plugin only when the old implementation uses cache policies. Use @contentstack/utils only when the app uses Contentstack utility behavior such as rich text or embedded item helpers.

Core API translations

Apply these translations carefully:

JavaScript Delivery SDK

TypeScript Delivery SDK

import contentstack from 'contentstack'

import contentstack from '@contentstack/delivery-sdk'

contentstack.Stack(config)

contentstack.stack(config)

Stack.ContentType(uid)

stack.contentType(uid)

.Entry(uid)

.entry(uid)

.Query()

.entry().query()

Stack.Assets(uid) or Stack.Asset(uid)

stack.asset(uid)

.language(locale)

.locale(locale)

.ascending(field)

.orderByAscending(field)

.descending(field)

.orderByDescending(field)

.toJSON().fetch()

.fetch()

.toJSON().find()

.find()

Do not use blind search-and-replace for every chain. Read the call site and preserve whether it fetches one entry, a collection, an asset, a content type, or a sync result.

JavaScript-safe migration examples

For a JavaScript project, keep code valid JavaScript:

import contentstack from '@contentstack/delivery-sdk';

export const stack = contentstack.stack({
  apiKey: process.env.CONTENTSTACK_API_KEY,
  deliveryToken: process.env.CONTENTSTACK_DELIVERY_TOKEN,
  environment: process.env.CONTENTSTACK_ENVIRONMENT,
});

Do not add TypeScript-only syntax to .js files:

// Do not add this to JavaScript files.
const entry = await stack.contentType('page').entry(uid).fetch<PageEntry>();

Use the runtime call instead:

const entry = await stack.contentType('page').entry(uid).fetch();

Only add interfaces, generics, or non-null assertions in TypeScript files.

Common code transformations

Single entry:

// Before
const entry = await Stack.ContentType('page')
  .Entry(uid)
  .toJSON()
  .fetch();

// After
const entry = await stack.contentType('page')
  .entry(uid)
  .fetch();

Entry collection:

// Before
const entries = await Stack.ContentType('blog')
  .Query()
  .toJSON()
  .find();

// After
const entries = await stack.contentType('blog')
  .entry()
  .find();

Filtered query:

// Before
const entries = await Stack.ContentType('blog')
  .Query()
  .where('featured', true)
  .descending('published_date')
  .toJSON()
  .find();

// After
const entries = await stack.contentType('blog')
  .entry()
  .query()
  .equalTo('featured', true)
  .orderByDescending('published_date')
  .find();

Asset:

// Before
const asset = await Stack.Assets(assetUid)
  .toJSON()
  .fetch();

// After
const asset = await stack.asset(assetUid).fetch();

Locale and fallback:

const entry = await stack.contentType('page')
  .entry(uid)
  .locale('fr-fr')
  .includeFallback()
  .fetch();

Caching migration

If the old code uses setCachePolicy() or Contentstack.CachePolicy, configure cache options on the new stack client:

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',
    }),
  },
});

Avoid browser-only cache stores in server-only code paths. If the app renders on the server and client, check how the old code guarded access to browser APIs.

Troubleshooting flow

If initialization fails, check import, package installation, and stack config.

If one entry fetch works but listings fail, focus on Query() migration and sorting/filter helpers.

If content is missing in a locale, check language() to locale() migration and includeFallback() behavior.

If references disappear, check includeReference() and includeEmbeddedItems() chains.

If preview fails, test published delivery and preview delivery separately. Verify preview token, preview host, Live Preview settings, route handling, and runtime flags.

If cache behavior changes, check whether the persistence plugin is installed and whether the selected store is valid in the current runtime.

If TypeScript errors appear in JavaScript files, remove TypeScript-only syntax and keep the SDK calls plain JavaScript.

Completion criteria

The migration is complete when:

  • no app code imports the old contentstack package

  • package files include @contentstack/delivery-sdk

  • single-entry, collection, asset, content type, and sync calls are migrated where used

  • preview behavior is preserved where the project supports preview

  • cache and utility behavior are migrated only when needed

  • JavaScript projects remain JavaScript unless the user requested TypeScript conversion

  • build, typecheck, lint, and tests pass where available

  • the final response explains what changed and what was verified

Final response template for agents

When you finish, report:

  • files changed

  • package changes

  • SDK call patterns migrated

  • commands run and their results

  • any behavior that needs manual preview validation

  • any remaining old SDK references, or state that none remain

Keep the response short and concrete. The user needs to know whether the migration is ready to review and what still deserves attention.

Frequently asked questions

  • Does this migration require converting the project to TypeScript?

    No. Migrate the SDK usage while keeping the project language the same unless the user explicitly requests a TypeScript conversion.

  • What package changes are required for the migration?

    Uninstall the legacy contentstack package and install @contentstack/delivery-sdk. Add @contentstack/persistance-plugin and/or @contentstack/utils only if the existing app depends on caching or utility helpers.

  • What are the key API translations from the JavaScript SDK to the TypeScript Delivery SDK?

    Common changes include Stack() to stack(), ContentType() to contentType(), Entry() to entry(), Query() to entry().query(), and language() to locale(). Remove .toJSON() before fetch/find.

  • How should Query() chains be migrated for filters and sorting?

    Replace Query() with entry().query(), and translate helpers like descending() to orderByDescending() and ascending() to orderByAscending(). Validate each call site to preserve list vs single-entry behavior.

  • How do you migrate caching behavior that used setCachePolicy or CachePolicy?

    Configure cacheOptions on the new stack client and use Policy with an appropriate persistence store. Avoid browser-only stores (like localStorage) in server-only runtimes.