Skip to content

Props API doesn't work on deployed sites #214

@wise-king-sullyman

Description

@wise-king-sullyman

Problem Summary

The props API endpoints return 500 errors on deployed sites (Cloudflare Workers) while working correctly in local development environments.

Affected endpoints:

  • /props (src/pages/props.ts)
  • /api/[version]/[section]/[page]/props (src/pages/api/[version]/[section]/[page]/props.ts)

Error cause: These endpoints use Node.js filesystem APIs (readFileSync, process.cwd(), fs/promises) to read props.json at runtime, which are unavailable in Cloudflare Workers.

Root Cause

Both props endpoints have prerender = false and use Node.js filesystem operations:

// src/pages/api/[version]/[section]/[page]/props.ts:21-26
const config = await getConfig(`${process.cwd()}/pf-docs.config.mjs`)
const outputDir = config?.outputDir || join(process.cwd(), 'dist')
const propsFilePath = join(outputDir, 'props.json')
const propsDataFile = readFileSync(propsFilePath)  // ❌ Fails in Cloudflare Workers

The Astro config explicitly externalizes filesystem modules for Cloudflare compatibility:

// astro.config.mjs:14
external: ["node:fs", "node:path", "fs/promises", "path"]

Why other endpoints work: The CSS, examples, and other API endpoints use fetchApiIndex(url) which fetches apiIndex.json via HTTP instead of reading from the filesystem - this works in Cloudflare Workers.

Architecture Context

The build process generates static JSON files:

  • props.json - Component props data (generated by CLI's buildPropsData)
  • apiIndex.json - API routing/navigation data (generated by generateAndWriteApiIndex)

Both files are placed in the output directory (dist/) during build and deployed as static assets.

Working pattern:

// src/utils/apiIndex/fetch.ts
export async function fetchApiIndex(url: URL): Promise<ApiIndex> {
  const apiIndexUrl = new URL('/apiIndex.json', url.origin)
  const response = await fetch(apiIndexUrl)  // ✅ Works in Cloudflare Workers
  return await response.json()
}

Broken pattern:

// src/pages/props.ts
const propsDataFile = readFileSync(propsFilePath)  // ❌ Requires Node.js filesystem

Steps to Reproduce

  1. Deploy the docs to Cloudflare Workers
  2. Access props endpoint: /api/v6/components/alert/props
  3. Observe 500 error in production (works locally)

Completion Criteria

The issue is resolved when:

  1. Props endpoints work in Cloudflare Workers: All props API routes return data successfully in deployed environments
  2. HTTP-based file access: Props data is fetched via HTTP (like apiIndex.json) instead of filesystem operations
  3. Backward compatibility maintained: Local development and preview environments continue to work
  4. Consistent architecture: Props endpoints follow the same pattern as other API endpoints (CSS, examples, etc.)
  5. Remove filesystem dependencies: Eliminate usage of readFileSync, process.cwd(), and getConfig() from runtime API routes

Proposed Implementation

Create a fetchProps() helper similar to fetchApiIndex():

// src/utils/propsData/fetch.ts
export async function fetchProps(url: URL): Promise<PropsData> {
  const propsUrl = new URL('/props.json', url.origin)
  const response = await fetch(propsUrl)
  if (!response.ok) {
    throw new Error(`Failed to load props data: ${response.status}`)
  }
  return await response.json()
}

Then update both props endpoints to use this helper instead of filesystem operations.

Technical Notes

  • File locations: src/pages/props.ts:8-25 and src/pages/api/[version]/[section]/[page]/props.ts:21-26
  • The props.json file is already being built and deployed (visible in dist/props.json)
  • Reference implementation: src/utils/apiIndex/fetch.ts shows the working pattern
  • Both endpoints can remain prerender = false but must use HTTP fetch instead of filesystem reads

Related Links


Jira Issue: PF-3602

Metadata

Metadata

Labels

PF TeambugSomething isn't working

Type

No type

Projects

Status

Needs triage

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions