signalry-sdk
v1.0.0
Published
The official Signalry client for Next.js. Add a blog and free tools to your site in minutes.
Downloads
81
Maintainers
Readme
signalry-sdk
Signalry is an Autonomous SEO Agent for B2B SaaS. This package is the official Next.js-compatible SDK for rendering Signalry-hosted blog articles and embedding interactive tools.
Features
- Plug and play: add a blog and tools in minutes
- SSR-first: fetch on the server for SEO (Next.js App Router)
- CDN-backed: content is served from
cdn.signalry.co - Flexible styling: use the default theme or go unstyled
- TypeScript: typed API and components
Installation
npm install @signalry/contentWorkspace key (public)
Signalry uses a workspace key to identify which content bucket to read from. It is not a secret and is safe to use on the client.
# .env.local
NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY=ws_your_workspace_keyQuick start (Next.js App Router)
Server-side rendering (recommended)
Fetch on the server using the server-only entrypoint:
// app/blog/page.tsx
import Link from 'next/link';
import { getSignalryArticles } from '@signalry/content/server';
export const revalidate = 3600;
export default async function BlogPage() {
const workspaceKey = process.env.NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY!;
const articles = await getSignalryArticles(workspaceKey);
return (
<main>
<h1>Blog</h1>
<ul>
{articles.map((a) => (
<li key={a.id}>
<Link href={`/blog/${a.id}`}>{a.title}</Link>
</li>
))}
</ul>
</main>
);
}Render a full article:
// app/blog/[id]/page.tsx
import { SignalryArticle } from '@signalry/content';
import {
generateArticleMetadata,
generateArticleJsonLd,
getSignalryArticle,
} from '@signalry/content/server';
export const revalidate = 3600;
export async function generateMetadata({ params }: { params: { id: string } }) {
const workspaceKey = process.env.NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY!;
const article = await getSignalryArticle(workspaceKey, params.id);
if (!article) return {};
return generateArticleMetadata(article, {
canonicalBase: 'https://yoursite.com/blog',
siteName: 'Your Site',
});
}
export default async function ArticlePage({ params }: { params: { id: string } }) {
const workspaceKey = process.env.NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY!;
const article = await getSignalryArticle(workspaceKey, params.id);
if (!article) return <div>Not found</div>;
const jsonLd = generateArticleJsonLd(article, {
canonicalBase: 'https://yoursite.com/blog',
siteName: 'Your Site',
});
return (
<main>
<SignalryArticle article={article} />
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: jsonLd }} />
</main>
);
}Client-side rendering (optional)
If you prefer to fetch on the client (for example on gated pages), use the shared entrypoint:
"use client";
import { useEffect, useState } from 'react';
import { SignalryArticle, getSignalryArticle } from '@signalry/content';
export default function ArticleClient({ id }: { id: string }) {
const [article, setArticle] = useState<any>(null);
useEffect(() => {
const workspaceKey = process.env.NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY!;
getSignalryArticle(workspaceKey, id).then(setArticle);
}, [id]);
if (!article) return <div>Loading…</div>;
return <SignalryArticle article={article} />;
}Styling
Default theme
Import the bundled CSS:
import '@signalry/content/styles/signalry.css';Unstyled (bring your own)
All components support unstyled to avoid default classes.
Tools
Embed an interactive tool (iframe). This is a client component:
"use client";
import { SignalryTool } from '@signalry/content';
export default function ToolsPage() {
const workspaceKey = process.env.NEXT_PUBLIC_SIGNALRY_WORKSPACE_KEY!;
return <SignalryTool workspaceKey={workspaceKey} toolId="tool_id_here" />;
}API reference
Server functions (recommended import path)
getSignalryArticles(workspaceKey)getSignalryArticlesPaginated(workspaceKey, { page, limit })getSignalryArticle(workspaceKey, contentId)getSignalryArticlePaths(workspaceKey)getSignalryTools(workspaceKey)getSignalryToolUrl(workspaceKey, toolId)generateArticleMetadata(article, { canonicalBase, siteName?, twitterHandle? })generateArticleJsonLd(article, { canonicalBase, siteName?, twitterHandle? })
Import:
import { getSignalryArticles } from '@signalry/content/server';React components
<SignalryArticle article={article} unstyled? className? renderHeader? renderFooter? /><SignalryTableOfContents html={article.body_html} unstyled? className? /><SignalryTool workspaceKey toolId autoResize? minHeight? className? style? /><SignalryBlogList articles basePath? page totalPages onPageChange? renderCard? unstyled? className? cardClassName? /><SignalryBlogCard article basePath unstyled? className? onClick? />
Caching
- The SDK includes an in-memory cache for index endpoints (per process).
- For Next.js, the fetch calls include
next: { revalidate: ... }hints suitable for ISR.
License
MIT
