next-blogpanel 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +211 -0
  3. package/dist/admin/index.cjs +3062 -0
  4. package/dist/admin/index.cjs.map +1 -0
  5. package/dist/admin/index.d.cts +51 -0
  6. package/dist/admin/index.d.ts +51 -0
  7. package/dist/admin/index.js +3029 -0
  8. package/dist/admin/index.js.map +1 -0
  9. package/dist/api/categories.cjs +82 -0
  10. package/dist/api/categories.cjs.map +1 -0
  11. package/dist/api/categories.d.cts +27 -0
  12. package/dist/api/categories.d.ts +27 -0
  13. package/dist/api/categories.js +77 -0
  14. package/dist/api/categories.js.map +1 -0
  15. package/dist/api/media-file.cjs +46 -0
  16. package/dist/api/media-file.cjs.map +1 -0
  17. package/dist/api/media-file.d.cts +7 -0
  18. package/dist/api/media-file.d.ts +7 -0
  19. package/dist/api/media-file.js +44 -0
  20. package/dist/api/media-file.js.map +1 -0
  21. package/dist/api/media.cjs +180 -0
  22. package/dist/api/media.cjs.map +1 -0
  23. package/dist/api/media.d.cts +22 -0
  24. package/dist/api/media.d.ts +22 -0
  25. package/dist/api/media.js +176 -0
  26. package/dist/api/media.js.map +1 -0
  27. package/dist/api/posts.cjs +103 -0
  28. package/dist/api/posts.cjs.map +1 -0
  29. package/dist/api/posts.d.cts +27 -0
  30. package/dist/api/posts.d.ts +27 -0
  31. package/dist/api/posts.js +98 -0
  32. package/dist/api/posts.js.map +1 -0
  33. package/dist/api/rss.cjs +25 -0
  34. package/dist/api/rss.cjs.map +1 -0
  35. package/dist/api/rss.d.cts +5 -0
  36. package/dist/api/rss.d.ts +5 -0
  37. package/dist/api/rss.js +23 -0
  38. package/dist/api/rss.js.map +1 -0
  39. package/dist/api/settings.cjs +40 -0
  40. package/dist/api/settings.cjs.map +1 -0
  41. package/dist/api/settings.d.cts +17 -0
  42. package/dist/api/settings.d.ts +17 -0
  43. package/dist/api/settings.js +37 -0
  44. package/dist/api/settings.js.map +1 -0
  45. package/dist/api/sitemap.cjs +25 -0
  46. package/dist/api/sitemap.cjs.map +1 -0
  47. package/dist/api/sitemap.d.cts +5 -0
  48. package/dist/api/sitemap.d.ts +5 -0
  49. package/dist/api/sitemap.js +23 -0
  50. package/dist/api/sitemap.js.map +1 -0
  51. package/dist/api/tokens.cjs +56 -0
  52. package/dist/api/tokens.cjs.map +1 -0
  53. package/dist/api/tokens.d.cts +22 -0
  54. package/dist/api/tokens.d.ts +22 -0
  55. package/dist/api/tokens.js +52 -0
  56. package/dist/api/tokens.js.map +1 -0
  57. package/dist/chunk-2M46MMWN.cjs +76 -0
  58. package/dist/chunk-2M46MMWN.cjs.map +1 -0
  59. package/dist/chunk-4GK22Q3R.cjs +229 -0
  60. package/dist/chunk-4GK22Q3R.cjs.map +1 -0
  61. package/dist/chunk-6PZ772NQ.js +595 -0
  62. package/dist/chunk-6PZ772NQ.js.map +1 -0
  63. package/dist/chunk-BZXPRGLN.cjs +351 -0
  64. package/dist/chunk-BZXPRGLN.cjs.map +1 -0
  65. package/dist/chunk-DAX5C6SC.cjs +86 -0
  66. package/dist/chunk-DAX5C6SC.cjs.map +1 -0
  67. package/dist/chunk-DWNMHQ4I.cjs +57 -0
  68. package/dist/chunk-DWNMHQ4I.cjs.map +1 -0
  69. package/dist/chunk-FPGVR2BX.cjs +121 -0
  70. package/dist/chunk-FPGVR2BX.cjs.map +1 -0
  71. package/dist/chunk-JBP3G4QJ.js +50 -0
  72. package/dist/chunk-JBP3G4QJ.js.map +1 -0
  73. package/dist/chunk-JDP4DIHI.js +215 -0
  74. package/dist/chunk-JDP4DIHI.js.map +1 -0
  75. package/dist/chunk-LIZOVA4W.js +118 -0
  76. package/dist/chunk-LIZOVA4W.js.map +1 -0
  77. package/dist/chunk-QLBTOCT3.js +118 -0
  78. package/dist/chunk-QLBTOCT3.js.map +1 -0
  79. package/dist/chunk-UI2KDZ5H.js +344 -0
  80. package/dist/chunk-UI2KDZ5H.js.map +1 -0
  81. package/dist/chunk-V7QPRX4A.cjs +125 -0
  82. package/dist/chunk-V7QPRX4A.cjs.map +1 -0
  83. package/dist/chunk-VEJFN65Y.js +82 -0
  84. package/dist/chunk-VEJFN65Y.js.map +1 -0
  85. package/dist/chunk-WYZFAI6O.js +74 -0
  86. package/dist/chunk-WYZFAI6O.js.map +1 -0
  87. package/dist/chunk-XLYTATRQ.cjs +637 -0
  88. package/dist/chunk-XLYTATRQ.cjs.map +1 -0
  89. package/dist/cli/index.cjs +2036 -0
  90. package/dist/components/index.cjs +647 -0
  91. package/dist/components/index.cjs.map +1 -0
  92. package/dist/components/index.d.cts +187 -0
  93. package/dist/components/index.d.ts +187 -0
  94. package/dist/components/index.js +633 -0
  95. package/dist/components/index.js.map +1 -0
  96. package/dist/db-M3KXLBUP.js +3 -0
  97. package/dist/db-M3KXLBUP.js.map +1 -0
  98. package/dist/db-TDCZNY3Q.cjs +112 -0
  99. package/dist/db-TDCZNY3Q.cjs.map +1 -0
  100. package/dist/editor/index.cjs +1126 -0
  101. package/dist/editor/index.cjs.map +1 -0
  102. package/dist/editor/index.d.cts +137 -0
  103. package/dist/editor/index.d.ts +137 -0
  104. package/dist/editor/index.js +1093 -0
  105. package/dist/editor/index.js.map +1 -0
  106. package/dist/index-BcNka7gK.d.cts +475 -0
  107. package/dist/index-DPRgaNEE.d.ts +475 -0
  108. package/dist/index.cjs +433 -0
  109. package/dist/index.cjs.map +1 -0
  110. package/dist/index.d.cts +27 -0
  111. package/dist/index.d.ts +27 -0
  112. package/dist/index.js +209 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/lib/index.cjs +193 -0
  115. package/dist/lib/index.cjs.map +1 -0
  116. package/dist/lib/index.d.cts +4 -0
  117. package/dist/lib/index.d.ts +4 -0
  118. package/dist/lib/index.js +8 -0
  119. package/dist/lib/index.js.map +1 -0
  120. package/dist/styles/admin.css +667 -0
  121. package/dist/styles/blog.css +851 -0
  122. package/dist/styles/editor.css +452 -0
  123. package/dist/styles/globals.css +270 -0
  124. package/dist/styles/prose.css +299 -0
  125. package/dist/types-CgrBuig-.d.cts +778 -0
  126. package/dist/types-CgrBuig-.d.ts +778 -0
  127. package/package.json +140 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 blogforge-ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Next BlogPanel
