nextblogkit 0.6.2 → 0.7.2
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.
- package/README.md +84 -21
- package/dist/admin/index.cjs +656 -115
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.d.cts +7 -3
- package/dist/admin/index.d.ts +7 -3
- package/dist/admin/index.js +575 -37
- package/dist/admin/index.js.map +1 -1
- package/dist/api/categories.cjs +32 -32
- package/dist/api/categories.cjs.map +1 -1
- package/dist/api/categories.d.cts +1 -1
- package/dist/api/categories.d.ts +1 -1
- package/dist/api/categories.js +6 -6
- package/dist/api/categories.js.map +1 -1
- package/dist/api/media.cjs +37 -30
- package/dist/api/media.cjs.map +1 -1
- package/dist/api/media.d.cts +1 -1
- package/dist/api/media.d.ts +1 -1
- package/dist/api/media.js +13 -6
- package/dist/api/media.js.map +1 -1
- package/dist/api/posts.cjs +39 -39
- package/dist/api/posts.cjs.map +1 -1
- package/dist/api/posts.d.cts +1 -1
- package/dist/api/posts.d.ts +1 -1
- package/dist/api/posts.js +6 -6
- package/dist/api/posts.js.map +1 -1
- package/dist/api/rss.cjs +3 -3
- package/dist/api/rss.js +2 -2
- package/dist/api/settings.cjs +13 -13
- package/dist/api/settings.cjs.map +1 -1
- package/dist/api/settings.d.cts +1 -1
- package/dist/api/settings.d.ts +1 -1
- package/dist/api/settings.js +5 -5
- package/dist/api/settings.js.map +1 -1
- package/dist/api/sitemap.cjs +3 -3
- package/dist/api/sitemap.js +2 -2
- package/dist/api/tokens.cjs +56 -0
- package/dist/api/tokens.cjs.map +1 -0
- package/dist/api/tokens.d.cts +22 -0
- package/dist/api/tokens.d.ts +22 -0
- package/dist/api/tokens.js +52 -0
- package/dist/api/tokens.js.map +1 -0
- package/dist/{chunk-6HKMZOI4.cjs → chunk-3BKPNOES.cjs} +8 -7
- package/dist/chunk-3BKPNOES.cjs.map +1 -0
- package/dist/{chunk-N5MKAD7J.cjs → chunk-DR7QNI32.cjs} +6 -2
- package/dist/chunk-DR7QNI32.cjs.map +1 -0
- package/dist/{chunk-QE4VLQYN.cjs → chunk-F47RPOTU.cjs} +13 -10
- package/dist/chunk-F47RPOTU.cjs.map +1 -0
- package/dist/{chunk-64HUVJOZ.js → chunk-JI2RK6KX.js} +80 -13
- package/dist/chunk-JI2RK6KX.js.map +1 -0
- package/dist/{chunk-R6MO3QIP.js → chunk-NSR7NYSB.js} +6 -5
- package/dist/chunk-NSR7NYSB.js.map +1 -0
- package/dist/{chunk-4PY224XM.js → chunk-O3XES5O2.js} +6 -3
- package/dist/chunk-O3XES5O2.js.map +1 -0
- package/dist/{chunk-4NKOJYWJ.js → chunk-OOUJYUGP.js} +8 -7
- package/dist/chunk-OOUJYUGP.js.map +1 -0
- package/dist/{chunk-A2S32RZN.js → chunk-OWWWTTUT.js} +8 -3
- package/dist/chunk-OWWWTTUT.js.map +1 -0
- package/dist/{chunk-E2QLTHKN.cjs → chunk-QBZLGBHQ.cjs} +11 -10
- package/dist/chunk-QBZLGBHQ.cjs.map +1 -0
- package/dist/{chunk-ZP5XRVVH.cjs → chunk-SUJT6LWH.cjs} +12 -7
- package/dist/chunk-SUJT6LWH.cjs.map +1 -0
- package/dist/{chunk-JM7QRXXK.js → chunk-TVHY4BR2.js} +10 -7
- package/dist/chunk-TVHY4BR2.js.map +1 -0
- package/dist/{chunk-JLPJKNRZ.js → chunk-UMIBGO4S.js} +18 -5
- package/dist/chunk-UMIBGO4S.js.map +1 -0
- package/dist/{chunk-U2ROR6AY.cjs → chunk-VWKVU3SE.cjs} +86 -12
- package/dist/chunk-VWKVU3SE.cjs.map +1 -0
- package/dist/{chunk-KDZER3PU.cjs → chunk-YTJQ426D.cjs} +19 -5
- package/dist/chunk-YTJQ426D.cjs.map +1 -0
- package/dist/cli/index.cjs +90 -19
- package/dist/components/index.cjs +12 -6
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +2 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +12 -6
- package/dist/components/index.js.map +1 -1
- package/dist/db-OUSQPM53.js +3 -0
- package/dist/db-OUSQPM53.js.map +1 -0
- package/dist/db-RFY6O5UE.cjs +108 -0
- package/dist/db-RFY6O5UE.cjs.map +1 -0
- package/dist/editor/index.cjs +49 -12
- package/dist/editor/index.cjs.map +1 -1
- package/dist/editor/index.d.cts +5 -1
- package/dist/editor/index.d.ts +5 -1
- package/dist/editor/index.js +37 -1
- package/dist/editor/index.js.map +1 -1
- package/dist/{index-vjlZDWNr.d.cts → index-Bk8gOqBq.d.cts} +25 -21
- package/dist/{index-Cgzphklp.d.ts → index-DsnG2kdW.d.ts} +25 -21
- package/dist/index.cjs +47 -47
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/lib/index.cjs +39 -35
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +5 -5
- package/dist/{types-CBEEBR4A.d.ts → types-Cu515Egx.d.cts} +16 -1
- package/dist/{types-CBEEBR4A.d.cts → types-Cu515Egx.d.ts} +16 -1
- package/package.json +1 -1
- package/dist/chunk-4NKOJYWJ.js.map +0 -1
- package/dist/chunk-4PY224XM.js.map +0 -1
- package/dist/chunk-64HUVJOZ.js.map +0 -1
- package/dist/chunk-6HKMZOI4.cjs.map +0 -1
- package/dist/chunk-A2S32RZN.js.map +0 -1
- package/dist/chunk-E2QLTHKN.cjs.map +0 -1
- package/dist/chunk-JLPJKNRZ.js.map +0 -1
- package/dist/chunk-JM7QRXXK.js.map +0 -1
- package/dist/chunk-KDZER3PU.cjs.map +0 -1
- package/dist/chunk-N5MKAD7J.cjs.map +0 -1
- package/dist/chunk-QE4VLQYN.cjs.map +0 -1
- package/dist/chunk-R6MO3QIP.js.map +0 -1
- package/dist/chunk-U2ROR6AY.cjs.map +0 -1
- package/dist/chunk-ZP5XRVVH.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ A complete blog engine for Next.js — admin panel, block editor, SEO, media sto
|
|
|
18
18
|
|
|
19
19
|
- **Next.js 14+** with App Router
|
|
20
20
|
- **MongoDB** (Atlas or self-hosted)
|
|
21
|
-
- **Cloudflare R2** bucket (for media storage)
|
|
22
21
|
- **Node.js 18+**
|
|
22
|
+
- **Cloudflare R2** bucket (optional — for persistent image storage)
|
|
23
23
|
|
|
24
24
|
## Quick Start
|
|
25
25
|
|
|
@@ -61,24 +61,31 @@ cp .env.local.example .env.local
|
|
|
61
61
|
Fill in your values:
|
|
62
62
|
|
|
63
63
|
```env
|
|
64
|
+
# ── REQUIRED ─────────────────────────────────────────────
|
|
64
65
|
# MongoDB Connection
|
|
65
66
|
NEXTBLOGKIT_MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/mydb
|
|
66
67
|
|
|
67
|
-
#
|
|
68
|
-
NEXTBLOGKIT_R2_ACCOUNT_ID=your-account-id
|
|
69
|
-
NEXTBLOGKIT_R2_ACCESS_KEY=your-access-key
|
|
70
|
-
NEXTBLOGKIT_R2_SECRET_KEY=your-secret-key
|
|
71
|
-
NEXTBLOGKIT_R2_BUCKET=blog-media
|
|
72
|
-
NEXTBLOGKIT_R2_PUBLIC_URL=https://media.yourdomain.com
|
|
73
|
-
|
|
74
|
-
# Authentication
|
|
68
|
+
# Authentication (must be at least 32 characters)
|
|
75
69
|
NEXTBLOGKIT_API_KEY=your-secure-api-key-must-be-at-least-32-characters-long
|
|
76
70
|
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
# ── OPTIONAL ─────────────────────────────────────────────
|
|
72
|
+
# Database name (optional — defaults to the database in your connection URI)
|
|
73
|
+
# NEXTBLOGKIT_MONGODB_DB=nextblogkit
|
|
74
|
+
|
|
75
|
+
# Cloudflare R2 Storage (needed for image uploads; without it, images use temporary blob URLs)
|
|
76
|
+
# NEXTBLOGKIT_R2_ACCOUNT_ID=your-account-id
|
|
77
|
+
# NEXTBLOGKIT_R2_ACCESS_KEY=your-access-key
|
|
78
|
+
# NEXTBLOGKIT_R2_SECRET_KEY=your-secret-key
|
|
79
|
+
# NEXTBLOGKIT_R2_BUCKET=blog-media
|
|
80
|
+
# NEXTBLOGKIT_R2_PUBLIC_URL=https://media.yourdomain.com
|
|
81
|
+
|
|
82
|
+
# Site Info (used in SEO meta tags, RSS, sitemap)
|
|
83
|
+
# NEXTBLOGKIT_SITE_URL=https://yourdomain.com
|
|
84
|
+
# NEXTBLOGKIT_SITE_NAME="Your Site Name"
|
|
80
85
|
```
|
|
81
86
|
|
|
87
|
+
> **Only `NEXTBLOGKIT_MONGODB_URI` and `NEXTBLOGKIT_API_KEY` are required to start.** `NEXTBLOGKIT_MONGODB_DB` overrides the database name from the URI. R2 variables are needed for persistent image uploads. Site URL/name are used for SEO — defaults are empty/`"Blog"` if omitted.
|
|
88
|
+
|
|
82
89
|
### 4. Run database migrations
|
|
83
90
|
|
|
84
91
|
```bash
|
|
@@ -525,7 +532,7 @@ import {
|
|
|
525
532
|
| Component | Description |
|
|
526
533
|
|-----------|-------------|
|
|
527
534
|
| `BlogCard` | Post preview card (vertical or horizontal layout) |
|
|
528
|
-
| `BlogSearch` | Search input with instant results dropdown |
|
|
535
|
+
| `BlogSearch` | Search input with instant results dropdown (accepts `basePath` prop) |
|
|
529
536
|
| `TableOfContents` | Heading list with scroll-to and active heading tracking |
|
|
530
537
|
| `ShareButtons` | Social share buttons (Twitter, Facebook, LinkedIn, copy link) |
|
|
531
538
|
| `ReadingProgressBar` | Top-of-page progress bar tied to scroll position |
|
|
@@ -552,6 +559,8 @@ import {
|
|
|
552
559
|
SEOPanel,
|
|
553
560
|
useAdminApi,
|
|
554
561
|
setApiBase,
|
|
562
|
+
setBasePath,
|
|
563
|
+
getBasePath,
|
|
555
564
|
} from 'nextblogkit/admin';
|
|
556
565
|
```
|
|
557
566
|
|
|
@@ -565,8 +574,9 @@ Wraps all admin pages with sidebar navigation and authentication.
|
|
|
565
574
|
| `apiKey` | `string` | — | Pre-set API key (bypasses login prompt) |
|
|
566
575
|
| `apiPath` | `string` | `'/api/blog'` | API route prefix for all admin API calls |
|
|
567
576
|
| `adminPath` | `string` | `'/admin/blog'` | Admin route prefix for sidebar nav links |
|
|
577
|
+
| `basePath` | `string` | `'/blog'` | Public blog URL prefix (used for "View" links in post list and SEO preview) |
|
|
568
578
|
|
|
569
|
-
**Important:** If you change `apiPath` in your config, you **must** pass
|
|
579
|
+
**Important:** If you change `apiPath` or `basePath` in your config, you **must** pass them to `AdminLayout`:
|
|
570
580
|
|
|
571
581
|
```tsx
|
|
572
582
|
// app/admin/blog/layout.tsx
|
|
@@ -575,7 +585,7 @@ import 'nextblogkit/styles/admin.css';
|
|
|
575
585
|
|
|
576
586
|
export default function AdminBlogLayout({ children }: { children: React.ReactNode }) {
|
|
577
587
|
return (
|
|
578
|
-
<AdminLayout apiPath="/api/blogs" adminPath="/admin/blog">
|
|
588
|
+
<AdminLayout apiPath="/api/blogs" adminPath="/admin/blog" basePath="/blogs">
|
|
579
589
|
{children}
|
|
580
590
|
</AdminLayout>
|
|
581
591
|
);
|
|
@@ -636,6 +646,7 @@ export { GET, POST, PUT, DELETE } from 'nextblogkit/api/posts';
|
|
|
636
646
|
export { GET, POST, DELETE } from 'nextblogkit/api/media';
|
|
637
647
|
export { GET, POST, PUT, DELETE } from 'nextblogkit/api/categories';
|
|
638
648
|
export { GET, PUT } from 'nextblogkit/api/settings';
|
|
649
|
+
export { GET, POST, DELETE } from 'nextblogkit/api/tokens';
|
|
639
650
|
export { GET } from 'nextblogkit/api/sitemap';
|
|
640
651
|
export { GET } from 'nextblogkit/api/rss';
|
|
641
652
|
|
|
@@ -727,17 +738,67 @@ All API routes require a Bearer token (`NEXTBLOGKIT_API_KEY`) for write operatio
|
|
|
727
738
|
|
|
728
739
|
> **Note:** These endpoints use the default `/api/blog` prefix. If you changed `apiPath` in your config, replace `/api/blog` with your custom path.
|
|
729
740
|
|
|
741
|
+
### Tokens
|
|
742
|
+
|
|
743
|
+
| Method | Endpoint | Description |
|
|
744
|
+
|--------|----------|-------------|
|
|
745
|
+
| GET | `/api/blog/tokens` | List API tokens (master key only) |
|
|
746
|
+
| POST | `/api/blog/tokens` | Generate new token (master key only) |
|
|
747
|
+
| DELETE | `/api/blog/tokens?id=abc123` | Revoke token (master key only) |
|
|
748
|
+
|
|
730
749
|
### Authentication
|
|
731
750
|
|
|
732
|
-
Include the API key as a Bearer token:
|
|
751
|
+
Include the API key or a generated token as a Bearer token:
|
|
733
752
|
|
|
734
753
|
```bash
|
|
735
754
|
curl -X POST http://localhost:3000/api/blog/posts \
|
|
736
755
|
-H "Authorization: Bearer your-api-key-here" \
|
|
737
756
|
-H "Content-Type: application/json" \
|
|
738
|
-
-d '{"title": "My Post", "content":
|
|
757
|
+
-d '{"title": "My Post", "content": [...], "status": "published"}'
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
**API Tokens** — You can generate scoped API tokens from the admin Settings page (API Access section). Generated tokens work the same as the master key for read/write operations, but cannot manage other tokens. This is useful for CI pipelines, n8n workflows, and other external integrations.
|
|
761
|
+
|
|
762
|
+
### Create Post — Sample JSON
|
|
763
|
+
|
|
764
|
+
```json
|
|
765
|
+
{
|
|
766
|
+
"title": "My Blog Post",
|
|
767
|
+
"content": [{ "type": "paragraph", "content": [{ "type": "text", "text": "Hello world!" }] }],
|
|
768
|
+
"contentHTML": "<p>Hello world!</p>",
|
|
769
|
+
"excerpt": "A short summary of the post",
|
|
770
|
+
"status": "published",
|
|
771
|
+
"categories": ["tech"],
|
|
772
|
+
"tags": ["nextjs", "blog"],
|
|
773
|
+
"author": {
|
|
774
|
+
"name": "John Doe",
|
|
775
|
+
"bio": "Software engineer",
|
|
776
|
+
"avatar": "https://example.com/avatar.jpg"
|
|
777
|
+
},
|
|
778
|
+
"seo": {
|
|
779
|
+
"metaTitle": "My Blog Post | MySite",
|
|
780
|
+
"metaDescription": "A short summary for search engines",
|
|
781
|
+
"focusKeyword": "blog post"
|
|
782
|
+
}
|
|
783
|
+
}
|
|
739
784
|
```
|
|
740
785
|
|
|
786
|
+
| Field | Type | Required | Description |
|
|
787
|
+
|-------|------|----------|-------------|
|
|
788
|
+
| `title` | string | Yes | Post title |
|
|
789
|
+
| `content` | BlockContent[] | No | TipTap JSON content blocks |
|
|
790
|
+
| `contentHTML` | string | No | HTML version of the content |
|
|
791
|
+
| `excerpt` | string | No | Short summary (auto-generated if omitted) |
|
|
792
|
+
| `slug` | string | No | URL slug (auto-generated from title if omitted) |
|
|
793
|
+
| `status` | `"draft"` \| `"published"` \| `"scheduled"` | No | Defaults to `"draft"` |
|
|
794
|
+
| `categories` | string[] | No | Category slugs |
|
|
795
|
+
| `tags` | string[] | No | Tag strings |
|
|
796
|
+
| `author` | `{ name, bio?, avatar?, url? }` | No | Post author info |
|
|
797
|
+
| `seo` | `{ metaTitle?, metaDescription?, focusKeyword?, ... }` | No | SEO metadata |
|
|
798
|
+
| `coverImage` | `{ _id, url, alt?, caption? }` | No | Cover image reference |
|
|
799
|
+
| `publishedAt` | ISO date string | No | Publish date (auto-set when status is `"published"`) |
|
|
800
|
+
| `scheduledAt` | ISO date string | No | Schedule date for future publishing |
|
|
801
|
+
|
|
741
802
|
---
|
|
742
803
|
|
|
743
804
|
## Editor Slash Commands
|
|
@@ -754,6 +815,7 @@ Type `/` in the editor to open the command menu:
|
|
|
754
815
|
| Blockquote | Quote block |
|
|
755
816
|
| Code Block | Syntax-highlighted code |
|
|
756
817
|
| Image | Upload an image |
|
|
818
|
+
| Media Library | Choose from uploaded images (when `onBrowseMedia` is provided) |
|
|
757
819
|
| Table | Insert a 3x3 table |
|
|
758
820
|
| Divider | Horizontal rule |
|
|
759
821
|
| Callout | Info/warning/tip/danger box |
|
|
@@ -852,6 +914,7 @@ app/
|
|
|
852
914
|
├── media/route.ts # Media upload/list/delete
|
|
853
915
|
├── categories/route.ts # Categories CRUD
|
|
854
916
|
├── settings/route.ts # Settings read/update
|
|
917
|
+
├── tokens/route.ts # API token management
|
|
855
918
|
├── sitemap.xml/route.ts # Dynamic sitemap
|
|
856
919
|
└── rss.xml/route.ts # RSS feed
|
|
857
920
|
```
|
|
@@ -862,7 +925,7 @@ Because these are thin wrappers, you can customize any page by editing the gener
|
|
|
862
925
|
|
|
863
926
|
## Local Development (without R2)
|
|
864
927
|
|
|
865
|
-
|
|
928
|
+
NextBlogKit works with just **MongoDB + API key**. Cloudflare R2 is optional — without it, the editor uses temporary blob URLs for images (they won't persist across reloads), and the upload API returns a clear 503 error. This lets you develop locally and add R2 when you're ready.
|
|
866
929
|
|
|
867
930
|
1. **MongoDB** — Use a free [MongoDB Atlas](https://www.mongodb.com/atlas) cluster, or run locally:
|
|
868
931
|
```bash
|
|
@@ -871,13 +934,13 @@ If you want to try NextBlogKit locally without Cloudflare R2, images will fall b
|
|
|
871
934
|
# Then use: NEXTBLOGKIT_MONGODB_URI=mongodb://localhost:27017/nextblogkit
|
|
872
935
|
```
|
|
873
936
|
|
|
874
|
-
2. **
|
|
875
|
-
|
|
876
|
-
3. **API Key** — Generate a secure key:
|
|
937
|
+
2. **API Key** — Generate a secure key:
|
|
877
938
|
```bash
|
|
878
939
|
openssl rand -hex 32
|
|
879
940
|
```
|
|
880
941
|
|
|
942
|
+
3. **R2 (optional)** — Create a free Cloudflare R2 bucket at [dash.cloudflare.com](https://dash.cloudflare.com) for persistent image storage. The free tier includes 10 GB storage and 10 million reads/month.
|
|
943
|
+
|
|
881
944
|
---
|
|
882
945
|
|
|
883
946
|
## Project Structure (package internals)
|