From 7e5e17bde1a44b9fb18aba7bb16639f4ea9ada8b Mon Sep 17 00:00:00 2001 From: scadmin Date: Sun, 14 Dec 2025 22:18:10 +0000 Subject: [PATCH] Added blog drafts and ui for posting them. --- public/admin/config.yml | 26 +++++++ src/content/config.ts | 21 ++++++ src/pages/admin.html | 13 ++++ src/pages/blog/[...slug].astro | 14 ++-- src/pages/blog/index.astro | 132 ++++++++++----------------------- src/pages/index.astro | 45 +++++++++-- 6 files changed, 147 insertions(+), 104 deletions(-) create mode 100644 public/admin/config.yml create mode 100644 src/content/config.ts create mode 100644 src/pages/admin.html diff --git a/public/admin/config.yml b/public/admin/config.yml new file mode 100644 index 0000000..fcdfc52 --- /dev/null +++ b/public/admin/config.yml @@ -0,0 +1,26 @@ +backend: + name: gitea + repo: scadmin/seans-cloud # / + branch: main + app_id: "607244b1-2313-478b-bd25-40b224c66617" + base_url: "https://git.seans.cloud" # or https://:3000 + api_root: "https://git.seans.cloud/api/v1" + auth_endpoint: "https://git.seans.cloud/login/oauth/authorize" + +site_url: "https://seans.cloud" + +media_folder: "src/assets/images/uploads" +public_folder: "/src/assets/images/uploads" + +collections: + - name: "blog" + label: "Blog" + folder: "src/content/blog" + create: true + slug: "{{slug}}" + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Publish Date", name: "date", widget: "datetime" } + - { label: "Description", name: "description", widget: "text", required: false } + - { label: "Draft", name: "draft", widget: "boolean", default: false, required: false } + - { label: "Body", name: "body", widget: "markdown" } diff --git a/src/content/config.ts b/src/content/config.ts new file mode 100644 index 0000000..8763547 --- /dev/null +++ b/src/content/config.ts @@ -0,0 +1,21 @@ +import { defineCollection, z } from "astro:content"; + +const blog = defineCollection({ + type: "content", + schema: z.object({ + title: z.string(), + description: z.string().optional(), + pubDate: z.coerce.date(), + updatedDate: z.coerce.date().optional(), + draft: z.boolean().optional().default(false), + // Optional if you use hero images in your layout: + heroImage: z + .object({ + src: z.string(), + alt: z.string().optional(), + }) + .optional(), + }), +}); + +export const collections = { blog }; diff --git a/src/pages/admin.html b/src/pages/admin.html new file mode 100644 index 0000000..7f24df7 --- /dev/null +++ b/src/pages/admin.html @@ -0,0 +1,13 @@ + + + + + + + + Content Manager + + + + + diff --git a/src/pages/blog/[...slug].astro b/src/pages/blog/[...slug].astro index 0754ea7..b8ed93b 100644 --- a/src/pages/blog/[...slug].astro +++ b/src/pages/blog/[...slug].astro @@ -4,14 +4,18 @@ import BlogPost from '../../layouts/BlogPost.astro'; export async function getStaticPaths() { const posts = await getCollection('blog'); - return posts.map((post) => ({ - params: { slug: post.id }, - props: post, - })); + + return posts + .filter((post) => !(post.data as { draft?: boolean }).draft) + .map((post) => ({ + params: { slug: post.id }, + props: post, + })); } + type Props = CollectionEntry<'blog'>; -const post = Astro.props; +const post = Astro.props as Props; const { Content } = await render(post); --- diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 5b08c9f..be27000 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -1,113 +1,59 @@ --- -import { Image } from 'astro:assets'; -import { getCollection } from 'astro:content'; import BaseHead from '../../components/BaseHead.astro'; import Footer from '../../components/Footer.astro'; -import FormattedDate from '../../components/FormattedDate.astro'; import Header from '../../components/Header.astro'; import { SITE_DESCRIPTION, SITE_TITLE } from '../../consts'; -const posts = (await getCollection('blog')).sort( - (a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(), -); +import { getCollection } from 'astro:content'; + +const posts = (await getCollection('blog')) + .filter((p) => !(p.data as { draft?: boolean }).draft) + .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()); --- - - +
-
+

Sean's Cloud!

+

Infrastructure • Cloud • Systems Thinking • Leadership

+ +

+ seans.cloud is an evolving space focused on building, testing, and refining modern IT and cloud practices with an eye toward what’s next. It serves as a foundation for future projects in cloud architecture, automation, security, and operational excellence—along with the leadership thinking that supports sustainable systems. +

+

+ As this site grows, it will become a place to share practical insights, real-world experiments, and lessons learned from working with infrastructure at scale. Future content may include technical guides, architecture patterns, tooling evaluations, and perspectives on how technology, process, and people intersect to create resilient organizations. +

+ +

On this site you’ll find:

+
    +
  • Technical experiments and lab notes
  • +
  • Cloud and infrastructure architecture thinking
  • +
  • Reflections on reliability, security, and process
  • +
  • Lessons learned from real-world systems
  • +
+ +
+ +

Latest Posts

+ + {posts.length === 0 ? ( +

No posts yet. Check back soon.

+ ) : ( -
+ )}