diff --git a/astro.config.mjs b/astro.config.mjs index 0c443c4..5836e36 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,11 +1,26 @@ // @ts-check import { defineConfig } from "astro/config"; +import sitemap from "@astrojs/sitemap"; import tailwindcss from "@tailwindcss/vite"; // https://astro.build/config export default defineConfig({ site: "https://www.bztmon.com", + integrations: [sitemap()], + build: { + // Keep CSS in external files (no inlined diff --git a/src/components/ProjectCard.astro b/src/components/ProjectCard.astro index b28ec24..f37a4ed 100644 --- a/src/components/ProjectCard.astro +++ b/src/components/ProjectCard.astro @@ -1,30 +1,30 @@ --- -import type { Project } from "../data/projects"; +import type { CollectionEntry } from "astro:content"; interface Props { - project: Project; + entry: CollectionEntry<"projects">; } -const { project } = Astro.props; -const href = project.hasCaseStudy ? `/projects/${project.slug}` : undefined; -const Tag = href ? "a" : "article"; +const { entry } = Astro.props; +const p = entry.data; +const href = `/projects/${entry.id}`; --- - +
-

{project.title}

- {href && } +

{p.title}

+
-

{project.outcome}

-

{project.summary}

+

{p.outcome}

+

{p.summary}

- {project.role}·{project.period} + {p.role}·{p.period}

-
+ diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro new file mode 100644 index 0000000..ce6fcaf --- /dev/null +++ b/src/pages/blog/index.astro @@ -0,0 +1,52 @@ +--- +import Layout from "../../layouts/Layout.astro"; +import Section from "../../components/Section.astro"; +import PostList from "../../components/PostList.astro"; +import { getPosts, allTags } from "../../lib/blog"; + +const posts = await getPosts(); +const tags = allTags(posts); +--- + + +
+

+ Lessons from edge Kubernetes, GPUs, and running infrastructure like it matters. +

+ + {tags.length > 0 && ( + + )} + + +
+
+ + diff --git a/src/pages/blog/tags/[tag].astro b/src/pages/blog/tags/[tag].astro new file mode 100644 index 0000000..cdfe308 --- /dev/null +++ b/src/pages/blog/tags/[tag].astro @@ -0,0 +1,33 @@ +--- +import Layout from "../../../layouts/Layout.astro"; +import Section from "../../../components/Section.astro"; +import PostList from "../../../components/PostList.astro"; +import { getPosts, allTags } from "../../../lib/blog"; +import type { GetStaticPaths } from "astro"; + +export const getStaticPaths = (async () => { + const posts = await getPosts(); + const tags = allTags(posts); + return tags.map((tag) => ({ + params: { tag }, + props: { tag, posts: posts.filter((p) => p.data.tags.includes(tag)) }, + })); +}) satisfies GetStaticPaths; + +const { tag, posts } = Astro.props; +--- + + +
+

+ ← All posts +

+ +
+
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro index f16323e..da54114 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -7,7 +7,11 @@ import SkillGroup from "../components/SkillGroup.astro"; import ProjectCard from "../components/ProjectCard.astro"; import Contact from "../components/Contact.astro"; import { skills } from "../data/skills"; -import { featuredProjects } from "../data/projects"; +import { getCollection } from "astro:content"; + +const featuredProjects = (await getCollection("projects", (p) => p.data.featured)).sort( + (a, b) => a.data.order - b.data.order, +); --- @@ -25,7 +29,7 @@ import { featuredProjects } from "../data/projects";
- {featuredProjects.map((project) => )} + {featuredProjects.map((entry) => )}

All projects → diff --git a/src/pages/projects/[slug].astro b/src/pages/projects/[slug].astro new file mode 100644 index 0000000..d8da119 --- /dev/null +++ b/src/pages/projects/[slug].astro @@ -0,0 +1,105 @@ +--- +import Layout from "../../layouts/Layout.astro"; +import { getCollection, render } from "astro:content"; +import type { GetStaticPaths } from "astro"; + +export const getStaticPaths = (async () => { + const projects = await getCollection("projects"); + return projects.map((entry) => ({ params: { slug: entry.id }, props: { entry } })); +}) satisfies GetStaticPaths; + +const { entry } = Astro.props; +const p = entry.data; +const { Content } = await render(entry); +--- + + +

+
+ ← All projects + +
+

Case study

+

{p.title}

+

{p.outcome}

+ +

+ {p.role}·{p.period} +

+ +
    + {p.stack.map((s) =>
  • {s}
  • )} +
+ + {p.links && ( + + )} +
+ +
+ +
+
+
+ + + diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro index 3ed7343..6f997a5 100644 --- a/src/pages/projects/index.astro +++ b/src/pages/projects/index.astro @@ -2,24 +2,28 @@ import Layout from "../../layouts/Layout.astro"; import Section from "../../components/Section.astro"; import ProjectCard from "../../components/ProjectCard.astro"; -import { projects } from "../../data/projects"; +import { getCollection } from "astro:content"; + +const projects = (await getCollection("projects")).sort( + (a, b) => a.data.order - b.data.order, +); ---

- Edge Kubernetes, GPU inference, self-hosted AI, and the automation that ties - it together. Full case studies are on the way. + Edge Kubernetes, GPU inference, self-hosted AI, and the automation that ties it + together — each with the problem, the design, and the outcome.

- {projects.map((project) => )} + {projects.map((entry) => )}