Skip to content

ptrrrr/thebeam-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@thebeam/sdk

Official TypeScript SDK for integrating Pippa (thebeam.studio) as a headless CMS into your Next.js application.

Features

  • 🔐 Secure API authentication with Bearer tokens
  • ISR caching — automatic revalidation every hour
  • 🔄 Webhook support — instant cache invalidation when content changes
  • 📦 Zero dependencies — tiny bundle size
  • 🎯 Full TypeScript support — complete type safety
  • 🚀 Next.js optimized — built for App Router
  • 🎨 SEO helpers — metadata and JSON-LD generation

Installation

From private git repository:

pnpm add "git+https://github.com/ptrrrr/thebeam-sdk.git"
# or
npm install "git+https://github.com/ptrrrr/thebeam-sdk.git"

From npm (if published):

npm install @thebeam/sdk
# or
pnpm add @thebeam/sdk

Quick Start

Interactive Setup (Recommended)

Install the SDK and run the interactive installer:

# 1. Install the SDK
pnpm add "git+https://github.com/ptrrrr/thebeam-sdk.git"

# 2. Run the installer
pnpm exec beam-init
# or: npx beam-init

The installer will:

  • ✅ Ask for your preferred route path (/blog, /insights, /articles, etc.)
  • ✅ Check for conflicts and create backups
  • ✅ Copy and configure all templates
  • ✅ Install missing dependencies
  • ✅ Guide you through next steps

That's it! Just add your BEAM_API_KEY to .env.local and visit your blog route.


Manual Setup

If you prefer manual control:

1. Get an API Key

  1. Log in to your Pippa admin panel
  2. Go to Sites → [Your Site] → Settings
  3. Enable "Headless Mode"
  4. Create an API key in the "API Keys" section

2. Configure the Client

// lib/beam.ts
import { createBeamClient } from '@thebeam/sdk';

export const beam = createBeamClient({
  apiKey: process.env.BEAM_API_KEY!,
  baseUrl: 'https://www.thebeam.studio', // optional
  revalidate: 3600, // optional, default: 3600 seconds (1 hour)
});

Add to .env.local:

BEAM_API_KEY=beam_your_api_key_here

3. Fetch Content

// app/blog/page.tsx
import { beam } from '@/lib/beam';

export default async function BlogPage() {
  const { posts, pagination } = await beam.posts.list({ limit: 10 });

  return (
    <div>
      {posts.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
          <a href={`/blog/${post.slug}`}>Read more</a>
        </article>
      ))}
    </div>
  );
}

Ready-to-Use Page Templates

The SDK includes complete Next.js page templates that you can copy into your project for instant blog integration.

Quick Setup

