{"_id":"@blogree/nextjs-adapter","_rev":"5-4c28dd5176ff043e84eb0d68452cae4e","name":"@blogree/nextjs-adapter","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.0":{"name":"@blogree/nextjs-adapter","version":"1.0.0","keywords":["blogree","nextjs","cms","adapter"],"_id":"@blogree/nextjs-adapter@1.0.0","maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"dist":{"shasum":"d6bae5f3b2cf19bc60ca57428734d4b5cb92ba8d","tarball":"https://registry.npmjs.org/@blogree/nextjs-adapter/-/nextjs-adapter-1.0.0.tgz","fileCount":8,"integrity":"sha512-JV1dSN6XByiCekcSZyILiSt3fAxehpktdq7H7+kB8r6WPA3KY0fuZJOWcbutxHliTDR8g/wq7Nlay0eORTkssQ==","signatures":[{"sig":"MEUCIQCoRxnviVC+UcdDC5U6oz5vH73gsqJ/FZTFpJ7kqiwLagIgZlTkHFmCc4/JF1lYhVgnUbEj8ClHyoJTuPwGbAJlbS4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38859},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"6a4bd1aa089b4908eaa39edae570b76485304a0b","scripts":{"dev":"tsc --watch","build":"tsc"},"_npmUser":{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"},"_npmVersion":"10.8.2","description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","directories":{},"_nodeVersion":"20.17.0","dependencies":{"crypto":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"next":"^14.1.0","typescript":"^5.3.3","@types/node":"^20.11.5"},"peerDependencies":{"next":">=13.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nextjs-adapter_1.0.0_1775258918425_0.002503944820506643","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@blogree/nextjs-adapter","version":"1.0.1","keywords":["blogree","nextjs","cms","adapter"],"_id":"@blogree/nextjs-adapter@1.0.1","maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"dist":{"shasum":"27d30d5e97ffa68a938a477648235aaf5521722a","tarball":"https://registry.npmjs.org/@blogree/nextjs-adapter/-/nextjs-adapter-1.0.1.tgz","fileCount":13,"integrity":"sha512-/v70JUoDsZK/HLUgE9Lu/5oxTgJFtKEdu0pbBcMFUzvrArhZZu8z8rgQ6pzzGwGOF8Do8gshgeiTZFM0KaiNig==","signatures":[{"sig":"MEUCIEV1ESfqSAe8VPqm4UMtxIAkEs5sI2M/VESPLLXONgXoAiEA/JG8sZJPxmGi4hSxIyDUc/b2THKzQ1UagH5PWehruhM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41997},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"bbdfeac497d32a288b88fb14651677889096abee","scripts":{"dev":"tsc --watch","build":"tsc"},"_npmUser":{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"},"_npmVersion":"10.8.2","description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","directories":{},"_nodeVersion":"20.17.0","dependencies":{"crypto":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"next":"^14.1.0","typescript":"^5.3.3","@types/node":"^20.11.5"},"peerDependencies":{"next":">=13.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nextjs-adapter_1.0.1_1775464011361_0.23413973106467934","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@blogree/nextjs-adapter","version":"1.0.2","keywords":["blogree","nextjs","cms","adapter"],"_id":"@blogree/nextjs-adapter@1.0.2","maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"dist":{"shasum":"377ea30b9baa18946e7f26c2316d977b6b26f330","tarball":"https://registry.npmjs.org/@blogree/nextjs-adapter/-/nextjs-adapter-1.0.2.tgz","fileCount":13,"integrity":"sha512-0LTi4t2UixY/e5LowM/Aj1wjntFHjHLX/U9fwvzTknLUlEi4pxuQ6A4Y+bTfOE0QBOJeWur2ZHtFyqaxuYJKlA==","signatures":[{"sig":"MEQCIGeiDywkz1o+v09OPd+LZ6P9v4CGmYT8gpL+l7UDAOimAiB0SdYGUNBf0F5m9Hq5WW2NWWkoSul/isY3ADNIcQmkdA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44834},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"dda5e3495bbae6a59a0d54543c5fd39d9b7d3b0c","scripts":{"dev":"tsc --watch","build":"tsc"},"_npmUser":{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"},"_npmVersion":"10.8.2","description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","directories":{},"_nodeVersion":"20.17.0","dependencies":{"crypto":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"next":"^14.1.0","typescript":"^5.3.3","@types/node":"^20.11.5"},"peerDependencies":{"next":">=13.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nextjs-adapter_1.0.2_1781718922859_0.10582572326154538","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@blogree/nextjs-adapter","version":"1.0.3","keywords":["blogree","nextjs","cms","adapter"],"_id":"@blogree/nextjs-adapter@1.0.3","maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"dist":{"shasum":"6e3bb5c2aa06556dc3096798646129bd6ef08db0","tarball":"https://registry.npmjs.org/@blogree/nextjs-adapter/-/nextjs-adapter-1.0.3.tgz","fileCount":13,"integrity":"sha512-Mgcn9HsJ3uWDZJkiqQ2xaxrdFsH8KfTd91e/bSxIIsUhUsGnHqvUvKT+qdtVjHrA0IpvqPYNlAj+sCBl2ofzgw==","signatures":[{"sig":"MEYCIQCan5VQ1YXQAbgYMlLLzUUVk8iNkf5F+0CxVz9xSIl6ZgIhAKTxgcd1g5B0U+EuhxoEI8SdFWcIqlj3AkUzPajm/PzI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45585},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"dda5e3495bbae6a59a0d54543c5fd39d9b7d3b0c","scripts":{"dev":"tsc --watch","build":"tsc"},"_npmUser":{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"},"_npmVersion":"10.8.2","description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","directories":{},"_nodeVersion":"20.17.0","dependencies":{"crypto":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"next":"^14.1.0","typescript":"^5.3.3","@types/node":"^20.11.5"},"peerDependencies":{"next":">=13.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nextjs-adapter_1.0.3_1781768550201_0.5800372747305882","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@blogree/nextjs-adapter","version":"1.0.4","description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","license":"MIT","author":{"name":"Blogree"},"homepage":"https://blogree.com/docs/integrations/nextjs-app-router","repository":{"type":"git","url":"git+https://github.com/blogree/blogree.git","directory":"nextjs-adapter"},"bugs":{"url":"https://github.com/blogree/blogree/issues"},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"tsc","dev":"tsc --watch","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["blogree","nextjs","cms","adapter","headless-cms","isr","webhooks"],"devDependencies":{"@types/node":"^20.11.5","next":"^14.1.0","typescript":"^5.3.3"},"peerDependencies":{"next":">=13.0.0"},"_id":"@blogree/nextjs-adapter@1.0.4","gitHead":"ba2fe24ae15dfe3caa7716c7372b659b6db7b6b3","_nodeVersion":"20.17.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-2JF0xa8HI7i2QvvGKJ7bLi0IqsdhZCcxe/dVSntJNazeX2DdnMwvQHxXQYo+Nyw03qPDU1fzVVJen+LvGXgAgg==","shasum":"ab3c059ca02cf8790c135ef742c4b425f1a210d7","tarball":"https://registry.npmjs.org/@blogree/nextjs-adapter/-/nextjs-adapter-1.0.4.tgz","fileCount":7,"unpackedSize":76067,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHEFHiUR/ITJZYucSwTf4lWqFuNCvUFNIOukYKHAO9d8AiEA+RYbdkZYGipHQU3m6cVWpeLSNq/NpvaagwmSJpk++pQ="}]},"_npmUser":{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"},"directories":{},"maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nextjs-adapter_1.0.4_1786924139056_0.3974652740563387"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-03T23:28:38.316Z","modified":"2026-08-16T23:48:59.347Z","1.0.0":"2026-04-03T23:28:38.578Z","1.0.1":"2026-04-06T08:26:51.499Z","1.0.2":"2026-06-17T17:55:22.998Z","1.0.3":"2026-06-18T07:42:30.329Z","1.0.4":"2026-08-16T23:48:59.197Z"},"keywords":["blogree","nextjs","cms","adapter","headless-cms","isr","webhooks"],"description":"Official Next.js adapter for Blogree — pull posts and handle ISR revalidation","maintainers":[{"name":"muhammadyasirkhan","email":"yasirtariqg@gmail.com"}],"readme":"# @blogree/nextjs-adapter\n\nThe official Next.js adapter for [Blogree](https://blogree.com). Blogree is an AI-powered content engine that helps you generate thousands of SEO-optimized articles and sync them directly to your website. Connect your website to your Blogree workspace in minutes. It automatically finds the gaps in your content and generates high-quality, intent-driven articles to fill those gaps. Fetch your blog posts, handle automatic caching (ISR), and set up secure webhooks with almost zero configuration.\n\n---\n\n## What's new in 1.0.4\n\n- **`getAllBlogreePosts()`** — fetches every post, paging for you. Use it in\n  `generateStaticParams`, `getStaticPaths` and sitemaps so large sites build\n  completely. `getPostsPage()` gives you a page plus `total` and `hasMore` if you\n  prefer to page yourself.\n- **Granular cache invalidation** — publishing a post refreshes your index pages\n  and that post, leaving the rest of your cache warm. Set\n  `revalidateStrategy: 'all'` to refresh everything instead.\n- **`generatePostSchemaScript()`** — JSON-LD output ready to drop straight into a\n  `<script type=\"application/ld+json\">` tag, correctly escaped.\n- **Timestamped webhook signatures** — `X-Blogree-Signature-V2` binds each\n  delivery to a timestamp, with a 5-minute window. The adapter reads it\n  automatically and falls back to the original header, so nothing changes on your\n  side.\n- **Automatic retries** — 429 and 5xx responses from the Blogree API are retried\n  with `Retry-After` honoured, so a busy moment doesn't fail your page render.\n- **`updated_at` on every post** — `dateModified` in your structured data now\n  reflects real edits.\n- **One consistent post shape** — posts fetched over the Pull API and posts\n  delivered by webhook are normalized to the same `BlogreePost` type.\n- **Zero runtime dependencies**, MIT licensed, Node 18+.\n\n### Before you upgrade\n\nSet `BLOGREE_WEBHOOK_SECRET` in the environment you deploy to — the webhook\nhandler requires it. And deploy fresh rather than swapping the package on a warm\ncache, so the new cache tags take effect.\n\n---\n\n## 🚀 5-Minute Integration Guide\n\nIf you just want to get your blog up and running quickly, follow these steps. The code below is designed so you can simply copy and paste it into your project.\n\n### Step 1: Install the package\n\n```bash\nnpm install @blogree/nextjs-adapter\n```\n\nOr with yarn:\n\n```bash\nyarn add @blogree/nextjs-adapter\n```\n\nOr with pnpm:\n\n```bash\npnpm add @blogree/nextjs-adapter\n```\n\n\n### Step 2: Add your Environment Variables\n\n1. Log in to your [Blogree Dashboard](https://app.blogree.com/login)\n2. Navigate to **Sites**, and add your website there \n3. Copy:\n   - **Pull API Key** (for fetching posts)\n   - **Webhook Secret** (for signature verification)\n4. Add them to your `.env.local` file:\n\n```env\nBLOGREE_API_KEY=your_pull_api_key\nBLOGREE_WEBHOOK_SECRET=your_webhook_secret\n```\n\n### Step 3: Fetch and Display Posts\n\nWe provide a simple helper function `getBlogreePosts` to fetch your content. Here is a perfect boilerplate for your core blog page using the modern Next.js **App Router**:\n\n```tsx\n// app/blog/page.tsx\nimport { getBlogreePosts } from '@blogree/nextjs-adapter';\nimport Link from 'next/link';\n\nexport default async function BlogPage() {\n  // 1. Fetch your posts from Blogree\n  const posts = await getBlogreePosts({\n    apiKey: process.env.BLOGREE_API_KEY!,\n  });\n\n  // 2. Render them to the screen\n  return (\n    <div style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>\n      <h1>My Blog</h1>\n      {posts.map((post) => (\n        <article key={post.id} style={{ marginBottom: '2rem' }}>\n          {/* Optional: display author */}\n          {post.author && (\n            <p style={{ fontSize: '13px', color: '#6b7280' }}>By {post.author.name}</p>\n          )}\n          <h2>{post.title}</h2>\n          <p>{post.excerpt}</p>\n          <Link href={`/blog/${post.slug}`}>\n            <span style={{ color: 'blue', textDecoration: 'underline' }}>Read more</span>\n          </Link>\n        </article>\n      ))}\n    </div>\n  );\n}\n```\n\n### Step 4: Show a Single Post\n\nWhen a user clicks \"Read more\", they need to go to a dedicated page that displays the content of your post. We use the helper function `getBlogreePost` for this.\n\n```tsx\n// app/blog/[slug]/page.tsx\nimport { getBlogreePost } from '@blogree/nextjs-adapter';\nimport { notFound } from 'next/navigation';\n\nexport default async function BlogPostPage({ params }: { params: { slug: string } }) {\n  // 1. Fetch a single post based on the URL parameter (slug)\n  const post = await getBlogreePost(params.slug, {\n    apiKey: process.env.BLOGREE_API_KEY!,\n  });\n\n  // 2. Show a graceful 404 error if someone types a bad URL structure\n  if (!post) {\n    notFound(); \n  }\n\n  // 3. Render the post HTML\n  return (\n    <article style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>\n      <h1>{post.title}</h1>\n      <time>{new Date(post.published_at).toLocaleDateString()}</time>\n\n      {/* Optional: display the author block */}\n      {post.author && (\n        <div style={{ display: 'flex', alignItems: 'center', gap: '12px', margin: '16px 0', padding: '12px', background: '#f9fafb', borderRadius: '8px' }}>\n          {post.author.avatar_url && (\n            <img src={post.author.avatar_url} alt={post.author.name} style={{ width: '40px', height: '40px', borderRadius: '50%' }} />\n          )}\n          <div>\n            <strong>{post.author.name}</strong>\n            {post.author.bio && <p style={{ margin: 0, fontSize: '13px', color: '#6b7280' }}>{post.author.bio}</p>}\n          </div>\n        </div>\n      )}\n      \n      <div \n        style={{ marginTop: '2rem' }} \n        dangerouslySetInnerHTML={{ __html: post.body.html }} \n      />\n    </article>\n  );\n}\n```\n\n### Step 5: Setup Auto-Updating (Zero-Config Webhooks)\n\nBy default, Next.js caches your pages so they load blazingly fast. But when you write a new post in the Blogree dashboard, Next.js needs to know about it. \n\nWe provide a **zero-config webhook handler** that securely validates the request and automatically clears the proper cache tags for you when you hit \"Publish\".\n\n**First, create an API Route in Next.js:**\n```typescript\n// app/api/blogree/route.ts\nimport { createWebhookHandler } from '@blogree/nextjs-adapter';\n\n// It really is this simple!\nexport const POST = createWebhookHandler({\n  apiKey: process.env.BLOGREE_API_KEY!,\n  webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,\n});\n```\n\n**Next, connect it to your Blogree account:**\nGo to your Blogree Dashboard > **Sites > Your Site > Webhook URL** and add your live URL (e.g., `https://yourwebsite.com/api/blogree`). Select all `post` events.\n\n🎉 **That's it! You've successfully integrated a fully-featured, auto-updating, SEO-friendly blog.**\n\n---\n\n<details>\n<summary><h2>📚 Advanced Developer Reference (Click to expand)</h2></summary>\n\n### Types\nIf you are strictly typing your components, import our standard types:\n\n```typescript\nimport type { BlogreePost, WebhookPayload, BlogreeConfig } from '@blogree/nextjs-adapter';\n\ninterface BlogreePost {\n  id: string;\n  slug: string;\n  title: string;\n  excerpt: string | null;\n  body: {\n    html: string;\n    markdown: string;\n    json: Record<string, unknown> | null;\n  };\n  meta: {\n    title: string | null;\n    description: string | null;\n    og_image: string | null;\n  };\n  tags: string[];\n  published_at: string;\n  status: string;\n  version: number;\n  // v1.0.2: Author attribution support\n  author?: {\n    name: string;\n    slug: string;\n    bio: string | null;\n    avatar_url: string | null;\n  } | null;\n}\n```\n\n### Author Attribution (New in v1.0.2)\n\nEach post now optionally includes an `author` object when an author has been assigned in the Blogree dashboard. You can use this to render author bylines, bios, and profile images anywhere in your blog.\n\n```tsx\n{post.author && (\n  <div className=\"author-card\">\n    {post.author.avatar_url && <img src={post.author.avatar_url} alt={post.author.name} />}\n    <span>By {post.author.name}</span>\n    {post.author.bio && <p>{post.author.bio}</p>}\n  </div>\n)}\n```\n\n### Advanced Client Class\nInstead of the helper functions from Step 3, if your app is more advanced, you can instantiate our `BlogreeClient` class once and reuse it across files. Notice that `apiUrl` is completely optional for local development overrides!\n\n```typescript\nimport { BlogreeClient } from '@blogree/nextjs-adapter';\n\nconst client = new BlogreeClient({\n  apiKey: process.env.BLOGREE_API_KEY!,\n  webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,\n  // apiUrl: 'http://localhost:4000' // Override for local testing only\n});\n\n// Fetch one page of posts (10 by default, 100 max)\nconst posts = await client.getPosts({ limit: 10, page: 1, tag: 'technology' });\n\n// Fetch every post, paging automatically. Use this for generateStaticParams,\n// getStaticPaths and sitemaps so large sites build completely.\nconst all = await client.getAllPosts();\n\n// A page plus its metadata, if you want to page yourself\nconst { posts: page1, total, hasMore } = await client.getPostsPage({ limit: 50 });\n\n// Fetch a single post\nconst post = await client.getPost('my-post-slug');\n\n// Manually confirm a delivery status back to Blogree\nawait client.confirmDelivery(postId, 'success');\nawait client.confirmDelivery(postId, 'failed', 'Rendering error occurred');\n```\n\n### Structured Data (JSON-LD)\n\n`generatePostSchemaScript()` returns a JSON-LD string ready to inject, with the\ncharacters that matter inside a `<script>` tag already escaped. Prefer it over\nserialising `generatePostSchema()` yourself.\n\n```tsx\nimport { getBlogreePost, generatePostSchemaScript } from '@blogree/nextjs-adapter';\n\nconst post = await getBlogreePost(slug, config);\n\n<script\n  type=\"application/ld+json\"\n  dangerouslySetInnerHTML={{\n    __html: generatePostSchemaScript(post, {\n      siteUrl: 'https://mysite.com',\n      siteName: 'My Blog',        // without this, publisher.name falls back to\n                                  // the hostname — pass it to control your brand\n      logoUrl: 'https://mysite.com/logo.png',\n    }),\n  }}\n/>\n```\n\n### Cache Invalidation\n\nFetches are tagged so a publish only clears what changed:\n\n| Fetch | Tags |\n|---|---|\n| `getPosts`, `getPostsPage`, `getAllPosts` | `blogree`, `blogree-posts` |\n| `getPost(slug)` | `blogree`, `blogree-post-<slug>` |\n\nThe default webhook handler clears `blogree-posts` — so every index, tag page and\nsitemap updates immediately — plus the post that changed. Unchanged post pages\nkeep their cache, which keeps large sites fast and well inside API rate limits.\n\n```typescript\ncreateWebhookHandler({\n  apiKey: process.env.BLOGREE_API_KEY!,\n  webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,\n  revalidateStrategy: 'all',   // refresh every post instead\n  maxRetries: 2,               // retries on 429/5xx, honours Retry-After\n});\n```\n\n### Manual Delivery Confirmation\nThe `confirmDelivery()` method lets you manually report the status of a post delivery back to your Blogree dashboard. This is useful when you have custom webhook logic and want Blogree's analytics to accurately reflect delivery success or failure.\n\n```typescript\n// Inside a custom webhook handler:\nawait client.confirmDelivery(payload.post.id, 'success');\n\n// Or on failure:\nawait client.confirmDelivery(payload.post.id, 'failed', 'Database write failed');\n```\n\n</details>\n\n<details>\n<summary><h2>👴 Supporting the Legacy Pages Router (Click to expand)</h2></summary>\n\nIf you are using the older Next.js `pages/` directory instead of the `app/` router, use our dedicated pages router handler. Manual revalidation requires providing paths.\n\n**Webhook Handler for Pages Router:**\n```typescript\n// pages/api/blogree/webhooks.ts\nimport { createPagesWebhookHandler } from '@blogree/nextjs-adapter';\n\nexport default createPagesWebhookHandler(\n  {\n    apiKey: process.env.BLOGREE_API_KEY!,\n    webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,\n  },\n  async (payload, res) => {\n    // Manual ISR revalidation\n    await res.revalidate('/blog');\n    await res.revalidate(`/blog/${payload.post.slug}`);\n  }\n);\n```\n\n</details>\n\n<details>\n<summary><h2>🔧 Troubleshooting & FAQs (Click to expand)</h2></summary>\n\n- **\"Posts aren't appearing on my live production site.\"**\n  Make sure you have set the environment variables in your hosting provider's dashboard (like Vercel or Netlify), not just locally in `.env.local`.\n- **\"Webhooks are failing or returning Unauthorized error 401.\"**\n  Double check that your `BLOGREE_WEBHOOK_SECRET` matches exactly what is running in your Blogree dashboard. The adapter strictly verifies the HMAC-SHA256 signature to protect your site.\n- **\"The `author` field is always `null`.\"**\n  Authors must be created and assigned to a post inside the Blogree Dashboard. Navigate to **Posts → Edit Post → Author** to assign one.\n- **\"TypeScript errors with next/cache\"**\n  Ensure your `tsconfig.json` includes the correct libs:\n  `\"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"]`\n\n</details>\n\n---\n**Still stuck?** [View Documentation](https://docs.blogree.com) • [Report an Issue](https://github.com/blogree/nextjs-adapter/issues)\n","readmeFilename":"README.md","homepage":"https://blogree.com/docs/integrations/nextjs-app-router","repository":{"type":"git","url":"git+https://github.com/blogree/blogree.git","directory":"nextjs-adapter"},"author":{"name":"Blogree"},"bugs":{"url":"https://github.com/blogree/blogree/issues"},"license":"MIT"}