feat: switch to markdown content collections + remove emdash integration
- Remove emdash from astro.config.mjs (no more SSR/runtime) - Remove emdash + @astrojs/node from package.json - Switch output from 'server' to 'static' - Rewrite src/content.config.ts with 6 collections: pages, services, portfolio, faq, settings, blog - Keep live.config.ts as inert stub for build compat - Push new content from content-temp/pages/ into src/content/pages/ with full schema (title, subtitle, badge, hero_image, show_cta, cta_*, etc.) Build: 18 static pages, 0 errors
This commit is contained in:
@@ -2,26 +2,14 @@
|
|||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
import mdx from "@astrojs/mdx";
|
import mdx from "@astrojs/mdx";
|
||||||
import node from "@astrojs/node";
|
|
||||||
import emdash, { local } from "emdash/astro";
|
|
||||||
import { sqlite } from "emdash/db";
|
|
||||||
|
|
||||||
|
// All content is markdown → static output. No server runtime needed.
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: "server",
|
output: "static",
|
||||||
adapter: node({
|
|
||||||
mode: 'standalone'
|
|
||||||
}),
|
|
||||||
integrations: [
|
integrations: [
|
||||||
react(),
|
react(),
|
||||||
mdx(),
|
mdx(),
|
||||||
emdash({
|
|
||||||
database: sqlite({ url: "file:./data.db" }),
|
|
||||||
storage: local({
|
|
||||||
directory: "./uploads",
|
|
||||||
baseUrl: "/_emdash/api/media/file",
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
image: { layout: "constrained", responsiveStyles: true },
|
image: { layout: "constrained", responsiveStyles: true },
|
||||||
devToolbar: { enabled: true },
|
devToolbar: { enabled: true },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,10 +13,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^5.0.6",
|
"@astrojs/mdx": "^5.0.6",
|
||||||
"@astrojs/node": "^10.1.1",
|
|
||||||
"@astrojs/react": "^5.0.5",
|
"@astrojs/react": "^5.0.5",
|
||||||
"astro": "^6.2.2",
|
"astro": "^6.2.2",
|
||||||
"emdash": "^0.12.0",
|
|
||||||
"react": "^19.2.5",
|
"react": "^19.2.5",
|
||||||
"react-dom": "^19.2.5"
|
"react-dom": "^19.2.5"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,25 @@
|
|||||||
import { defineCollection, z } from 'astro:content';
|
import { defineCollection, z } from 'astro:content';
|
||||||
import { glob } from 'astro/loaders';
|
import { glob } from 'astro/loaders';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// PAGES — marketing page-level content (hero copy, badges, etc.)
|
||||||
|
// =============================================================================
|
||||||
|
const pages = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/pages' }),
|
||||||
|
schema: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
subtitle: z.string().optional(),
|
||||||
|
badge: z.string().optional(),
|
||||||
|
hero_image: z.string().optional(),
|
||||||
|
show_cta: z.boolean().optional().default(true),
|
||||||
|
cta_text: z.string().optional(),
|
||||||
|
cta_link: z.string().optional(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// SERVICES — service detail pages
|
||||||
|
// =============================================================================
|
||||||
const services = defineCollection({
|
const services = defineCollection({
|
||||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/services' }),
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/services' }),
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
@@ -9,9 +28,62 @@ const services = defineCollection({
|
|||||||
badge: z.string(),
|
badge: z.string(),
|
||||||
category: z.string(),
|
category: z.string(),
|
||||||
objective: z.string(),
|
objective: z.string(),
|
||||||
|
usp_free_server: z.string().optional(),
|
||||||
|
usp_content_edit: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// PORTFOLIO — client work
|
||||||
|
// =============================================================================
|
||||||
|
const portfolio = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/portfolio' }),
|
||||||
|
schema: z.object({
|
||||||
|
name: z.string(),
|
||||||
|
url: z.string().optional(),
|
||||||
|
category: z.string(), // webdev | ecommerce | marketing
|
||||||
|
category_label: z.string(),
|
||||||
|
industry: z.string().optional(), // NEW: industry for filtering
|
||||||
|
thumbnail: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
what_we_did: z.string().optional(), // NEW: separate from description
|
||||||
|
result: z.string().optional(), // NEW: outcome metric
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// FAQ
|
||||||
|
// =============================================================================
|
||||||
|
const faq = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/faq' }),
|
||||||
|
schema: z.object({
|
||||||
|
category: z.string(),
|
||||||
|
category_icon: z.string().optional(),
|
||||||
|
question: z.string(),
|
||||||
|
answer: z.string(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// SETTINGS — site identity & contact
|
||||||
|
// =============================================================================
|
||||||
|
const settings = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/settings' }),
|
||||||
|
schema: z.object({
|
||||||
|
site_name: z.string().optional(),
|
||||||
|
email: z.string().optional(),
|
||||||
|
phone: z.string().optional(),
|
||||||
|
address: z.string().optional(),
|
||||||
|
facebook: z.string().optional(),
|
||||||
|
line: z.string().optional(),
|
||||||
|
linkedin: z.string().optional(),
|
||||||
|
line_id: z.string().optional(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// BLOG (existing)
|
||||||
|
// =============================================================================
|
||||||
const blog = defineCollection({
|
const blog = defineCollection({
|
||||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
|
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
@@ -23,4 +95,11 @@ const blog = defineCollection({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const collections = { services, blog };
|
export const collections = {
|
||||||
|
pages,
|
||||||
|
services,
|
||||||
|
portfolio,
|
||||||
|
faq,
|
||||||
|
settings,
|
||||||
|
blog,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { defineLiveCollection } from "astro:content";
|
// live.config.ts — kept as a stub so Astro's runtime can import it,
|
||||||
import { emdashLoader } from "emdash/runtime";
|
// but no live collections are registered (we use markdown only via content.config.ts).
|
||||||
|
const collections = {};
|
||||||
// EmDash CMS Collections
|
export { collections };
|
||||||
export const collections = {
|
export default { collections };
|
||||||
_emdash: defineLiveCollection({ loader: emdashLoader() }),
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user