# Copy all templates to your project
cp -r node_modules/@thebeam/sdk/templates/* .

This includes:

  • Blog homepage (app/blog/page.tsx) — Paginated post list
  • Single post page (app/blog/[slug]/page.tsx) — Full post with SEO
  • Category page (app/blog/category/[category]/page.tsx) — Filtered posts
  • Reusable components — PostCard, PostContent, Pagination
  • Webhook route (app/api/revalidate/route.ts) — Cache invalidation
  • Beam client (lib/beam.ts) — Pre-configured setup

What You Get

Production-ready pages with:

  • Responsive Tailwind CSS styling
  • Full TypeScript support
  • Automatic SEO metadata
  • JSON-LD structured data
  • Image optimization
  • ISR caching
  • Related posts
  • Pagination
  • Breadcrumbs

See node_modules/@thebeam/sdk/templates/README.md for detailed setup instructions and customization options.

API Reference

createBeamClient(options)

Creates a new Beam client instance.

Options:

  • apiKey (required): Your Beam API key
  • baseUrl (optional): Base URL of your Pippa instance (default: https://www.thebeam.studio)
  • revalidate (optional): ISR revalidation time in seconds (default: 3600)

Posts

beam.posts.list(options?)

Fetch a paginated list of posts.

const { posts, pagination } = await beam.posts.list({
  page: 1,           // Page number (default: 1)
  limit: 10,         // Posts per page (default: 10)
  category: 'guides', // Filter by category (optional)
  search: 'keyword',  // Search query (optional)
});

Returns:

{
  posts: PostListItem[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    total_pages: number;
  };
}

beam.posts.get(slug, options?)

Fetch a single post by slug.

const { post, related_posts } = await beam.posts.get('my-post-slug', {
  preview: false, // Include draft posts (default: false)
});

Returns:

{
  post: Post;
  related_posts: RelatedPost[];
}

Categories

beam.categories.list()

Fetch all categories with post counts.

const { categories } = await beam.categories.list();
// [{ name: 'guides', count: 15 }, ...]

Site

beam.site.get()

Fetch site metadata (name, theme, navigation, social links).

const { site } = await beam.site.get();
console.log(site.name);    // "Your Site Name"
console.log(site.theme);   // { primary: "#...", ... }
console.log(site.nav);     // [{ label: "Home", href: "/" }, ...]

Sitemap

beam.sitemap.get()

Fetch all post URLs for sitemap generation.

const { urls } = await beam.sitemap.get();
// [{ slug: 'my-post', updated_at: '2025-03-10T12:00:00Z', category: 'guides' }, ...]

SEO Helpers

beam.seo.metadata(post, siteUrl?)

Generate Next.js Metadata object for a post.

// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const { post } = await beam.posts.get(params.slug);
  return beam.seo.metadata(post, 'https://yoursite.com');
}

beam.seo.jsonLd(post)

Generate Article JSON-LD structured data.

const jsonLd = beam.seo.jsonLd(post);

return (
  <script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
  />
);

Webhooks

beam.revalidate.handler(webhookSecret?)

Create a webhook handler for cache invalidation.

// app/api/revalidate/route.ts
import { beam } from '@/lib/beam';

export const POST = beam.revalidate.handler(process.env.BEAM_WEBHOOK_SECRET);

When you publish or update a post in Pippa, it will automatically invalidate your Next.js cache via revalidateTag('beam-posts').

Setup:

  1. Create the route above
  2. In Pippa admin, go to Sites → [Your Site] → API Keys
  3. Edit your API key and set:
    • Webhook URL: https://yoursite.com/api/revalidate
    • Webhook Secret: any random string (save in .env.local)

TypeScript Types

All types are exported for your convenience:

import type {
  Post,
  PostListItem,
  RelatedPost,
  Category,
  Site,
  SiteTheme,
  Pagination,
  BeamMetadata,
  ArticleJsonLd,
} from '@thebeam/sdk';

Caching Strategy

Without webhooks:

  • Content is cached for the configured revalidate time (default: 1 hour)
  • Stale content is served for 5 minutes while revalidating in the background

With webhooks:

  • Content is cached indefinitely
  • Instantly invalidated when you publish/update/unpublish content
  • First request after change: ~300ms (API call)
  • Subsequent requests: served from edge cache (< 50ms)

Complete Example

// lib/beam.ts
import { createBeamClient } from '@thebeam/sdk';

export const beam = createBeamClient({
  apiKey: process.env.BEAM_API_KEY!,
});

// app/blog/page.tsx
import { beam } from '@/lib/beam';

export default async function BlogPage() {
  const { posts } = await beam.posts.list({ limit: 10 });
  return (
    <div>
      {posts.map((post) => (
        <article key={post.id}>
          <h2><a href={`/blog/${post.slug}`}>{post.title}</a></h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

// app/blog/[slug]/page.tsx
import { beam } from '@/lib/beam';
import { notFound } from 'next/navigation';
import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const data = await beam.posts.get(params.slug);
  if (!data) return {};
  return beam.seo.metadata(data.post, 'https://yoursite.com');
}

export default async function PostPage({ params }) {
  const data = await beam.posts.get(params.slug);
  if (!data) notFound();

  const { post, related_posts } = data;
  const jsonLd = beam.seo.jsonLd(post);

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      <article>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.body_html }} />
      </article>
    </>
  );
}

// app/api/revalidate/route.ts
import { beam } from '@/lib/beam';
export const POST = beam.revalidate.handler(process.env.BEAM_WEBHOOK_SECRET);

Documentation

For detailed integration guides and examples, see the full integration documentation.

Rate Limits

  • 100 requests per minute per API key
  • Exceeding the limit returns 429 Too Many Requests
  • Contact support for higher limits if needed

For Maintainers

This SDK ships with pre-built dist/ files committed to git. This avoids build issues during installation for consumers.

When updating the SDK:

# 1. Make changes to src/
cd packages/sdk/src
# Edit files...

# 2. Build
cd ..
pnpm build

# 3. Commit both src/ and dist/
git add src/ dist/
git commit -m "Update SDK: description of changes"

# 4. Push to SDK repo
cd /tmp/thebeam-sdk
git pull
cp -r /path/to/usepippa/packages/sdk/* .
git add .
git commit -m "Update SDK"
git push

Important: Always rebuild and commit dist/ after changing src/ files.

License

MIT

Support

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors