CMS & Content Infrastructure

WeChat Mini Program with a Headless CMS: Strapi Integration Tutorial

Step-by-step: connecting a WeChat Mini Program to Strapi as a headless CMS, covering auth, content API, media and caching.

A WeChat Mini Program can read content from Strapi through its REST API, but the setup is not simply a matter of adding a fetch call. You need to decide which content is public, configure WeChat’s request-domain rules, and keep private credentials out of the Mini Program. Follow these steps to create a small, testable integration and avoid the common deployment traps.

1. Define the content and access rules

Start by deciding what the Mini Program needs to display and who is allowed to see it. A product listing might need a name, description, price and cover image; an account-specific order or unpublished editorial content needs access controls. Write down which fields are public, which need a signed-in user, and how frequently information such as price or stock can change.

In Strapi, create the content type and add only the fields the Mini Program needs. Keep the first version focused: returning extra fields increases the amount of data sent and makes it easier to expose information unintentionally. For a product collection, confirm whether the content is published and whether its media field is included in the API response.

Done looks like: you can name each screen’s content, its fields and its access rule before writing client code.

Common mistake: treating “available in the admin panel” as equivalent to “available through the API.” Content must be published, and the relevant API permissions must allow the intended request.

2. Prepare Strapi’s API and permissions

Strapi generates REST endpoints for content types. In Strapi’s REST API, a product collection is requested from /api/products. To include a media field called cover, request it explicitly:

/api/products?populate[cover]=true

For content that is genuinely public, configure read access for the relevant collection and test the endpoint without an administrator’s credentials. Do not grant broad access just to make a test pass. If the response contains more content than the Mini Program should expose, change the permissions or content design before connecting the client.

For private content, do not put a Strapi API token in the Mini Program. The app runs on a user’s device, so a token included in its files can be extracted. Instead, put a trusted server between the Mini Program and Strapi. That server can verify the user’s identity, decide what they may access, then make the Strapi request using a credential stored on the server. If your sign-in flow uses WeChat, perform the credential exchange and verification on the server as well; the client should not be trusted to assert a user’s identity.

Done looks like: a public endpoint returns only approved public fields without a secret, while private requests go through a server that checks access.

Common mistake: using an all-powerful API token in client code because it is quick to set up. That turns a content integration into a credential exposure risk.

3. Configure the Mini Program’s request domain

Before testing a deployed Mini Program, add the API host to the request-domain settings in the WeChat Mini Program administration tools. Use the production HTTPS host, not a local development address. The host must be reachable from the Mini Program’s environment, and its TLS certificate must be valid.

This is different from the CORS problem often seen in browser applications. Mini Programs do not make requests as a normal browser page, so changing Strapi’s CORS settings is not the usual fix for a rejected Mini Program request. Check the domain allowlist, the exact API hostname, the certificate and the server’s availability first. For local development, use the development tools’ available testing options; do not assume a local URL will work after release.

Keep the API host in one environment setting rather than scattering it through page code. Use the production host in the released build and a separate development setting while testing. This makes it less likely that a test address or an insecure connection ends up in the release.

Done looks like: a simple request to the production API host succeeds in the Mini Program after that host has been approved.

Common mistake: allowing every origin in Strapi to work around a domain allowlist issue. It does not approve a host in WeChat, and it can widen access unnecessarily.

The step people most often skip is checking the deployed domain rules before debugging the content API. A correct endpoint cannot compensate for a host the Mini Program is not allowed to contact.

4. Make a small request from the Mini Program

Start with a read-only request and inspect the response before connecting it to a screen. In Strapi’s current response format, content fields are available on each item’s attributes-free data object, so avoid copying examples written for older response shapes without checking them against your Strapi version.

const apiBase = getApp().globalData.apiBase;

wx.request({
  url: `${apiBase}/api/products?populate[cover]=true`,
  method: 'GET',
  success: (response) => {
    if (response.statusCode !== 200) {
      console.error('Product request failed', response.statusCode);
      return;
    }

    const products = response.data.data;
    console.log(products);
  },
  fail: (error) => {
    console.error('Network request failed', error);
  }
});

Keep the success and failure paths distinct. A request can reach the server and still receive an error response, which is not the same as a network failure. During development, inspect the status and response shape; in the user interface, show a useful empty or error state rather than leaving the page blank.

If your app needs protected data, send the user’s session information to your trusted server and have that server call Strapi. Never add a Strapi secret to the request above. Also avoid logging personal or confidential response data in production logs.

Done looks like: the Mini Program receives the expected published records, handles an empty result, and displays a useful message if the request fails.

Common mistake: treating a successful network connection as proof that the response has the fields the page expects. Check the actual response and handle missing or unpublished content.

5. Render media using a reachable address

Populating a media field gives the Mini Program media information, but an image still needs a usable address. Strapi may return a relative media path, so combine it with the public base address of the media host when needed. If you use a separate file service or content delivery network, make sure that address is also configured for requests in WeChat.

Use the returned media URL rather than constructing a file path from a product name or ID. Content editors may replace an image, and a guessed path can break without warning. Test images on the actual Mini Program environment, not only in a desktop browser: the browser may be able to load a host that the Mini Program has not approved.

Plan for missing media. Products without a cover should still render clearly, and a failed image request should not prevent the rest of the page from appearing. For large collections, load only the fields and images needed for the current view rather than downloading every image at once.

Done looks like: a published item with an image displays correctly in the Mini Program, and an item without one still has a sensible presentation.

Common mistake: testing the text API response but never checking whether the returned image host is reachable from the released app.

6. Add caching and test the release path

Caching can make frequently viewed public content quicker to retrieve and reduce repeated requests, but cached data can also become misleading. Decide which content may be a little out of date. An evergreen article may be suitable for longer-lived caching; a product’s price or stock may need a much shorter cache policy or a request that checks for updates. Do not apply one rule to every content type.

You can keep a previously received public response on the device to show content while a fresh request is loading or unavailable. Replace it when a successful response arrives, and provide a way for the app to refresh it. For server-side or delivery-network caching, set rules for what can be cached and how updates invalidate the stored copy. Never share one user’s private response through a cache used for other users.

Before release, test the full path: published content in Strapi, the deployed API, the approved request domain, media loading, permissions, and the Mini Program’s error states. Check what happens when content is unpublished or a media file is removed. If prices or stock drive a purchase decision, confirm that the checkout process validates the current value rather than trusting a value cached on the device.

Done looks like: the Mini Program remains usable when a request fails, public content refreshes according to its business needs, and private information is not cached across users.

Common mistake: treating caching as a speed setting alone. It is also a decision about how stale information may be and whether the information is safe to reuse.

How we approach this in practice

A headless CMS is useful when your team needs to update content independently of a release, but it should not be added just because the Mini Program needs an API. PixelHorizon’s TanosMotorsport case study describes a decoupled storefront with a reusable e-commerce engine; product prices and stock refresh without a redeploy. For the broader delivery approach, see how PixelHorizon takes software from architecture through support, or review PixelHorizon’s software and platform services.

Bottom line

Tomorrow, write down which fields are public and which require a signed-in user, then test one published Strapi record through the Mini Program’s approved HTTPS domain. Keep Strapi credentials on a trusted server, populate and verify media explicitly, and choose cache rules based on how current each piece of content must be. If public read access and a direct API call are enough, keep the first version simple.