@itmaster/sdk · quickstart

One dependency wires a Next.js site to the engine.

Pull finished articles, serve robots.txt / sitemap.xml / rss.xml / llms.txt, source the engine-managed <head>, host the IndexNow key, and receive publish webhooks — mostly one line per feature.

one command to scaffold
terminal
npm i @itmaster/sdk npx @itmaster/sdk init                 # interactive (y/n per feature)# or non-interactive:npx @itmaster/sdk init \  --site <PUBLISH_SITE> --engine https://itmaster.uk \  --features robots,sitemap,rss,llms,indexnow,webhook --yes

01 · the init CLI

Scaffold by selecting features.

It writes only new files (client + the routes you pick + middleware), adds env keys, and prints the two snippets it won't overwrite.

what init runs
npm i @itmaster/sdk npx @itmaster/sdk init                 # interactive (y/n per feature)# or non-interactive:npx @itmaster/sdk init \  --site <PUBLISH_SITE> --engine https://itmaster.uk \  --features robots,sitemap,rss,llms,indexnow,webhook --yes

02 · setup

Env, then one shared client.

Register the site engine-side (issues a pull key), set env, create the shared client. No pull key just means every call returns null and the site still renders.

.env.local
ITMASTER_API_URL=https://itmaster.uk
PUBLISH_SITE=<your TargetSite id>
PUBLISH_PULL_KEY=<per-site key>
lib/itmaster.ts
import { createClient } from "@itmaster/sdk";
export const itmaster = createClient({
  baseUrl: process.env.ITMASTER_API_URL!,
  site: process.env.PUBLISH_SITE!,
  pullKey: process.env.PUBLISH_PULL_KEY ?? "",
});

03 · what you get

Six wires, each a re-export.

robots.txt / sitemap.xml / rss.xml / llms.txt
create*Route(itmaster)
app/<name>/route.ts — 1 line each
IndexNow key
createIndexNowKeyRoute(PUBLISH_SITE)
app/api/indexnow-key/route.ts + middleware — no pull key
engine-managed <head>
applyMeta + headTagsFromConfig
app/layout.tsx — verification, analytics, OG, favicon
article metadata + JSON-LD
articleMetadata / articleJsonLd
app/blog/[slug]/page.tsx
publish → live in seconds
createWebhookRoute
app/api/itmaster-webhook/route.ts
write-back (CMS sites)
createProviderRoutes
app/api/external/[slug]/…

04 · the one-liners

Every route is a single re-export.

Derived feeds are a single re-export:

app/robots.txt/route.ts · same shape for sitemap.xml / rss.xml / llms.txt
import { createRobotsRoute } from "@itmaster/sdk/next";
import { itmaster } from "@/lib/itmaster";
export const GET = createRobotsRoute(itmaster);

IndexNow derives the exact key the engine submits — no secret, no round-trip:

app/api/indexnow-key/route.ts + middleware.ts
// app/api/indexnow-key/route.ts
import { createIndexNowKeyRoute } from "@itmaster/sdk/next";
export const GET = createIndexNowKeyRoute(process.env.PUBLISH_SITE ?? "your-site");

// middleware.ts
import { NextRequest, NextResponse } from "next/server";
export function middleware(req: NextRequest) {
  if (/^\/[a-f0-9]{32}\.txt$/.test(req.nextUrl.pathname))
    return NextResponse.rewrite(new URL("/api/indexnow-key", req.url));
  return NextResponse.next();
}
export const config = { matcher: ["/((?!_next/|favicon.ico).*)"] };

Engine-managed head — verification/OG/favicon via the Metadata API (the only path that reaches <head> in the App Router):

app/layout.tsx
import { applyMeta } from "@itmaster/sdk/next";
import { itmaster } from "@/lib/itmaster";
const base = { /* your defaults */ };
export async function generateMetadata() {
  const config = await itmaster.config().catch(() => null);
  return config ? applyMeta(base, config) : base;
}

05 · connect google — zero-click

One call verifies, submits, and indexes.

Once the head + IndexNow routes are live, one engine call verifies the site in Search Console, submits the sitemap, and turns on indexing (Google Indexing API + IndexNow).

Full reference, provider (write-back) mode, and the incremental mirror feed are in the README.

your account, from the command line
# Create a key: dashboard → API & AI accesscurl -X POST "https://itmaster.uk/api/mcp" \  -H "Authorization: Bearer itm_live_..." \  -H "Content-Type: application/json" \  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",       "params":{"name":"get_account_status","arguments":{}}}'