astro-php-ssr - Run PHP Routes Inside Astro

Posted by N.G. Onike on October 30, 2025 Software Technology Web Development

Bridging Two Worlds: Introducing astro-php-ssr - Run PHP Routes Inside Astro

If you've ever found yourself caught between the modern, blazing-fast world of Astro and the need to integrate legacy PHP code or leverage PHP's ecosystem, you're not alone. Today, I'm excited to introduce astro-php-ssr - a seamless integration that lets you run PHP routes directly inside your Astro SSR applications.

The Problem: Modern Frontend, Legacy Backend

Astro has revolutionized how we build content-focused websites. Its island architecture, zero-JS-by-default philosophy, and incredible performance make it a developer favorite. But what happens when you need to:

  • Integrate existing PHP APIs or services
  • Work with PHP-based CMSs or legacy systems
  • Leverage PHP libraries without rewriting everything in JavaScript
  • Gradually migrate a PHP application to a modern stack

Until now, you'd be stuck managing separate servers, dealing with CORS issues, or embarking on costly rewrites.

Enter astro-php-ssr

astro-php-ssr is a lightweight Astro integration that runs .php files directly inside your Astro SSR application using php-cgi or php as a fallback. No separate PHP server required. No complex proxy configurations. Just seamless PHP integration.

Key Features

Seamless Integration - Works with astro dev and production SSR
Full Request Support - Handles GET, POST, and other HTTP methods
Flexible Configuration - Customize PHP binary path and PHP file directory
Zero External Dependencies - Uses your existing PHP installation
TypeScript Support - Full type definitions included

Installation

Getting started is incredibly simple:

npm install astro-php-ssr

Or with your preferred package manager:

yarn add astro-php-ssr
# or
pnpm add astro-php-ssr

Prerequisites: You'll need php-cgi (preferred) or php installed on your system. Check with:

php-cgi -v
# or
php -v

Basic Usage

1. Configure Your Astro Project

First, add the integration to your astro.config.mjs:

import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
import astroPhpSSR from 'astro-php-ssr';

export default defineConfig({
  output: 'server',
  adapter: node({ mode: 'standalone' }),
  integrations: [
    astroPhpSSR({
      phpDir: './php',        // Where your PHP files live
      phpBinary: 'php-cgi'    // Or 'php' as fallback
    })
  ]
});

2. Create Your PHP Directory Structure

your-project/
├── php/
│   ├── api/
│   │   └── hello.php
│   └── contact.php
├── src/
│   └── pages/
│       └── index.astro
└── astro.config.mjs

3. Write Your PHP Routes

Create a simple API endpoint at php/api/hello.php:

<?php
header('Content-Type: application/json');

$name = $_GET['name'] ?? 'World';
echo json_encode([
    'message' => "Hello, $name!",
    'timestamp' => time()
]);

4. Access Your PHP Routes

Your PHP files are automatically served under /php/:

http://localhost:4321/php/api/hello.php?name=Astro

Response:

{
  "message": "Hello, Astro!",
  "timestamp": 1698624000
}

Real-World Examples

Example 1: Contact Form Handler

Create a contact form handler in php/contact.php:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'] ?? '';
    $email = $_POST['email'] ?? '';
    $message = $_POST['message'] ?? '';
    
    // Validate
    if (empty($name) || empty($email) || empty($message)) {
        http_response_code(400);
        echo json_encode(['error' => 'All fields are required']);
        exit;
    }
    
    // Process (send email, save to database, etc.)
    mail('admin@example.com', 'Contact Form', $message);
    
    echo json_encode(['success' => true]);
} else {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
}

Use it in your Astro component:

---
// src/pages/contact.astro
---

<form action="/php/contact.php" method="POST">
  <input type="text" name="name" placeholder="Your Name" required />
  <input type="email" name="email" placeholder="Your Email" required />
  <textarea name="message" placeholder="Your Message" required></textarea>
  <button type="submit">Send</button>
</form>

Example 2: WordPress REST API Bridge

Integrate WordPress content without exposing your WordPress installation:

<?php
// php/api/posts.php
$wp_url = 'https://your-wordpress-site.com';
$endpoint = '/wp-json/wp/v2/posts';

