mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 14:57:28 +00:00
feat(web): blog-post ingestion webhook + /blog, dynamic RSS & sitemap
Add an autoblog webhook receiver and a Supabase-backed blog to logicsrc-web (the app had no Supabase usage before). - Migration: blog_posts table (RLS: public reads published, service-role writes). Applied to the linked project. - POST /api/webhooks/blog: verifies the Standard Webhooks signature against BLOG_WEBHOOK_SECRET via @profullstack/autoblog verifyAndParse (no admin user — shared secret only) and upserts the post by slug. - /blog index + /blog/[slug] render published posts from the table. - /blog/rss.xml and /sitemap.xml are now dynamic, generated from the table; removed the static public/sitemap.xml and public/blog/rss.xml. - BLOG_WEBHOOK_SECRET added to .env.example. Verified end-to-end: a signed sample post delivered 200 and appeared in the index, post page, RSS, and sitemap; build + typecheck pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ade606c157
commit
cf99e93c53
13 changed files with 549 additions and 82 deletions
1
supabase/config.toml
Normal file
1
supabase/config.toml
Normal file
|
|
@ -0,0 +1 @@
|
|||
project_id = "qgytusjwuvlynkdknype"
|
||||
37
supabase/migrations/20260608020000_blog_posts.sql
Normal file
37
supabase/migrations/20260608020000_blog_posts.sql
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
-- Blog posts ingested via the autoblog webhook (/api/webhooks/blog).
|
||||
-- Source of truth for /blog, /blog/[slug], /blog/rss.xml, and sitemap.xml.
|
||||
-- Writes happen only through the service-role key (the webhook); the public
|
||||
-- (anon) key can read published posts.
|
||||
|
||||
create table if not exists public.blog_posts (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
external_id text unique, -- autoblog Post.id (idempotency)
|
||||
slug text not null unique,
|
||||
title text not null,
|
||||
excerpt text,
|
||||
html text not null,
|
||||
markdown text,
|
||||
url text,
|
||||
canonical_url text,
|
||||
author jsonb,
|
||||
tags text[] not null default '{}',
|
||||
categories text[] not null default '{}',
|
||||
featured_image jsonb,
|
||||
status text not null default 'published',
|
||||
published_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create index if not exists blog_posts_published_idx
|
||||
on public.blog_posts (published_at desc)
|
||||
where status = 'published';
|
||||
|
||||
alter table public.blog_posts enable row level security;
|
||||
|
||||
-- Public can read published posts; everything else is service-role only
|
||||
-- (service_role bypasses RLS, so no insert/update policy is needed).
|
||||
drop policy if exists "blog_posts public read" on public.blog_posts;
|
||||
create policy "blog_posts public read"
|
||||
on public.blog_posts for select
|
||||
using (status = 'published');
|
||||
Loading…
Add table
Add a link
Reference in a new issue