SvelteKit with Stubby

Updated on

Learn how to integrate Stubby CMS with SvelteKit to create a dynamic, revalidated blog. This guide walks you through setting up your project, fetching content from Stubby CMS, rendering markdown, and optimizing for SEO.

1. Setting up a SvelteKit project

Start by creating a new SvelteKit project using the SvelteKit CLI:

npx sv create stubby-demo-svelte

Follow the prompts to configure your project, then navigate into the project directory:

cd stubby-demo-svelte

Run the development server to confirm everything is working:

npm run dev

2. Configuring environment variables

Add your Stubby CMS credentials to a .env file at the root of your project:

STUBBY_API_KEY="your_stubby_api_key"
STUBBY_SITE_ID="your_site_id"
STUBBY_BASE_URL="https://stubby.io/api/v1"

These credentials can be found in the Settings section of your Stubby CMS dashboard.

3. Building the blog list page

  • Fetch blog data — Create a +page.server.ts file in the src/routes directory to fetch blog posts from Stubby CMS:
src/routes/+page.server.ts
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";

export const load: PageServerLoad = async ({ params }) => {
  const { STUBBY_API_KEY, STUBBY_SITE_ID, STUBBY_BASE_URL } = env;

  const url = `${STUBBY_BASE_URL}/sites/${STUBBY_SITE_ID}/collections?apiKey=${STUBBY_API_KEY}`;

  const res = await fetch(url);
  const data = await res.json();

  return {
    posts: data,
  };
};
  • Render blog list — Create a +page.svelte file in the src/routes directory to display the list of blog posts:
src/routes/+page.svelte
<script lang="ts">
  import type { PageData } from "./$types";
  let { data }: { data: PageData } = $props();
</script>

<main class="container pb-40 pt-16 mx-auto max-w-[65ch]">
  <h1 class="text-3xl font-semibold mb-10">Blog</h1>
  <ul class="flex flex-col space-y-10">
    {#each data.posts as blog}
      <li>
        <a href={`blog/${blog.slug}`} class="font-semibold text-lg">
          {blog.title}
        </a>
        <p>
          {blog.metadata.description}
        </p>
        <a href={`blog/${blog.slug}`} class="mt-3 inline-block text-blue-700">
          Read more &rarr;
        </a>
      </li>
    {/each}
  </ul>
</main>

4. Creating individual blog pages

  • Fetch blog post data — Create a +page.server.ts file in the src/routes/blog/[slug] directory to fetch individual blog post data:
src/routes/blog/[slug]/+page.server.ts
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";

export const load: PageServerLoad = async ({ params }) => {
  const { STUBBY_API_KEY, STUBBY_SITE_ID, STUBBY_BASE_URL } = env;

  const url = `${STUBBY_BASE_URL}/sites/${STUBBY_SITE_ID}/pages/${params.slug}?apiKey=${STUBBY_API_KEY}`;
  const res = await fetch(url);
  const data = await res.json();

  return {
    post: data,
  };
};
  • Install markdown library — Install the markdown library to render the markdown content.
npm install svelte-markdown
  • Render blog post content — Create a +page.svelte file in the src/routes/blog/[slug] directory to display individual blog posts::
src/routes/blog/[slug]/+page.svelte
<script lang="ts">
  import SvelteMarkdown from "svelte-markdown";
  import type { PageData } from "./$types";

  let { data }: { data: PageData } = $props();

  function removeFrontmatter(content: string): string {
    const frontmatterPattern = /^---[\s\S]*?---\s*/;
    return content.replace(frontmatterPattern, "");
  }
</script>

<main class="container pb-40 pt-16 mx-auto max-w-[65ch]">
  <a href="/blog" class="text-blue-700 mb-10 inline-block">
    &larr; Back to blog
  </a>
  <h1 class="text-3xl font-semibold mb-6">{data.post.title}</h1>
  <div class="prose">
    <SvelteMarkdown source={removeFrontmatter(data.post.content)} />
  </div>
</main>

5. Enhancing SEO and open graph support

To improve your site's SEO and social media visibility, include metadata like title, description, and image in the frontmatter of your Stubby CMS content. Use this metadata to dynamically update the <head> section of your SvelteKit pages.

6. Conclusion

Integrating Stubby CMS with SvelteKit allows you to build a dynamic, content-rich blog with ease. By leveraging SvelteKit's server-side rendering and Stubby CMS's flexible API, you can create a high-performance, SEO-friendly website. Start building your blog today and unlock the full potential of Stubby CMS with SvelteKit!

 
Source code — Github