CMS for React Native Apps: Content Over API Done Right

August 2, 2026 · 8 min read
CMS for React Native Apps: Content Over API Done Right

Every React Native app ships with content someone will want to change the week after release. Onboarding copy, FAQ screens, announcement banners, blog-style feeds. Hardcode them and each typo fix rides a full release train through app review. Put them behind a CMS and the marketing team edits Tuesday, users see it Tuesday.

The good news: a mobile app is just another API client, so any headless CMS technically works. The useful question is which ones fit the constraints phones add: flaky networks, offline expectations, and payloads you shouldn't make a 4G user download twice.

TL;DR: For React Native you want a CMS with a clean REST or GraphQL API, token auth that works from a mobile client, and webhooks to drive cache invalidation. Self-hosted options (UnfoldCMS, Strapi, Payload, Directus) avoid per-API-call pricing that mobile traffic patterns punish. Fetch content into a local cache (MMKV or SQLite via WatermelonDB), render from cache, refresh in the background. The CMS choice matters less than the caching pattern.


The Architecture That Works on Phones

Web apps can fetch on every page view. Mobile apps can't pretend the network is always there, so the standing pattern is cache-first:

  1. App launches and renders instantly from the local cache.
  2. A background fetch asks the CMS API for changes.
  3. New content lands in the cache; the UI updates when it makes sense (not mid-scroll).
  4. Offline sessions read cache alone and nobody notices.

The CMS's job in this picture is small and strict: serve JSON quickly, expose a "changed since" query so refreshes stay cheap, and never require the app to hold write-capable credentials.

// cache-first fetch, React Native + MMKV
const cached = storage.getString('posts');
if (cached) setPosts(JSON.parse(cached));

const res = await fetch('https://yoursite.com/api/v1/posts', {
  headers: { Accept: 'application/json' },
});
const fresh = await res.json();
storage.set('posts', JSON.stringify(fresh.data));
setPosts(fresh.data);

Public read endpoints keep secrets out of the binary entirely. Anything requiring auth should use a short-lived token from your own backend, never a CMS admin credential compiled into the app, because anything in the app bundle should be treated as public.


What Mobile Traffic Does to CMS Pricing

Here's the trap the pricing pages don't advertise. A website with 50,000 monthly visitors makes a predictable number of API calls. A mobile app with 50,000 installs makes wildly more: every launch is a refresh, push notifications spike traffic in minutes, and background fetches multiply everything.

SaaS headless platforms meter exactly this. Contentful's free tier caps at 100k API calls a month, which a modest app burns fast, and the next stop is $300/month. Usage-based tiers on other platforms turn a viral week into an invoice event.

Self-hosted flips the economics: your API's ceiling is your server, and content JSON behind a CDN (Cloudflare's free tier caches API responses fine) makes even launch-day spikes cheap. This is the single strongest argument for self-hosted CMS backends behind mobile apps, ahead of even the data-ownership one.


Platform Notes for React Native Teams

UnfoldCMS (ours; the bias disclosure applies) serves /api/v1 REST endpoints for posts, pages, categories, menus, search, and settings, with public read access for content and Sanctum tokens where auth is needed. HMAC-signed webhooks can notify your push service when content publishes, which is how "new post" notifications should work rather than polling. It runs on $5/month hosting with one-time pricing, and mobile API traffic costs nothing extra at any volume. The modeling limit from our other comparisons applies here too: four content types, not custom schemas. App backends needing arbitrary structures should look at the next two.