$response = file_get_contents($wp_url . $endpoint);
header('Content-Type: application/json');
echo $response;

Fetch in your Astro page:

---
// src/pages/blog.astro
const response = await fetch('http://localhost:4321/php/api/posts.php');
const posts = await response.json();
---

<div>
  {posts.map(post => (
    <article>
      <h2>{post.title.rendered}</h2>
      <div set:html={post.excerpt.rendered} />
    </article>
  ))}
</div>

Example 3: Database Operations

Access your MySQL database using PHP's native drivers:

<?php
// php/api/users.php
$db = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');

$stmt = $db->query('SELECT id, name, email FROM users LIMIT 10');
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);

header('Content-Type: application/json');
echo json_encode($users);

Advanced Configuration

Custom PHP Binary Path

If your PHP installation is in a non-standard location:

astroPhpSSR({
  phpDir: './php',
  phpBinary: '/usr/local/bin/php-cgi'
})

Multiple PHP Directories

You can structure your PHP files however you like within the phpDir:

php/
├── api/
│   ├── v1/
│   │   └── users.php
│   └── v2/
│       └── users.php
├── admin/
│   └── dashboard.php
└── public/
    └── info.php

Access them at:

  • /php/api/v1/users.php
  • /php/api/v2/users.php
  • /php/admin/dashboard.php
  • /php/public/info.php

Performance Considerations

astro-php-ssr spawns a PHP process for each request using CGI. While this works great for:

  • Low to moderate traffic sites
  • Development environments
  • Internal tools and dashboards
  • API endpoints that don't need millisecond response times

For high-traffic production applications, consider:

  • Caching PHP responses
  • Using PHP-FPM for long-running PHP processes
  • Rate limiting your PHP endpoints
  • Offloading heavy computation to background jobs

Use Cases

This integration shines in several scenarios:

  1. Legacy Integration: You have an existing PHP codebase and want to modernize the frontend without a complete rewrite

  2. Gradual Migration: You're moving from PHP to a modern stack and need both worlds to coexist

  3. PHP-Specific Libraries: You need functionality that's only available in PHP (certain payment gateways, legacy APIs, etc.)

  4. Content Management: Integrating with PHP-based CMSs like WordPress, Drupal, or custom systems

  5. Prototyping: Quickly spin up backend functionality using PHP's extensive ecosystem

Limitations & Considerations

  • Requires PHP: Your deployment environment must have php-cgi or php installed
  • CGI Performance: Each request spawns a new PHP process (consider PHP-FPM for production)
  • Session Management: PHP sessions work, but coordinate with Astro's session handling
  • File Uploads: Supported through standard PHP $_FILES handling

Deployment

Deploying to Vercel/Netlify

These platforms don't support PHP out of the box. Consider:

  • Using Vercel/Netlify for static Astro content
  • Deploying PHP portions to a PHP-friendly platform
  • Using serverless PHP options

Deploying to VPS/Traditional Hosting

This is where astro-php-ssr really shines:

  1. Ensure PHP is installed: sudo apt install php-cgi
  2. Build your Astro project: npm run build
  3. Run with Node: node dist/server/entry.mjs

Works perfectly on DigitalOcean, Linode, AWS EC2, or any VPS with Node.js and PHP.

Roadmap

Future enhancements I'm considering:

  • PHP-FPM support for better performance
  • Built-in caching layer
  • Request/response logging
  • Hot reload for PHP files in development
  • More granular error handling

Try It Yourself

Want to see it in action? Check out the live demo:

Run on Replit

Or install it in your project:

npm install astro-php-ssr

Conclusion

astro-php-ssr bridges the gap between Astro's modern, performant frontend architecture and PHP's mature, extensive ecosystem. Whether you're integrating legacy code, gradually migrating to a modern stack, or just need PHP's specific capabilities, this integration makes it seamless.

The web development landscape doesn't have to be all-or-nothing. Sometimes the best solution is bringing the best of both worlds together.


Links


Have you used astro-php-ssr in your project? I'd love to hear about your experience! Drop a comment below or open an issue on GitHub.

QUICK-SHARE :