Publish engine-written articles on your Next.js site
@itmaster/sdk is a typed Pull-API client plus drop-in App Router handlers. Install it, fill in one key, and the blog, robots.txt, sitemap, RSS, llms.txt and IndexNow key all come from the engine.
Published 2026-09-02, reviewed 2026-09-04, by Rodd Azad, editor-in-chief. How we check facts.
Setup, end to end.
1Step 1
Register the site in the IT Master dashboard so the engine mints its per-site pull key, or ask us to register it for you.2Step 2
Run npx @itmaster/sdk init in the project root and pick the features you want, or run npm install @itmaster/sdk and copy the same files from the README by hand.3Step 3
Paste the pull key into PUBLISH_PULL_KEY in .env.local; the CLI has already written ITMASTER_API_URL and PUBLISH_SITE for you.4Step 4
Keep lib/itmaster.ts server-only — it imports server-only on the first line so a client component that touches it fails the build instead of shipping the key.5Step 5
Render the blog: call listArticles on /blog, and getArticle plus articleMetadata and articleJsonLd on /blog/[slug].6Step 6
Export the drop-in handlers as one-line route files: createRobotsRoute, createSitemapRoute, createRssRoute and createLlmsRoute.7Step 7
Add createIndexNowKeyRoute at /api/indexnow-key and the middleware rewrite that maps a 32-hex .txt request to it.8Step 8
Add the webhook route with createWebhookRoute, set PUBLISH_PUSH_SECRET to the value registered with the engine, and revalidate the blog paths inside it.9Step 9
Call applyMeta with the site config in your root generateMetadata, and render headTagsFromConfig scripts through next/script.10Step 10
Deploy, then connect Search Console from the dashboard — the engine serves the verification token in your head tags, submits the sitemap and pings IndexNow on every publish.
What does @itmaster/sdk give a Next.js app?
The SDK is the official client for the engine's read-only Pull API. It ships on npm as @itmaster/sdk, MIT-licensed, ESM only, with full TypeScript declarations and zero runtime dependencies. next is declared as an optional peer at version 14 or later, so it installs cleanly in a project that has not upgraded yet, and the source is public at github.com/codedpro/itmaster-sdk if you would rather read it before you install it.
Two import paths matter. The root export gives you createClient, and with it listArticles, getArticle, listArticlesPage for an incremental mirror, plus the derived feeds sitemap, rss, llmsTxt, robots, redirects, clusters and config. The /next export gives you the App Router helpers: articleMetadata, articleJsonLd, applyMeta, headTagsFromConfig, deriveIndexNowKey, verifyWebhookSignature and the route factories below.
Nothing about your design is prescribed. An article record arrives as rendered body HTML plus hero image, FAQ pairs, a table of contents, internal links, engine-authored JSON-LD and a canonical path, and you render it in your own components. What the package removes is the layer every site would otherwise rewrite: the authenticated fetch, the feed proxies, the schema builder and the HMAC check.
This site pulls its own blog through the same package.
In one sentence
@itmaster/sdk is a client and a set of route handlers, not a theme: your components stay yours, while the authenticated fetch, the feeds, the schema and the signature checks stop being your problem.
How do I install it, and which keys do I need?
Install with npm install @itmaster/sdk. Then run npx @itmaster/sdk init, which asks yes or no per feature and writes only new files — the shared client at lib/itmaster.ts, a route file for each feature you picked, middleware.ts, and the webhook route. It detects whether your app lives in app or src/app, skips anything that already exists unless you pass --force, and prints the two snippets it refuses to clobber: the root layout head wiring and the blog pages.
It also ensures the env keys in .env.local and .env.example:
- ITMASTER_API_URL — the engine origin, written for you.
- PUBLISH_SITE — your site slug in the engine, written for you.
- PUBLISH_PULL_KEY — the per-site bearer key, left blank because only you should paste it.
- PUBLISH_PUSH_SECRET — added only if you chose the webhook.
So one value is yours to fill in. The generated client starts with an import of server-only, which is what keeps the pull key out of any client bundle. Pass cache with a number of seconds to createClient if you want ISR instead of the default no-store.
Which routes does the SDK give me for free?
Each feed is a one-line route file. The factory returns a plain async handler that proxies the engine's generated output and answers 404 rather than an empty body when a feed is not available.
- app/robots.txt/route.ts — createRobotsRoute serves the robots policy from your dashboard, including the single AI-crawler toggle that flips GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot and the rest of the managed list between allow and disallow.
- app/sitemap.xml/route.ts — createSitemapRoute serves the engine's sitemap, honouring the changefreq, priority and exclude settings.
- app/rss.xml/route.ts — createRssRoute.
- app/llms.txt/route.ts — createLlmsRoute publishes the llms.txt manifest.
- app/api/indexnow-key/route.ts — createIndexNowKeyRoute.
The IndexNow route is worth a note. The key is derived locally from a SHA-256 of a fixed salt and your site id, using exactly the formula the engine uses when it submits, so ownership verifies with no stored secret and no round trip. A middleware rule rewrites any 32-hex .txt request to that route, which is where search engines look for the proof.
Can head tags change without a redeploy?
Verification tokens, analytics IDs, the default OG image, the Twitter handle, the favicon and the title template live in the engine's site config, not in your repository. The SDK applies them at request time.
In the root layout, fetch config and pass your base metadata through applyMeta. That returns a Next Metadata object with the Google and Yandex verification fields set, Bing and Pinterest under verification.other, OG and Twitter defaults filled and the title template or suffix applied. Analytics are separate: headTagsFromConfig returns script descriptors for GA4, GTM, Plausible, Clarity and Meta Pixel, which you render with next/script.
On an article page, compose the two — applyMeta over articleMetadata gives you the canonical, description, keywords, OG and Twitter cards for that post under the site's own title rules. articleJsonLd returns the engine's authored JSON-LD when the article carries it, and otherwise builds an Article plus FAQPage graph.
One trap the README calls out: do not try to inject tags through a Fragment with dangerouslySetInnerHTML inside head. A Fragment has no DOM node, so nothing reaches the document. Use the Metadata API and next/script.
In one sentence
Verification tokens and analytics IDs live in the IT Master site config rather than in the repository, so @itmaster/sdk picks up a change on the next revalidate and a Next.js site never redeploys for a head tag.
How do publishes and takedowns reach the site?
If your site registers a push URL and secret, the engine POSTs each publish, update or takedown straight to it. createWebhookRoute reads the raw body, verifies the X-Thoth-Signature header — a hex HMAC-SHA256 of that body, compared in constant time — and answers 401 on a bad signature and 400 on malformed JSON before any of your code runs.
After the check it dispatches. Publish and update events go to onUpsert; unpublish, delete and takedown events go to onDelete, as does any article whose status is already unpublished. Then it calls your revalidate closure, which is where you put revalidatePath for the post and the index. That is the whole path from the engine passing its checks to the page being live.
Prefer polling? listArticlesPage returns a page of articles and a next_since cursor, tombstones included, so a mirror can add, update and delete in one pass. Either way, a takedown removes the article from your site rather than leaving an orphan.
The same signature scheme covers createSeoPatchRoute, which lets the engine propose rewritten titles, meta and JSON-LD for pages you already have.
What has already happened before my route sees an article?
By the time an article reaches your Next.js app it has been through the whole pipeline. Topics come from measured demand — DataForSEO plus your own Search Console queries. Research reads the competing pages, forums and, where it exists, your first-party data. A Claude model writes it. Then four checks run, none of them by the model that wrote it and each including at least one model from a different vendor: fact-check and novelty against the ranking pages led by Gemini and GPT, plus an E-E-A-T critique and AI-tell detection, with up to three revision rounds; see cross-model validation.
Stated as measured, not promised. Across 186 Standard-tier runs, 21% of drafts cleared every check on the first attempt with no revision, and 51% got there within the three revisions allowed; the rest never published. Pro-tier judges are stricter: 25% cleared every check across a small sample of 16 runs.
You pay per published article from a prepaid balance, with no subscription; a draft that fails the checks is not charged. Current rates are on pricing, and the route recipes above are written out in full in the docs.
Not on Next.js? The same engine serves WordPress through a plugin.
When the SDK is the wrong choice
The SDK is a convenience, not a requirement, and there are projects it does not suit.
- You are not on Next.js. The route factories, applyMeta and articleMetadata are shaped for the App Router. The core client is framework-agnostic, but if you are on Astro, Remix, Nuxt or a Go service, the REST pull feed is a plainer contract than a package with a Next peer.
- You already have a CMS that owns content. If editors work in Sanity or Contentful and expect articles to be entries they can edit, take the signed webhook and write them into that CMS instead of rendering our records directly.
- Your build is fully static with no revalidation. Articles arrive continuously. A site that only rebuilds when a human runs a deploy will show stale content, so wire the webhook to trigger a build or accept the lag.
- You cannot keep a secret on the server. The pull key must never reach the browser. The generated client imports server-only on its first line so a client component that touches it fails the build, but a purely client-rendered site has nowhere safe to put the key.
- You want the engine to edit pages you wrote. That is a separate, opt-in route (createSeoPatchRoute) that you mount and your handler governs; it is not what installing the package does.
The package pins nothing about your design. If none of the above applies, the honest summary is that it removes about a day of glue code and one class of bug: the authenticated fetch, the feed proxies, the schema builder and the HMAC check.
Questions people ask
Does the pull key ever reach the browser?
No, provided you keep the client where the scaffolder puts it. The generated lib/itmaster.ts opens with an import of the server-only package, so if any client component imports it, the build fails rather than the key shipping in a bundle. Every call the SDK makes sends the key as a bearer token from your server to the engine. The IndexNow key route is the one piece that needs no key at all: it derives the value locally from your site id.
Does it work with the Pages Router, or only the App Router?
The route factories, applyMeta and articleMetadata are shaped for the App Router, which is what the scaffolder generates. The core client is framework-agnostic and works anywhere in Node or an edge runtime, so a Pages Router app can still call listArticles and getArticle, build its own head from renderHeadHtml, and serve the feeds from API routes. The package declares next as an optional peer and imports nothing from it, so neither router is a hard requirement.
How fresh is the content on my pages?
That is your choice. By default createClient fetches with no-store, so every render sees the current article. Pass a number as the cache option and the SDK uses Next ISR revalidation with that many seconds instead. If you also wire the webhook route, the engine pushes each publish and takedown to you and your revalidate closure clears exactly the affected paths, so a long revalidate window and near-instant updates are not in conflict.
Can the engine change pages I wrote myself, not just the articles?
Only if you mount the route for it and only as far as your handler allows. createSeoPatchRoute receives proposed titles, meta descriptions, Open Graph values and JSON-LD, plus prose rewrites, each HMAC-verified the same way as the publish webhook. Your handler decides what to persist and can decline a patch by returning false. A content patch marked for staging should be saved for review rather than published. The engine never receives credentials for your database.
What arrives in each article record?
Rendered body HTML, title, description and meta description, an excerpt, a hero image with alt text, FAQ question and answer pairs, a table of contents, engine-authored JSON-LD, the canonical path and URL, published and updated timestamps, word count and reading time, the primary and secondary keywords, tags, author details, Open Graph and Twitter fields, internal links into your other posts, and outbound citations. Status is published or unpublished, and an unpublished record is a tombstone you should act on.
Do I have to use the SDK at all?
No. The SDK is a convenience over a plain REST API. Any stack can call the Pull API endpoints directly with the site's bearer key, render the body HTML, inject the JSON-LD and serve the sitemap and RSS straight through, polling with a since cursor for changes. The signed push webhook is equally open: verify the hex HMAC of the raw body against your secret in whatever language you like. The SDK exists so Next.js sites need not write that twice.
Is the SDK open source, and what is it licensed under?
It is published on npm as @itmaster/sdk under the MIT licence, with the source public at github.com/codedpro/itmaster-sdk, so you can read exactly what it sends and receives before installing it. It is ESM only, ships full TypeScript declarations, and has zero runtime dependencies, with next declared as an optional peer at version 14 or later. Nothing in it is required: every endpoint it calls is part of the documented REST pull feed, and the webhook verification it performs is an ordinary HMAC-SHA256 check you can write yourself.
See what search engines and AI assistants find on your site
Free, and no account. Type your address and the check tells you what is missing and what we would write first.