mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 04:09:14 +00:00
fix(build): remove @netlify/functions dependency, use inline types
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { Handler, HandlerEvent, HandlerContext } from "@netlify/functions";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
@@ -9,8 +8,20 @@ import * as path from "path";
|
||||
* Returns text/plain with minimal headers for reliable AI ingestion.
|
||||
*/
|
||||
|
||||
// Inline types for Netlify Functions (avoids external dependency)
|
||||
interface HandlerEvent {
|
||||
path: string;
|
||||
httpMethod: string;
|
||||
}
|
||||
|
||||
interface HandlerResponse {
|
||||
statusCode: number;
|
||||
headers: Record<string, string>;
|
||||
body: string;
|
||||
}
|
||||
|
||||
// Response headers optimized for AI crawlers
|
||||
const AI_HEADERS = {
|
||||
const AI_HEADERS: Record<string, string> = {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Cache-Control": "public, max-age=3600",
|
||||
@@ -20,10 +31,7 @@ const AI_HEADERS = {
|
||||
// Extract slug from path like /api/raw/my-post or /.netlify/functions/raw/my-post
|
||||
function extractSlug(rawPath: string): string | null {
|
||||
// Handle both /api/raw/:slug and /.netlify/functions/raw/:slug patterns
|
||||
const patterns = [
|
||||
/^\/api\/raw\/(.+)$/,
|
||||
/^\/.netlify\/functions\/raw\/(.+)$/,
|
||||
];
|
||||
const patterns = [/^\/api\/raw\/(.+)$/, /^\/.netlify\/functions\/raw\/(.+)$/];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
const match = rawPath.match(pattern);
|
||||
@@ -59,10 +67,8 @@ function readMarkdownFile(slug: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handler: Handler = async (
|
||||
event: HandlerEvent,
|
||||
_context: HandlerContext,
|
||||
) => {
|
||||
// Netlify Function handler
|
||||
const handler = async (event: HandlerEvent): Promise<HandlerResponse> => {
|
||||
// Only allow GET requests
|
||||
if (event.httpMethod !== "GET") {
|
||||
return {
|
||||
@@ -103,4 +109,3 @@ const handler: Handler = async (
|
||||
};
|
||||
|
||||
export { handler };
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
"remark-gfm": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@netlify/functions": "^2.8.2",
|
||||
"@types/node": "^25.0.2",
|
||||
"@types/react": "^18.2.56",
|
||||
"@types/react-dom": "^18.2.19",
|
||||
|
||||
@@ -98,6 +98,7 @@ export default function Home() {
|
||||
<strong>
|
||||
An open-source publishing framework for AI agents and developers.
|
||||
</strong>{" "}
|
||||
<br />
|
||||
Write markdown, sync from the terminal. <br />
|
||||
<br />
|
||||
<a
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
BookOpen,
|
||||
Activity,
|
||||
} from "lucide-react";
|
||||
import { GithubLogo } from "@phosphor-icons/react";
|
||||
import { GithubLogo, Spinner } from "@phosphor-icons/react";
|
||||
import VisitorMap from "../components/VisitorMap";
|
||||
import siteConfig from "../config/siteConfig";
|
||||
|
||||
@@ -48,9 +48,27 @@ export default function Stats() {
|
||||
.catch(() => setGithubStars(null));
|
||||
}, []);
|
||||
|
||||
// Don't render until stats load
|
||||
// Show loading spinner while stats load
|
||||
if (stats === undefined) {
|
||||
return null;
|
||||
return (
|
||||
<div className="stats-page-wide">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
minHeight: "60vh",
|
||||
flexDirection: "column",
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<Spinner size={32} className="spinner-icon" />
|
||||
<p style={{ color: "var(--text-secondary)", fontSize: "0.875rem" }}>
|
||||
Loading statistics...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Stats card configuration with numbered sections
|
||||
|
||||
@@ -715,6 +715,20 @@ body {
|
||||
animation: dropdownFadeIn 0.15s ease;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
animation: spin 1s linear infinite;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
@keyframes dropdownFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
@@ -878,8 +892,8 @@ body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
@@ -896,6 +910,8 @@ body {
|
||||
}
|
||||
|
||||
.page-sidebar-expand svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
@@ -904,7 +920,7 @@ body {
|
||||
}
|
||||
|
||||
.page-sidebar-spacer {
|
||||
width: 20px;
|
||||
width: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -1012,17 +1028,17 @@ body {
|
||||
}
|
||||
|
||||
.page-sidebar-expand {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.page-sidebar-expand svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.page-sidebar-spacer {
|
||||
width: 18px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.page-sidebar-link {
|
||||
|
||||
Reference in New Issue
Block a user