Integrations
SvelteKit Integration
Connect Blogree to your SvelteKit application using SvelteKit's server-side API routes. The webhook handler receives new posts and triggers page invalidation.
Step 1 — Install the Blogree SDK
npm install @blogree/js-sdk
# .env
BLOGREE_API_KEY=bk_live_xxxxxxxxxxxx
BLOGREE_API_URL=https://api.blogree.com
BLOGREE_WEBHOOK_SECRET=whs_xxxxxxxxxxxx
Step 2 — Create the Webhook Handler
// src/routes/api/blogree/+server.ts
import { json } from '@sveltejs/kit';
import { BLOGREE_WEBHOOK_SECRET } from '$env/static/private';
import { createHmac, timingSafeEqual } from 'crypto';
function verifySignature(rawBody: string, signature: string): boolean {
const expected = 'sha256=' + createHmac('sha256', BLOGREE_WEBHOOK_SECRET)
.update(rawBody).digest('hex');
try {
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
} catch {
return false;
}
}
export async function POST({ request }) {
const rawBody = await request.text();
const signature = request.headers.get('x-blogree-signature') || '';
if (!verifySignature(rawBody, signature)) {
return json({ error: 'Unauthorized' }, { status: 401 });
}
const payload = JSON.parse(rawBody);
const post = payload.post;
// Store post — example with a simple JSON file store
// In production, use your database (Prisma, Supabase, etc.)
await storeBlogPost(post);
// Confirm delivery to Blogree
await fetch(`${process.env.BLOGREE_API_URL}/api/pull/confirm`, {
method: 'POST',
headers: { 'X-API-Key': process.env.BLOGREE_API_KEY || '', 'Content-Type': 'application/json' },
body: JSON.stringify({ post_id: post.id, site_id: post.site_id, status: 'delivered' }),
});
return json({ success: true }, { status: 200 });
}
Step 3 — Fetch Posts in Pages
// src/routes/blog/+page.server.ts
import { BLOGREE_API_KEY, BLOGREE_API_URL } from '$env/static/private';
export async function load({ fetch }) {
const res = await fetch(`${BLOGREE_API_URL}/api/pull/posts`, {
headers: { 'X-API-Key': BLOGREE_API_KEY },
});
const { posts } = await res.json();
return { posts };
}
// src/routes/blog/+page.svelte
<script>
export let data;
</script>
<ul>
{#each data.posts as post}
<li><a href="/blog/{post.slug}">{post.title}</a></li>
{/each}
</ul>
// src/routes/blog/[slug]/+page.server.ts
import { BLOGREE_API_KEY, BLOGREE_API_URL } from '$env/static/private';
import { error } from '@sveltejs/kit';
export async function load({ params, fetch }) {
const res = await fetch(`${BLOGREE_API_URL}/api/pull/posts/${params.slug}`, {
headers: { 'X-API-Key': BLOGREE_API_KEY },
});
if (res.status === 404) throw error(404, 'Post not found');
const post = await res.json();
return { post };
}
// src/routes/blog/[slug]/+page.svelte
<script>
export let data;
</script>
<svelte:head>
<title>{data.post.meta.title}</title>
<meta name="description" content={data.post.meta.description} />
</svelte:head>
<article>
<h1>{data.post.title}</h1>
{@html data.post.body.html}
</article>
Step 4 — Set Webhook URL in Blogree
Your SvelteKit webhook URL is the route you created:
https://yourdomain.com/api/blogree
Paste this in the Blogree dashboard under Sites → your site → Settings → Webhook URL, then click Test Delivery.
Database Integration Example (Prisma)
For production, store posts in a database instead of the filesystem. Here's the webhook handler using Prisma:
// src/routes/api/blogree/+server.ts (with Prisma)
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Inside POST handler, after verification:
const post = payload.post;
await prisma.post.upsert({
where: { slug: post.slug },
update: {
title: post.title,
content: post.body.html,
excerpt: post.excerpt,
metaTitle: post.meta.title,
metaDescription: post.meta.description,
tags: post.tags,
publishedAt: new Date(post.published_at),
},
create: {
slug: post.slug,
title: post.title,
content: post.body.html,
excerpt: post.excerpt,
metaTitle: post.meta.title,
metaDescription: post.meta.description,
tags: post.tags,
publishedAt: new Date(post.published_at),
},
});