Claude Skills Guide

Claude Code for Astro Server Endpoints Workflow

Astro’s server endpoints (also known as API routes) enable you to build full-stack applications with the same elegant developer experience that makes Astro famous for static sites. When combined with Claude Code, you get AI-assisted development for your backend logic, data handling, and API implementations. This guide walks you through practical workflows for creating and managing server endpoints in Astro using Claude Code.

Understanding Astro Server Endpoints

Astro supports multiple rendering modes that determine how your endpoints work. In Astro 5.0 and later, you can choose between static site generation (SSG), server-side rendering (SSR), and hybrid rendering. For server endpoints, you’ll primarily work with SSR or hybrid mode, where your API routes run on the server at request time.

Server endpoints in Astro follow a simple file-based routing system. Place your endpoint files in the src/pages directory with appropriate extensions like .ts, .js, or .tsx (if using React). The filename determines the route—for example, src/pages/api/users.ts becomes /api/users.

When you need AI assistance for building these endpoints, Claude Code can help generate the implementation, handle error cases, and suggest best practices. The key is knowing how to prompt Claude effectively for server-side code.

Setting Up Your Astro Project for Server Endpoints

Before creating server endpoints, ensure your Astro project is configured for server-side rendering. Start by adding the server adapter for your deployment platform:

npx astro add node

This command installs the Node.js adapter and updates your astro.config.mjs. For other platforms like Vercel or Netlify, use their respective adapters (npx astro add vercel or npx astro add netlify).

After adding the adapter, enable SSR in your configuration:

import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: 'standalone'
  })
});

With this setup, you can now create API endpoints that handle dynamic requests.

Creating Your First Server Endpoint

Create a basic endpoint to understand the pattern. In src/pages/api/health.ts:

export const GET = async () => {
  return new Response(JSON.stringify({
    status: 'ok',
    timestamp: new Date().toISOString()
  }), {
    status: 200,
    headers: {
      'Content-Type': 'application/json'
    }
  });
};

This endpoint returns a JSON response with health status. When working with Claude Code, you can generate more complex endpoints by describing your requirements clearly.

Prompting Claude for Endpoint Development

Effective prompting makes a significant difference when Claude Code generates your server endpoints. Instead of vague requests, provide specific details about your API requirements.

For example, instead of:

Create an API endpoint for users

Use:

Create a TypeScript API endpoint at src/pages/api/users.ts that:
- Returns a list of users with pagination (page, limit query params)
- Includes error handling for invalid parameters
- Returns users with id, name, email, createdAt fields
- Uses proper HTTP status codes

Claude will generate a comprehensive implementation that handles edge cases you might have missed.

Working with Request Data

Server endpoints often need to handle request bodies, query parameters, and headers. Here’s how Claude Code can help you manage these:

Handling Query Parameters

export const GET = async ({ url }) => {
  const page = parseInt(url.searchParams.get('page') || '1');
  const limit = parseInt(url.searchParams.get('limit') || '10');
  
  if (isNaN(page) || page < 1) {
    return new Response(JSON.stringify({
      error: 'Invalid page parameter'
    }), { status: 400, headers: { 'Content-Type': 'application/json' } });
  }
  
  // Fetch data with pagination
  const users = await fetchUsers(page, limit);
  
  return new Response(JSON.stringify(users), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });
};

Handling Request Bodies

For POST, PUT, and PATCH requests:

export const POST = async ({ request }) => {
  try {
    const data = await request.json();
    
    // Validate required fields
    if (!data.name || !data.email) {
      return new Response(JSON.stringify({
        error: 'Missing required fields: name, email'
      }), { status: 400, headers: { 'Content-Type': 'application/json' } });
    }
    
    // Create user
    const newUser = await createUser(data);
    
    return new Response(JSON.stringify(newUser), {
      status: 201,
      headers: { 'Content-Type': 'application/json' }
    });
  } catch (error) {
    return new Response(JSON.stringify({
      error: 'Failed to create user'
    }), { status: 500, headers: { 'Content-Type': 'application/json' } });
  }
};

When prompting Claude for these patterns, specify the validation rules and error handling requirements explicitly.

Integrating with Databases and External APIs

Server endpoints become powerful when connecting to databases. Here’s a practical pattern for database integration:

// src/pages/api/products.ts
export const GET = async ({ url }) => {
  const category = url.searchParams.get('category');
  
  let query = 'SELECT * FROM products';
  const params: any[] = [];
  
  if (category) {
    query += ' WHERE category = $1';
    params.push(category);
  }
  
  const result = await db.query(query, params);
  
  return new Response(JSON.stringify(result.rows), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });
};

For more complex database operations, ask Claude to implement proper patterns:

Authentication and Authorization

Protecting your endpoints is crucial. Claude Code can help implement proper auth patterns:

import { verifyToken } from '../../lib/auth';

export const GET = async ({ request }) => {
  const authHeader = request.headers.get('Authorization');
  
  if (!authHeader?.startsWith('Bearer ')) {
    return new Response(JSON.stringify({
      error: 'Missing or invalid authorization header'
    }), { status: 401, headers: { 'Content-Type': 'application/json' } });
  }
  
  const token = authHeader.substring(7);
  const user = await verifyToken(token);
  
  if (!user) {
    return new Response(JSON.stringify({
      error: 'Invalid or expired token'
    }), { status: 403, headers: { 'Content-Type': 'application/json' } });
  }
  
  // User is authenticated, proceed with protected logic
  const data = await fetchUserData(user.id);
  
  return new Response(JSON.stringify(data), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });
};

When implementing authentication, specify your auth provider (JWT, session-based, OAuth) in your prompts to Claude.

Best Practices for Server Endpoints

Follow these practices when building with Claude Code assistance:

  1. Always validate input: Request parameters and body data should be validated before processing.

  2. Use appropriate HTTP status codes: 200 for success, 201 for creation, 400 for bad requests, 401 for unauthorized, 404 for not found, 500 for server errors.

  3. Set proper headers: Include Content-Type: application/json for JSON responses.

  4. Handle errors gracefully: Return meaningful error messages without exposing internal details.

  5. Implement rate limiting: Protect your endpoints from abuse.

  6. Log appropriately: Use structured logging for debugging and monitoring.

When prompting Claude Code, reference these practices to ensure they’re incorporated in the generated code.

Testing Your Endpoints

Claude Code can help generate tests for your endpoints. Request test implementations that cover:

// Example test structure Claude can generate
describe('API /api/users', () => {
  it('should return users with pagination', async () => {
    const response = await fetch('/api/users?page=1&limit=10');
    expect(response.status).toBe(200);
    const data = await response.json();
    expect(data).toHaveProperty('users');
  });
  
  it('should return 400 for invalid page', async () => {
    const response = await fetch('/api/users?page=-1');
    expect(response.status).toBe(400);
  });
});

Conclusion

Building server endpoints in Astro with Claude Code combines the best of both worlds—Astro’s elegant developer experience and AI-assisted coding. By understanding the endpoint patterns, providing specific prompts, and following best practices, you can rapidly develop robust APIs for your applications.

The key is to be explicit about your requirements when working with Claude Code, specify the data models and validation rules, and ensure proper error handling is always implemented. With these workflows, you’ll build production-ready server endpoints efficiently.

Built by theluckystrike — More at zovo.one