NativePress

Screens API Reference

The NativePress Screens API delivers fully-composed home screen layouts from WordPress to your Expo React Native app. Each screen is a named configuration containing an ordered list of blocks — sections of posts drawn from a WordPress category, rendered using a specific layout type (carousel, list, or hero).

Screens are configured visually in WP Admin → NativePress → App Screens Builder. The API reflects exactly what is saved there: block order, enabled/disabled state, post counts, and category assignments. No code changes are needed in the app when a screen is reconfigured in the admin.

Base URL — all endpoints are relative to your WordPress installation. Set WP_BASE_URL in constants/config.ts to your site root.

GET /wp-json/nativepress/v1/screens/{slug}

The {slug} segment matches the screen name you configure in the Screens Builder — for example home, discover, or trending.

Endpoints

GET /screens/{slug}

Returns the full screen object, including all enabled blocks and their resolved post objects. Use this as the primary data source for rendering a dynamic screen in your app.

GET /wp-json/nativepress/v1/screens/{slug}

Example: GET /wp-json/nativepress/v1/screens/home

JSON
{
  "slug": "home",
  "label": "Home",
  "blocks": [
    {
      "id": "1773330986098",
      "type": "carousel",
      "label": "Featured",
      "category_id": 48,
      "category_name": "Featured",
      "post_count": 10,
      "posts": [
        {
          "id": 12444,
          "title": "Love me tender, this song make you miss someone?",
          "slug": "love-me-tender-this-song-make-you-miss-someone",
          "date": "2026-03-12T05:12:07+00:00",
          "modified": "2026-03-12T05:16:00+00:00",
          "excerpt": "",
          "link": "https://toniai.com/featured/love-me-tender-this-song-make-you-miss-someone/",
          "author": {
            "id": 1,
            "display_name": "Toni",
            "avatar": "https://secure.gravatar.com/avatar/ae63c0e...?s=96&d=mm&r=g"
          },
          "categories": [
            { "id": 48, "name": "Featured", "slug": "featured" }
          ],
          "featured_image": {
            "thumbnail": "https://toniai.com/wp-content/uploads/2025/02/img_3447-1-150x150.png",
            "medium":    "https://toniai.com/wp-content/uploads/2025/02/img_3447-1-138x300.png",
            "large":     "https://toniai.com/wp-content/uploads/2025/02/img_3447-1-473x1024.png",
            "full":      "https://toniai.com/wp-content/uploads/2025/02/img_3447-1.png",
            "alt":       ""
          },
          "show_featured_image": true
        }
      ]
    },
    {
      "id": "1773333068082",
      "type": "hero",
      "label": "Hero",
      "category_id": 36,
      "category_name": "Entertainment",
      "post_count": 1,
      "posts": [
        {
          "id": 10307,
          "title": "18 Highest-Rated TV Seasons on IMDb",
          "slug": "18-highest-rated-tv-seasons-on-imdb",
          "date": "2026-03-12T04:52:56+00:00",
          "modified": "2026-03-12T05:16:00+00:00",
          "excerpt": "Television seasons that have received high ratings...",
          "link": "https://toniai.com/entertainment/18-highest-rated-tv-seasons-on-imdb/",
          "author": {
            "id": 1,
            "display_name": "Toni",
            "avatar": "https://secure.gravatar.com/avatar/ae63c0e...?s=96&d=mm&r=g"
          },
          "categories": [
            { "id": 36, "name": "Entertainment", "slug": "entertainment" }
          ],
          "featured_image": {
            "thumbnail": "https://toniai.com/wp-content/uploads/...-150x150.png",
            "medium":    "https://toniai.com/wp-content/uploads/...-300x168.png",
            "large":     "https://toniai.com/wp-content/uploads/...-1024x574.png",
            "full":      "https://toniai.com/wp-content/uploads/....png",
            "alt":       ""
          },
          "show_featured_image": true
        }
      ]
    }
  ]
}

Append ?structure_only=1 to receive block metadata without post data. Useful for prefetching layout before content loads.

Example: GET /wp-json/nativepress/v1/screens/home?structure_only=1

JSON
{
  "slug": "home",
  "label": "Home",
  "blocks": [
    {
      "id": "1773330986098",
      "type": "carousel",
      "label": "Featured",
      "category_id": 48,
      "category_name": "Featured",
      "post_count": 10
    },
    {
      "id": "1773333068082",
      "type": "hero",
      "label": "Hero",
      "category_id": 36,
      "category_name": "Entertainment",
      "post_count": 1
    }
  ]
}

Query parameters

Parameter Type Default Description
slug string Required. URL path segment identifying the screen (e.g. home).
structure_only 0 | 1 0 When 1, returns block metadata only. The posts array is omitted from every block.

JSON Schema

All field types and descriptions for the three objects returned by the Screens API.

Screen object

FieldTypeDescription
slug string Screen identifier matching the URL slug (e.g. "home").
label string Human-readable screen name displayed in the app header.
blocks Block[] Ordered array of enabled blocks as configured in the Screens Builder.

Block object

FieldTypeDescription
id string Unique block identifier (timestamp-based string). Stable across renames.
type "carousel" | "list" | "hero" Block layout type. Controls which component renders this block in the app.
label string Section heading shown above the block in the app.
category_id number WordPress category term ID. 0 means all categories.
category_name string Resolved category name. "All Posts" when category_id is 0.
post_count number Number of posts configured for this block (1–20).
posts Post[] Resolved post objects. Omitted when structure_only=1 is passed.

Post object

FieldTypeDescription
id number WordPress post ID.
title string Post title (decoded HTML entities).
slug string URL-friendly post slug.
date string Publish date in ISO 8601 format.
modified string Last modified date in ISO 8601 format.
excerpt string Post excerpt. May be empty string if no excerpt is set.
link string Full canonical permalink on the WordPress site.
author.id number Author user ID.
author.display_name string Author display name.
author.avatar string Gravatar URL at 96px. Always present (falls back to default Gravatar).
categories {id, name, slug}[] All categories this post belongs to.
featured_image object | null Image URLs for four sizes (thumbnail, medium, large, full) plus alt text. null if no featured image is set.
show_featured_image boolean Whether the app should display the featured image in the post detail view.

Block Types

Each block has a type field that tells the app which layout component to render. The three types cover the most common news/blog feed patterns.

carousel

Carousel

Horizontal scrollable card strip. Ideal for browsable topic categories or featured content.

Typical post_count: 5–10
Component: CarouselBlock
list

List

Vertical post cards with a section header. Standard chronological feed layout.

Typical post_count: 5–10
Component: ListBlock
hero

Hero

Single large feature card occupying the full width. Best for a highlighted or pinned article.

Typical post_count: 1
Component: HeroBlock

Dispatching block types — in the app, components/BlockRenderer.tsx switches on the block.type value and renders the appropriate component. Adding a new block type requires adding a new case to that switch and a corresponding component.

TypeScript Types

Drop this file into types/screens.ts in your Expo project. All API service functions and hooks reference these interfaces.

TypeScript — types/screens.ts
export type BlockType = 'carousel' | 'list' | 'hero';

export interface PostAuthor {
  id: number;
  display_name: string;
  avatar: string;
}

export interface PostCategory {
  id: number;
  name: string;
  slug: string;
}

export interface FeaturedImage {
  thumbnail: string;
  medium: string;
  large: string;
  full: string;
  alt: string;
}

export interface ScreenPost {
  id: number;
  title: string;
  slug: string;
  date: string;
  modified: string;
  excerpt: string;
  link: string;
  author: PostAuthor;
  categories: PostCategory[];
  featured_image: FeaturedImage | null;
  show_featured_image: boolean;
}

export interface ScreenBlock {
  id: string;
  type: BlockType;
  label: string;
  category_id: number;
  category_name: string;
  post_count: number;
  posts?: ScreenPost[];  // omitted when structure_only=1
}

export interface Screen {
  slug: string;
  label: string;
  blocks: ScreenBlock[];
}

API Service

Add getScreen() to your services/api.ts file. It fetches a screen by slug and returns a typed Screen promise. Errors are thrown so callers can handle them with try/catch or via the hook below.

TypeScript — services/api.ts
import { WP_BASE_URL } from '../constants/config';
import { Screen } from '../types/screens';

export async function getScreen(slug: string): Promise<Screen> {
  const response = await fetch(`${WP_BASE_URL}/wp-json/nativepress/v1/screens/${slug}`);
  if (!response.ok) {
    throw new Error(`Screen fetch failed: ${response.status}`);
  }
  return response.json();
}

WP_BASE_URL is the only value buyers need to change — set it to your WordPress site root (e.g. https://yoursite.com) in constants/config.ts. No trailing slash.

useScreen() Hook

A React hook that wraps getScreen() with loading, error, and refresh state. Place this in hooks/useScreen.ts and call it from any screen component. The refresh() function re-fetches without remounting the component.

TypeScript — hooks/useScreen.ts
import { useState, useEffect } from 'react';
import { Screen, ScreenBlock } from '../types/screens';
import { getScreen } from '../services/api';

interface UseScreenResult {
  screen: Screen | null;
  blocks: ScreenBlock[];
  loading: boolean;
  error: string | null;
  refresh: () => void;
}

export function useScreen(slug: string): UseScreenResult {
  const [screen, setScreen]   = useState<Screen | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError]     = useState<string | null>(null);
  const [tick, setTick]       = useState(0);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    getScreen(slug)
      .then((data) => { if (!cancelled) setScreen(data); })
      .catch((err) => { if (!cancelled) setError(err.message ?? 'Failed to load screen'); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [slug, tick]);

  return {
    screen,
    blocks: screen?.blocks ?? [],
    loading,
    error,
    refresh: () => setTick((t) => t + 1),
  };
}

Return values

PropertyTypeDescription
screen Screen | null The full screen object once loaded; null while loading or on error.
blocks ScreenBlock[] Convenience shorthand for screen.blocks. Empty array before load.
loading boolean true while the request is in flight (including on refresh).
error string | null Error message string if the request failed; otherwise null.
refresh () => void Call to re-fetch the screen. Triggers loading: true again.

Quick Reference

Everything you need at a glance.

TaskWhere / What
Configure screens & blocks WP Admin → NativePress → App Screens Builder
View endpoint URLs Screens Builder → select screen tab → "API Endpoints" box
Screen endpoint GET /wp-json/nativepress/v1/screens/{slug}
Structure-only endpoint GET /wp-json/nativepress/v1/screens/{slug}?structure_only=1
TypeScript types types/screens.ts
API function services/api.ts → getScreen(slug)
Data hook hooks/useScreen.ts → useScreen(slug)
Block dispatch components/BlockRenderer.tsx
Full screen component screens/DynamicScreen.tsx
WP option key nativepress_screens
GET /search Search posts and categories. Params: q (required), mode (full|suggest), per_page, page