Skip to content

Headless example ​

Pro

This example reads and updates a Book from a Node.js or browser front end, using an Application Password. It assumes the Book post type is in the REST API and its fields are exposed.

Reading a book ​

js
const SITE = "https://example.com";
const auth = "Basic " + btoa("api-user:xxxx xxxx xxxx xxxx xxxx xxxx");

async function getBook(id) {
  const res = await fetch(`${SITE}/wp-json/wp/v2/books/${id}?_fields=id,title,vx`, {
    headers: { Authorization: auth },
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(err.message || res.statusText);
  }
  const book = await res.json();
  const vx = book.vx || {};

  return {
    id: book.id,
    title: book.title?.rendered ?? "",
    tagline: vx.tagline ?? null,
    priceRange: vx.price_range?.label ?? null,   // choice: { value, label }
    cover: vx.photos?.[0]?.url ?? null,           // media object
    writers: (vx.writers || []).map((s) => ({ id: s.id, title: s.title, url: s.url })),
  };
}

Fields the user can't read are simply missing from vx, so always allow for a missing key.

Listing books ​

js
const res = await fetch(`${SITE}/wp-json/wp/v2/books?per_page=20&page=1&_fields=id,title,vx`, {
  headers: { Authorization: auth },
});
const books = await res.json();                  // each item has its own vx
const totalPages = Number(res.headers.get("X-WP-TotalPages"));

Updating a book ​

js
async function updateBook(id, values) {
  const res = await fetch(`${SITE}/wp-json/wp/v2/books/${id}`, {
    method: "POST",
    headers: { Authorization: auth, "Content-Type": "application/json" },
    body: JSON.stringify({ vx: values }),
  });
  const body = await res.json();
  if (!res.ok) {
    const details = body.data?.errors?.map((e) => `${e.path}: ${e.message}`).join("; ");
    throw new Error(details || body.message);
  }
  if (body.vx_warnings?.length) {
    console.warn("Saved with warnings:", body.vx_warnings);
  }
  return body.vx;
}

await updateBook(123, {
  tagline: "A novel of lost catalogues",
  price_range: "$$",        // write the value, not { value, label }
  photos: [88, 91],         // attachment IDs
});

The user behind the Application Password needs permission to edit the book. Writes are merged: only the keys you send change.

Technical details for LLMs
  • Read vx defensively: absent key = not readable or not exposed. Choices read { value, label }, write the value. Media reads objects, writes ids. See Field formats for every type.
  • Pagination: WordPress core headers X-WP-Total / X-WP-TotalPages; per_page ≤ 100.
  • Add ?vx_strict=1 to fail on warnings instead of logging them.

Documentation for the VX Framework.