Skip to content

Commit c9f1db5

Browse files
jmckinleyclaude
andcommitted
Fix API to use GitHub API instead of filesystem
Vercel serverless functions can't access static files directly. Now fetches blog posts from GitHub repo via API. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c51aa2c commit c9f1db5

1 file changed

Lines changed: 26 additions & 14 deletions

File tree

api/posts.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import fs from 'fs';
2-
import path from 'path';
1+
const REPO = 'kyliemckinleydemo/sandeep-khera-website';
2+
const BRANCH = 'main';
3+
const BLOG_PATH = 'content/blog';
34

45
function parseFrontMatter(content) {
56
const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -15,7 +16,6 @@ function parseFrontMatter(content) {
1516
currentKey = line.substring(0, colonIndex).trim();
1617
let value = line.substring(colonIndex + 1).trim();
1718

18-
// Remove quotes
1919
if ((value.startsWith('"') && value.endsWith('"')) ||
2020
(value.startsWith("'") && value.endsWith("'"))) {
2121
value = value.slice(1, -1);
@@ -30,15 +30,27 @@ function parseFrontMatter(content) {
3030
return metadata;
3131
}
3232

33-
export default function handler(req, res) {
33+
export default async function handler(req, res) {
3434
try {
35-
const blogDir = path.join(process.cwd(), 'content', 'blog');
36-
const files = fs.readdirSync(blogDir).filter(f => f.endsWith('.md'));
35+
// Get list of files in content/blog from GitHub
36+
const listUrl = `https://api.github.com/repos/${REPO}/contents/${BLOG_PATH}?ref=${BRANCH}`;
37+
const listResponse = await fetch(listUrl, {
38+
headers: { 'Accept': 'application/vnd.github.v3+json' }
39+
});
40+
41+
if (!listResponse.ok) {
42+
throw new Error(`GitHub API error: ${listResponse.status}`);
43+
}
3744

38-
const posts = files.map(filename => {
39-
const slug = filename.replace('.md', '');
40-
const filePath = path.join(blogDir, filename);
41-
const content = fs.readFileSync(filePath, 'utf-8');
45+
const files = await listResponse.json();
46+
const mdFiles = files.filter(f => f.name.endsWith('.md'));
47+
48+
// Fetch each markdown file's content
49+
const posts = await Promise.all(mdFiles.map(async (file) => {
50+
const slug = file.name.replace('.md', '');
51+
52+
const contentResponse = await fetch(file.download_url);
53+
const content = await contentResponse.text();
4254
const metadata = parseFrontMatter(content);
4355

4456
return {
@@ -50,15 +62,15 @@ export default function handler(req, res) {
5062
author: metadata.author || 'Sandeep Khera',
5163
tags: Array.isArray(metadata.tags) ? metadata.tags : []
5264
};
53-
});
65+
}));
5466

5567
// Sort by date (newest first)
5668
posts.sort((a, b) => new Date(b.date) - new Date(a.date));
5769

58-
res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
70+
res.setHeader('Cache-Control', 's-maxage=300, stale-while-revalidate=600');
5971
res.status(200).json(posts);
6072
} catch (error) {
61-
console.error('Error reading blog posts:', error);
62-
res.status(500).json({ error: 'Failed to load posts' });
73+
console.error('Error fetching blog posts:', error);
74+
res.status(500).json({ error: 'Failed to load posts', details: error.message });
6375
}
6476
}

0 commit comments

Comments
 (0)