Examples

Embed
Preview of the card
<a href="https://forumulate.com/reference/examples"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/3e48aa1c-9a05-4846-a632-3229ed680b79/social-card.svg?v=3e7ae33eec8b" alt="Examples" width="600" height="315"></a>

Complete, runnable snippets. Each assumes a client configured with a PAT:

import { ForumulateClient, ForumulateError } from '@forumulate/sdk';

const forumulate = new ForumulateClient({
  baseUrl: 'https://forumulate.com/api',
  token: process.env.FORUMULATE_TOKEN!,
});

1. Create a docs space and publish a page

Builds a public DOCS space, adds a collection, creates a page, sets its content (a TipTap/ProseMirror document), and publishes it — then reads it back through the public (unauthenticated) reader.

async function publishDocsPage(orgId: string) {
  const { space } = await forumulate.spaces.create(orgId, {
    name: 'Docs',
    slug: 'docs',
    type: 'DOCS',
    visibility: 'PUBLIC',
  });

  const { collection } = await forumulate.spaces.createCollection(orgId, space.id, {
    name: 'Guides',
    slug: 'guides',
  });

  const { page } = await forumulate.spaces.createPage(orgId, space.id, collection.id, {
    title: 'Intro',
    slug: 'intro',
  });

  await forumulate.spaces.setPageContent(orgId, space.id, page.id, {
    title: 'Intro',
    content: {
      type: 'doc',
      content: [
        { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: 'Welcome' }] },
        { type: 'paragraph', content: [{ type: 'text', text: 'Hello from the SDK.' }] },
      ],
    },
  });

  await forumulate.spaces.publishPage(orgId, space.id, page.id);

  // Read it back with no auth, through the public reader.
  const { hits } = await forumulate.public.search(orgId, space.id, 'welcome');
  return { space, page, hits };
}

The content is a BlockDoc: { type: 'doc', content: BlockNode[] }, where each node has type, optional content, text, attrs, and marks.

2. Create and list items (the space-agnostic "pieces" surface)

items is the uniform way to write one piece of a space — a docs page, a blog post, a release, an incident — whatever that space holds. You send Markdown sections and the response tells you what a piece's shape says is still missing.

async function seedRelease(orgId: string, spaceId: string) {
  // Create a piece with a whole-body markdown.
  const { item } = await forumulate.items.create(orgId, spaceId, {
    title: 'v1.4.0',
    body: '## Highlights\n\n- Faster search\n- New PDF export',
  });

  // Fill a single named section (idempotent — sending it twice writes it once).
  const { conformance } = await forumulate.items.setSection(
    orgId, spaceId, item.id, 'summary', 'A performance-focused release.',
  );
  if (!conformance.conforms) {
    console.log('still missing sections:', conformance.missing);
  }

  // Publish it (kinds that are already live on creation say so and change nothing).
  await forumulate.items.publish(orgId, spaceId, item.id);

  // List what's in the space.
  const { items } = await forumulate.items.list(orgId, spaceId, 50);
  return items;
}

To page through or incrementally sync a large space, use client.typed with a cursor / updated_since — see Errors & pagination.

3. Start a forum topic and reply to it

Community spaces (type: 'FORUM') use topics and posts. Content is a BlockDoc, same as docs pages.

async function askAndAnswer(orgId: string, spaceId: string) {
  const body = (text: string) => ({
    type: 'doc' as const,
    content: [{ type: 'paragraph', content: [{ type: 'text', text }] }],
  });

  const { topic } = await forumulate.forum.createTopic(orgId, spaceId, {
    title: 'How do I rotate a PAT?',
    content: body('What is the recommended way to rotate a token without downtime?'),
    kind: 'QUESTION',        // optional; e.g. 'QUESTION' | 'DISCUSSION'
    tags: ['auth', 'tokens'], // optional
  });

  // `topic` is untyped in the helper; cast to read its id.
  const topicId = (topic as { id: string }).id;

  await forumulate.forum.reply(orgId, spaceId, topicId, body('Issue a new token, deploy it, then revoke the old one.'));

  // List topics in the space.
  const { topics } = await forumulate.forum.listTopics(orgId, spaceId, { sort: 'latest' });
  return topics;
}

Error handling across all three

Wrap calls and branch on code:

try {
  await publishDocsPage(orgId);
} catch (err) {
  if (err instanceof ForumulateError && err.code === 'space.slug_taken') {
    // pick a different slug
  } else {
    throw err;
  }
}
The Forumulate teamUpdated