2
+
3
+ A drop-in blog engine for Next.js — admin panel, block editor, SEO, and media, all backed by your own MongoDB.
4
+
5
+ `next-blogpanel` scaffolds a working blog into an existing Next.js App Router project: public pages, an admin CMS, and API routes. You own the database, the files, and the URLs. There is no hosted service and no third-party account to create.
6
+
7
+ ## Features
8
+
9
+ - **Block editor** — TipTap with slash commands, image upload, Shiki code blocks, callouts, FAQ blocks, tables, task lists
10
+ - **Admin panel** — dashboard, post list, block editor, media library, category manager, settings, scoped API tokens
11
+ - **SEO** — meta tags, Open Graph, Twitter Cards, JSON-LD (`BlogPosting`, `BreadcrumbList`, `FAQPage`), sitemap, RSS, and a 17-check SEO scorer
12
+ - **Images stored in your MongoDB by default; Cloudflare R2 optional; anything else pluggable** — GridFS needs no setup at all, R2 takes over when you supply its five environment variables, and `StorageProvider` is public API for the rest
13
+ - **MongoDB backend** — CRUD, slug generation, revision history, full-text search
14
+ - **Components** — two page-level components with slot injection, plus eleven atomic ones for building your own layout
15
+ - **Theming** — colours, fonts, radii and shadows are `--nbp-*` CSS variables, dark mode included
16
+ - **CLI** — `init`, `migrate`, `seed`, `health`
17
+
18
+ ## Prerequisites
19
+
20
+ - Node.js 18+
21
+ - Next.js 14+ using the App Router
22
+ - MongoDB — Atlas free tier is enough, and it stores your images too
23
+
24
+ No object storage account is required.
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Install
29
+
30
+ ```bash
31
+ pnpm add next-blogpanel # or: npm install next-blogpanel
32
+ ```
33
+
34
+ ### 2. Scaffold
35
+
36
+ ```bash
37
+ npx next-blogpanel init
38
+ ```
39
+
40
+ Into your existing `app/` (or `src/app/`) directory this writes:
41
+
42
+ - `app/blog/` — layout, list page, `[slug]` post page, `category/[slug]` page
43
+ - `app/admin/blog/` — layout, dashboard, posts, new, `[id]/edit`, media, categories, settings
44
+ - `app/api/blog/` — posts, media, `media/file/[...key]`, categories, settings, tokens, `sitemap.xml`, `rss.xml`
45
+ - `app/next-blogpanel.setup.ts` — hands your config file to the server at runtime; every scaffolded file imports it
46
+
47
+ …and at the project root, `next-blogpanel.config.ts` and `.env.local.example`. The API routes and admin pages are one-line re-exports; the blog pages are real source built from the atomic components, so they are the ones to edit when you want a different layout. Files that already exist are skipped, never overwritten.
48
+
49
+ ### 3. Configure the environment
50
+
51
+ ```bash
52
+ cp .env.local.example .env.local
53
+ ```
54
+
55
+ ```env
56
+ BLOGPANEL_MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/mydb
57
+ BLOGPANEL_API_KEY=a-secure-key-of-at-least-32-characters
58
+ ```
59
+
60
+ Those two are the only variables you need. Generate the key with `openssl rand -hex 32`.
61
+
62
+ > The generated `.env.local.example` also contains five `BLOGPANEL_R2_*` placeholder lines. **Delete or comment them out unless you have a real Cloudflare R2 bucket.** All five being set — even to placeholder text — is what switches image storage from MongoDB to R2, and uploads will then fail against credentials that do not exist. See [docs/storage.md](docs/storage.md).
63
+
64
+ Other optional variables: `BLOGPANEL_MONGODB_DB` (overrides the database named in the URI), `BLOGPANEL_SITE_URL` and `BLOGPANEL_SITE_NAME` (used in meta tags, sitemap and RSS; default to `""` and `"Blog"`), and `BLOGPANEL_STORAGE`.
65
+
66
+ `BLOGPANEL_SITE_URL` is optional to start but required before you deploy. Images stored in GridFS get root-relative URLs, and `og:image`, `twitter:image`, JSON-LD `image` and RSS `<enclosure>` all have to be absolute — so without it those four are omitted (with a warning) rather than emitted as URLs no crawler can resolve.
67
+
68
+ ### 4. Create the indexes
69
+
70
+ ```bash
71
+ npx next-blogpanel migrate
72
+ ```
73
+
74
+ Creates the MongoDB indexes. If it finds media documents from a pre-1.0 install it upgrades their schema at the same time. Safe to re-run.
75
+
76
+ ### 5. Run
77
+
78
+ ```bash
79
+ pnpm dev
80
+ ```
81
+
82
+ - Blog — <http://localhost:3000/blog>
83
+ - Admin — <http://localhost:3000/admin/blog>
84
+
85
+ The admin panel asks for your `BLOGPANEL_API_KEY` on first visit and validates it against the server before letting you in. From there, **New Post** opens the block editor — type `/` for the command menu — and publishing puts the post on the blog immediately. To see the whole thing populated before writing anything, `npx next-blogpanel seed` inserts three categories and an example post.
86
+
87
+ ## Paths
88
+
89
+ > **Three independent paths, and all three are defaults you own.** Set them at
90
+ > `init` and every scaffolded folder, link, and fetch follows. Nothing in the
91
+ > package hardcodes the word "blog".
92
+ >
93
+ > ```bash
94
+ > npx next-blogpanel init --blog-path /articles --admin-path /admin/articles --api-path /api/articles
95
+ > ```
96
+
97
+ The three flags default to `/blog`, `/admin/blog` and `/api/blog`. Whatever you pass is written into the scaffolded directory names, into the `basePath`/`adminPath`/`apiPath` props of every generated file, and into `next-blogpanel.config.ts`. `init` refuses paths that resolve to the site root, and refuses any two paths that resolve to the same directory.
98
+
99
+ Changing the paths later means re-running `init` with the new flags, updating `next-blogpanel.config.ts`, and removing the old folders. `init` warns you when it spots a tree left behind from a previous run.
100
+
101
+ ## Configuration
102
+
103
+ `next-blogpanel.config.ts` is generated with just the paths and auth strategy. Everything else falls back to a built-in default:
104
+
105
+ ```typescript
106
+ import { defineConfig } from 'next-blogpanel';
107
+
108
+ export default defineConfig({
109
+ basePath: '/blog',
110
+ adminPath: '/admin/blog',
111
+ apiPath: '/api/blog',
112
+ postsPerPage: 10,
113
+ editor: {
114
+ maxImageSize: 2 * 1024 * 1024, // stored ceiling — reached by compression
115
+ maxUploadSize: 10 * 1024 * 1024, // ingest ceiling — enforced by rejection
116
+ autosaveInterval: 30000,
117
+ },
118
+ seo: {
119
+ titleTemplate: '%s | %siteName%',
120
+ generateRSS: true,
121
+ generateSitemap: true,
122
+ structuredData: true,
123
+ },
124
+ features: {
125
+ search: true,
126
+ relatedPosts: true,
127
+ readingProgress: true,
128
+ tableOfContents: true,
129
+ shareButtons: true,
130
+ darkMode: true,
131
+ scheduling: true,
132
+ revisionHistory: true,
133
+ imageOptimization: true,
134
+ },
135
+ auth: { strategy: 'api-key' },
136
+ });
137
+ ```
138
+
139
+ The file only takes effect because `app/next-blogpanel.setup.ts` imports it and calls `setConfig()`, and every scaffolded file imports that module in turn. If you hand-write a route handler or server component that calls a `next-blogpanel` API, import the setup module at the top of it too — [docs/configuration.md](docs/configuration.md#getting-the-config-to-the-server) explains why the import has to be repeated rather than done once.
140
+
141
+ The two image limits are not the same knob and are not interchangeable. `maxUploadSize` (10MB) is the largest file the upload endpoint will accept — anything bigger is rejected with a 413. `maxImageSize` (2MB) is the largest file that will ever be *stored* — anything above it is compressed down, not refused. Full reference: [docs/configuration.md](docs/configuration.md).
142
+
143
+ ## Storage
144
+
145
+ Uploaded images go into your MongoDB via GridFS by default. That needs no configuration, no extra account, and no extra bill. Budget for it honestly, though: one upload is stored as **up to seven objects** — the WebP original plus five responsive widths and a 200x200 thumbnail — so a photo whose original lands at 200KB occupies roughly 500-800KB in total. On the Atlas free tier that puts 512MB at **several hundred images**, not the couple of thousand the original alone would suggest. Deleting a media item reclaims only the original; the derivatives are not tracked and stay behind. See [docs/storage.md](docs/storage.md).
146
+
147
+ Add the five `BLOGPANEL_R2_*` variables and Cloudflare R2 takes over automatically. Set `BLOGPANEL_STORAGE` to force a specific backend regardless of what is configured.
148
+
149
+ Neither one? Implement the exported `StorageProvider` interface, hand the instance to `registerStorageProvider()` in the generated setup module, and set `BLOGPANEL_STORAGE` to its name — Vercel Blob, Supabase Storage, Backblaze B2, ImageKit, UploadThing and plain S3 all fit it. The name is recorded on every media document and read back to route deletes to the right backend; a name that cannot be resolved fails loudly rather than deleting from the wrong one. Worked example in [docs/storage.md](docs/storage.md#custom-storage-providers).
150
+
151
+ Every upload is re-encoded to WebP and stepped down through quality levels (85 → 75 → 65 → 55) and then width caps (2560 → 1920) until it fits under 2MB. A 5MB photo is stored, just smaller. Only files over the 10MB ingest ceiling are refused outright, along with SVGs over 2MB — sharp cannot meaningfully shrink those. Details, cost comparison and the provider interface: [docs/storage.md](docs/storage.md).
152
+
153
+ ## Documentation
154
+
155
+ | Guide | Contents |
156
+ |---|---|
157
+ | [docs/configuration.md](docs/configuration.md) | Every config key and environment variable, CLI flags, what `init` scaffolds |
158
+ | [docs/components.md](docs/components.md) | Page-level and atomic components, props, slots, admin components, stylesheets |
159
+ | [docs/api.md](docs/api.md) | REST endpoints, auth, request/response shapes, package exports, slash commands |
160
+ | [docs/theming.md](docs/theming.md) | All CSS variables, colour presets, dark mode |
161
+ | [docs/storage.md](docs/storage.md) | GridFS vs R2, free-tier comparison, the compression ladder, writing a custom `StorageProvider` |
162
+ | [docs/migrating-from-nextblogkit.md](docs/migrating-from-nextblogkit.md) | Upgrading from `nextblogkit` 0.7.x |
163
+
164
+ ## CLI
165
+
166
+ ```bash
167
+ npx next-blogpanel init # scaffold into your Next.js project
168
+ npx next-blogpanel migrate # create indexes, upgrade a pre-1.0 media schema
169
+ npx next-blogpanel seed # insert example categories and a post
170
+ npx next-blogpanel health # check MongoDB, R2 and environment variables
171
+ ```
172
+
173
+ ## Tech Stack
174
+
175
+ | Layer | Technology |
176
+ |---|---|
177
+ | Framework | Next.js 14+ (App Router) |
178
+ | Editor | TipTap 2.x |
179
+ | Database | MongoDB (native driver) |
180
+ | Storage | MongoDB GridFS, Cloudflare R2, or any backend you register |
181
+ | Image processing | sharp |
182
+ | Syntax highlighting | Shiki |
183
+ | Validation | Zod |
184
+ | CLI | Commander.js |
185
+ | Build | tsup (ESM + CJS) |
186
+
187
+ ## Developing the package
188
+
189
+ ```bash
190
+ git clone https://github.com/butterblogs/next-blogpanel.git
191
+ cd next-blogpanel
192
+ pnpm install
193
+ pnpm build # or: pnpm dev, for watch mode
194
+ pnpm test
195
+ ```
196
+
197
+ To try a local build in a real app, `npm pack` here and install the resulting tarball there, then `rm -rf .next` before restarting the dev server.
198
+
199
+ ## License
200
+
201
+ MIT
202
+
203
+ ---
204
+
205
+ ## Sponsored by ButterBlogs
206
+
207
+ Next BlogPanel is built and sponsored by [ButterBlogs](https://butterblogs.com), an AI content platform that takes a blog post from research to publication.
208
+
209
+ The two fit together through the API: draft and optimise in ButterBlogs, then `POST` to your own `/api/blog/posts` endpoint, or paste into the admin editor. ButterBlogs handles content SEO — keyword targeting, EEAT signals, internal linking. Next BlogPanel handles technical SEO — structured data, sitemap, RSS, meta tags — on infrastructure you control.
210
+
211
+ [Get started with ButterBlogs](https://butterblogs.com)