· Marvin Bangemann · tutorials · 3 min read

Chapter 2 - Crafting an Astro Website Using WordPress as a Headless CMS | API Configuration & Data Fetching

Step-by-step guide on integrating WordPress as a headless CMS for Astro projects

Step-by-step guide on integrating WordPress as a headless CMS for Astro projects

Following my initial discussion, this chapter delves into employing WordPress as a headless CMS for Astro, focusing on Advanced Custom Fields for content structuring. Initially straightforward, the challenge lies in bridging WordPress with Astro.

My development environment, a mirrored structure of WordPress themes synced via rsync across staging and production, emphasizes developer-centric workflow. By localizing changes to the theme folder, it enhances developer experience and simplifies WordPress use for non-developers. Fields managed through PHP in the theme folder ensure version control and clarity.

Essential Theme Files Overview

Organized as follows, the theme structure facilitates efficient management:

├── api/
│   ├── endpoints/
│   │   └── get_menu.php
│   └── endpoint-registration.php
├── blocks/
│   ├── textbox/
│   │   ├── acf.php
│   │   ├── block.json
│   │   └── preview.php
│   └── block-registration.php
├── config/
│   ├── block-access.php
│   ├── menus.php
│   └── setup.php
└── functions.php

functions.php Core Functionality

Central to theme operation, this file orchestrates the loading of various scripts.

// Include configuration files
require get_template_directory() . '/config/setup.php';
require get_template_directory() . '/config/block-access.php';
require get_template_directory() . '/config/menus.php';

// Include API endpoints and block methods
require get_template_directory() . '/api/endpoint-registration.php';
require get_template_directory() . '/blocks/block-registration.php';

Theme Setup in setup.php

Adjusts WordPress features to match project needs.

function wp_rest_setup() {
add_action('after_setup_theme', 'wp_rest_setup');

Block Access Management in block-access.php

Specifies block access based on user roles, enhancing content customization.

function wp_rest_define_block_groups() {
    $common_blocks = ['core/image', 'core/group', 'core/columns', 'acf/textbox'];
    $editor_blocks = array_merge($common_blocks, ['core/gallery']);
    $admin_blocks = array_merge($editor_blocks, ['core/code', 'core/html']);

    return ['administrator' => $admin_blocks, 'editor' => $editor_blocks, 'default' => $common_blocks];

function wp_rest_assign_block_groups($allowed_blocks, $post) {
    $block_groups = wp_rest_define_block_groups();
    $current_user = wp_get_current_user();

    return $block_groups[in_array('administrator', $current_user->roles) ? 'administrator' : (in_array('editor', $current_user->roles) ? 'editor' : 'default')];
add_filter('allowed_block_types_all', 'wp_rest_assign_block_groups', 10, 2);

Registers menus within the theme for controlled navigation management.

function wp_rest_register_menus() {
        'overlay_menu' => esc_html__('Main Navigation', 'wp-rest'),
        'header_submenu' => esc_html__('Sub Navigation', 'wp-rest'),
        'footer_menu' => esc_html__('Footer Navigation', 'wp-rest'),
        'footer_submenu' => esc_html__('Footer Sub Navigation', 'wp-rest'),
add_action('after_setup_theme', 'wp_rest_register_menus');

Block Registration Process in block-registration.php

Handles custom block registration, ensuring seamless integration.

require __DIR__ . '/textbox/acf.php';
require __DIR__ . '/textbox/preview.php';

function wp_rest_register_acf_blocks() {
    register_block_type(__DIR__ . '/textbox', [
        'render_callback' => 'textbox_block_render_callback',
add_action('init', 'wp_rest_register_acf_blocks');

Advanced Custom Fields Setup in acf.php

Defines field groups programmatically for API visibility. Dig into the ACF Documentation, or just export your ACF Field Groups via it’s GUI to PHP and have a look at the generated code. Alternatively you can stick with the GUI

Preview Functionality in preview.php

Offers a backend glimpse of custom blocks, aiding in layout decisions. Here’s an example of a preview for a simple text box block:

Block Preview

Custom API Endpoint Creation in endpoint-registration.php

Explored further in Chapter 3 - Navigation, this script introduces tailored REST API endpoints.

Linking Astro to WordPress

This segment outlines the pivotal step of connecting Astro to WordPress, focusing on API interactions and data presentation.

Secure API Authentication

Ensure WordPress credentials are securely stored for API communication.


Axios Client Setup

Demonstrates configuring Axios for API requests, adaptable to alternative libraries.

import axios from 'axios';

const config = {
  baseURL: import.meta.env.WORDPRESS_STAGING_URL + '/wp-json/wp/v2/',
  headers: {
    'Content-Type': 'application/json',
  auth: {
    username: import.meta.env.WORDPRESS_USER,
    password: import.meta.env.WORDPRESS_SECRET,

export const fetchApi = axios.create(config);

  (config) => config,
  (error) => Promise.reject(error)

Further exploration on fetching WordPress data within Astro will continue in Chapter 3 - Fetch your Navigation. Feel free to share questions or feedback in the comments section.

Back to Blog

Related Posts

View All Posts »