Strapi and Payload both model custom content types (level screens, product catalogs, whatever your app's domain needs) and both speak REST and GraphQL. You operate a Node process on a 2 GB VPS; the self-hosted headless comparison covers the running costs.

Directus shines when the app's content is really data: existing SQL tables become an API without re-modeling. Mind the BSL license threshold if you're building client apps as an agency.

Contentful and Sanity work well technically (their CDNs are genuinely fast) and their SDKs are polished. Price the API-call meters against your install projections first, and re-read the mobile traffic section above before trusting a free tier.


Publishing Flow: From CMS Edit to User's Screen

The part teams under-design. An editor hits publish; what happens on 50,000 phones?

The lazy answer (every app refetches on next launch) works and costs nothing. The better answer chains webhooks: CMS fires on publish → your tiny backend receives it (verify the HMAC signature) → it invalidates the CDN cache and, for content worth interrupting people over, sends a push through Expo Notifications or Firebase. Total code: under a hundred lines, and your content pipeline now matches apps ten times your size.

Marketing edits copy. Phones update. Nobody files a release.


Beyond Posts: Remote Config and Feature Copy

The blog feed is the obvious CMS use in an app. The higher-leverage one is quieter: all the copy and configuration you currently hardcode.

Think about what shipping a text change costs you today. The onboarding headline, the paywall pitch, the empty-state jokes, the "maintenance tonight" banner: each lives in the bundle, so each edit is a build, a review queue, and a staged rollout measured in days. Model them as CMS content instead (a settings endpoint or a keyed content type) and the app fetches them with the same cache-first pattern as everything else. Marketing rewrites the paywall copy Thursday morning; Thursday's sessions see it.

Two design rules keep this from becoming a foot-gun. Ship defaults in the bundle for every remote string, so a failed fetch degrades to yesterday's copy instead of blank screens. And version the config shape: when the app expects paywall.headline and an editor deletes the key, the default saves you, but when a new app version needs a new shape, key it (paywall.v2) so old installs keep reading the shape they understand.

Teams pay real money for dedicated remote-config services that are, underneath, a JSON endpoint with a cache. If your CMS already serves authenticated JSON with an editing UI and roles, you have the same machinery plus an audit trail of who changed the paywall copy before conversion dropped. That last part has settled more than one argument.

The pattern scales down honestly too: a solo developer with one app gets marketing-copy agility for zero extra infrastructure, which at that size matters more than any architectural point.


FAQ

Can I use a regular CMS for a React Native app?

If it exposes a JSON API, yes. Traditional CMSs without APIs (or with page-oriented HTML output) fight you; API-first and headless CMSs fit natively. The app consumes endpoints exactly like a web frontend would, plus caching.

How do I handle offline content in React Native?

Cache-first: persist fetched content in MMKV for small payloads or SQLite (WatermelonDB) for large collections, render from the cache always, refresh in the background. Users should never see a spinner for content they viewed yesterday.

Should the app talk to the CMS directly or through my backend?

Public content: directly to the CMS's read endpoints through a CDN, it's simpler and faster. Anything user-specific or write-capable: through your backend, which holds the credentials and issues its own short-lived tokens to the app.

What about images from the CMS on mobile?

Request sized variants rather than originals; a 3 MB hero image is a web sin and a mobile crime. Most CMS media libraries (ours included) generate conversions. Pair with a caching image component like expo-image and the bandwidth problem mostly disappears.

Does Expo work with headless CMS content?

Yes, identically to bare React Native: fetch JSON, cache it, render. Expo adds conveniences that fit the pattern well (expo-image for cached images, expo-notifications for publish-triggered pushes, background fetch APIs for refresh).

How often should the app refresh CMS content?

On launch plus pull-to-refresh covers most content apps. Add background fetch (15-minute minimum intervals on iOS) only for genuinely time-sensitive feeds, and let push notifications carry the urgent cases instead of polling.


Methodology

API pricing references vendor pages as of July 2026 (Contentful free tier: 100k calls/month, next tier $300/month). React Native patterns reflect current community-standard libraries: MMKV, WatermelonDB, and expo-image, per their public repositories. UnfoldCMS API capabilities (REST /api/v1, Sanctum auth, HMAC webhooks) reflect the live product documented at unfoldcms.com. We build UnfoldCMS; the cases where Strapi, Payload, or Directus fit a mobile backend better are stated because they're real.

Free & Open Source

Own your CMS. No subscriptions.

Unfold CMS is free to download and self-host. Built on Laravel + React, full source code included.

Share this post:

Discussion

Comments (0)

Leave a Comment

Please log in to leave a comment.

Don't have an account? Register here

No comments yet. Be the first to share your thoughts!

Keep Reading

Related Posts

Back to all posts