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:
Macky
2026-06-03 14:14:35 +07:00
parent b7787cc403
commit 0faf75a9a2
4 changed files with 88 additions and 25 deletions

View File

@@ -2,26 +2,14 @@
import { defineConfig } from 'astro/config';
import react from "@astrojs/react";
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({
output: "server",
adapter: node({
mode: 'standalone'
}),
output: "static",
integrations: [
react(),
mdx(),
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
image: { layout: "constrained", responsiveStyles: true },
devToolbar: { enabled: true },
});
});

View File

@@ -13,10 +13,8 @@
},
"dependencies": {
"@astrojs/mdx": "^5.0.6",
"@astrojs/node": "^10.1.1",
"@astrojs/react": "^5.0.5",
"astro": "^6.2.2",
"emdash": "^0.12.0",
"react": "^19.2.5",
"react-dom": "^19.2.5"
}

View File

@@ -1,6 +1,25 @@
import { defineCollection, z } from 'astro:content';
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({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/services' }),
schema: z.object({
@@ -9,9 +28,62 @@ const services = defineCollection({
badge: z.string(),
category: 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({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
schema: z.object({
@@ -23,4 +95,11 @@ const blog = defineCollection({
}),
});
export const collections = { services, blog };
export const collections = {
pages,
services,
portfolio,
faq,
settings,
blog,
};

View File

@@ -1,7 +1,5 @@
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
// EmDash CMS Collections
export const collections = {
_emdash: defineLiveCollection({ loader: emdashLoader() }),
};
// live.config.ts — kept as a stub so Astro's runtime can import it,
// but no live collections are registered (we use markdown only via content.config.ts).
const collections = {};
export { collections };
export default { collections };