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.
Files changed (113) hide show
  1. package/README.md +84 -21
  2. package/dist/admin/index.cjs +656 -115
  3. package/dist/admin/index.cjs.map +1 -1
  4. package/dist/admin/index.d.cts +7 -3
  5. package/dist/admin/index.d.ts +7 -3
  6. package/dist/admin/index.js +575 -37
  7. package/dist/admin/index.js.map +1 -1
  8. package/dist/api/categories.cjs +32 -32
  9. package/dist/api/categories.cjs.map +1 -1
  10. package/dist/api/categories.d.cts +1 -1
  11. package/dist/api/categories.d.ts +1 -1
  12. package/dist/api/categories.js +6 -6
  13. package/dist/api/categories.js.map +1 -1
  14. package/dist/api/media.cjs +37 -30
  15. package/dist/api/media.cjs.map +1 -1
  16. package/dist/api/media.d.cts +1 -1
  17. package/dist/api/media.d.ts +1 -1
  18. package/dist/api/media.js +13 -6
  19. package/dist/api/media.js.map +1 -1
  20. package/dist/api/posts.cjs +39 -39
  21. package/dist/api/posts.cjs.map +1 -1
  22. package/dist/api/posts.d.cts +1 -1
  23. package/dist/api/posts.d.ts +1 -1
  24. package/dist/api/posts.js +6 -6
  25. package/dist/api/posts.js.map +1 -1
  26. package/dist/api/rss.cjs +3 -3
  27. package/dist/api/rss.js +2 -2
  28. package/dist/api/settings.cjs +13 -13
  29. package/dist/api/settings.cjs.map +1 -1
  30. package/dist/api/settings.d.cts +1 -1
  31. package/dist/api/settings.d.ts +1 -1
  32. package/dist/api/settings.js +5 -5
  33. package/dist/api/settings.js.map +1 -1
  34. package/dist/api/sitemap.cjs +3 -3
  35. package/dist/api/sitemap.js +2 -2
  36. package/dist/api/tokens.cjs +56 -0
  37. package/dist/api/tokens.cjs.map +1 -0
  38. package/dist/api/tokens.d.cts +22 -0
  39. package/dist/api/tokens.d.ts +22 -0
  40. package/dist/api/tokens.js +52 -0
  41. package/dist/api/tokens.js.map +1 -0
  42. package/dist/{chunk-6HKMZOI4.cjs → chunk-3BKPNOES.cjs} +8 -7
  43. package/dist/chunk-3BKPNOES.cjs.map +1 -0
  44. package/dist/{chunk-N5MKAD7J.cjs → chunk-DR7QNI32.cjs} +6 -2
  45. package/dist/chunk-DR7QNI32.cjs.map +1 -0
  46. package/dist/{chunk-QE4VLQYN.cjs → chunk-F47RPOTU.cjs} +13 -10
  47. package/dist/chunk-F47RPOTU.cjs.map +1 -0
  48. package/dist/{chunk-64HUVJOZ.js → chunk-JI2RK6KX.js} +80 -13
  49. package/dist/chunk-JI2RK6KX.js.map +1 -0
  50. package/dist/{chunk-R6MO3QIP.js → chunk-NSR7NYSB.js} +6 -5
  51. package/dist/chunk-NSR7NYSB.js.map +1 -0
  52. package/dist/{chunk-4PY224XM.js → chunk-O3XES5O2.js} +6 -3
  53. package/dist/chunk-O3XES5O2.js.map +1 -0
  54. package/dist/{chunk-4NKOJYWJ.js → chunk-OOUJYUGP.js} +8 -7
  55. package/dist/chunk-OOUJYUGP.js.map +1 -0
  56. package/dist/{chunk-A2S32RZN.js → chunk-OWWWTTUT.js} +8 -3
  57. package/dist/chunk-OWWWTTUT.js.map +1 -0
  58. package/dist/{chunk-E2QLTHKN.cjs → chunk-QBZLGBHQ.cjs} +11 -10
  59. package/dist/chunk-QBZLGBHQ.cjs.map +1 -0
  60. package/dist/{chunk-ZP5XRVVH.cjs → chunk-SUJT6LWH.cjs} +12 -7
  61. package/dist/chunk-SUJT6LWH.cjs.map +1 -0
  62. package/dist/{chunk-JM7QRXXK.js → chunk-TVHY4BR2.js} +10 -7
  63. package/dist/chunk-TVHY4BR2.js.map +1 -0
  64. package/dist/{chunk-JLPJKNRZ.js → chunk-UMIBGO4S.js} +18 -5
  65. package/dist/chunk-UMIBGO4S.js.map +1 -0
  66. package/dist/{chunk-U2ROR6AY.cjs → chunk-VWKVU3SE.cjs} +86 -12
  67. package/dist/chunk-VWKVU3SE.cjs.map +1 -0
  68. package/dist/{chunk-KDZER3PU.cjs → chunk-YTJQ426D.cjs} +19 -5
  69. package/dist/chunk-YTJQ426D.cjs.map +1 -0
  70. package/dist/cli/index.cjs +90 -19
  71. package/dist/components/index.cjs +12 -6
  72. package/dist/components/index.cjs.map +1 -1
  73. package/dist/components/index.d.cts +2 -1
  74. package/dist/components/index.d.ts +2 -1
  75. package/dist/components/index.js +12 -6
  76. package/dist/components/index.js.map +1 -1
  77. package/dist/db-OUSQPM53.js +3 -0
  78. package/dist/db-OUSQPM53.js.map +1 -0
  79. package/dist/db-RFY6O5UE.cjs +108 -0
  80. package/dist/db-RFY6O5UE.cjs.map +1 -0
  81. package/dist/editor/index.cjs +49 -12
  82. package/dist/editor/index.cjs.map +1 -1
  83. package/dist/editor/index.d.cts +5 -1
  84. package/dist/editor/index.d.ts +5 -1
  85. package/dist/editor/index.js +37 -1
  86. package/dist/editor/index.js.map +1 -1
  87. package/dist/{index-vjlZDWNr.d.cts → index-Bk8gOqBq.d.cts} +25 -21
  88. package/dist/{index-Cgzphklp.d.ts → index-DsnG2kdW.d.ts} +25 -21
  89. package/dist/index.cjs +47 -47
  90. package/dist/index.d.cts +3 -3
  91. package/dist/index.d.ts +3 -3
  92. package/dist/index.js +5 -5
  93. package/dist/lib/index.cjs +39 -35
  94. package/dist/lib/index.d.cts +2 -2
  95. package/dist/lib/index.d.ts +2 -2
  96. package/dist/lib/index.js +5 -5
  97. package/dist/{types-CBEEBR4A.d.ts → types-Cu515Egx.d.cts} +16 -1
  98. package/dist/{types-CBEEBR4A.d.cts → types-Cu515Egx.d.ts} +16 -1
  99. package/package.json +1 -1
  100. package/dist/chunk-4NKOJYWJ.js.map +0 -1
  101. package/dist/chunk-4PY224XM.js.map +0 -1
  102. package/dist/chunk-64HUVJOZ.js.map +0 -1
  103. package/dist/chunk-6HKMZOI4.cjs.map +0 -1
  104. package/dist/chunk-A2S32RZN.js.map +0 -1
  105. package/dist/chunk-E2QLTHKN.cjs.map +0 -1
  106. package/dist/chunk-JLPJKNRZ.js.map +0 -1
  107. package/dist/chunk-JM7QRXXK.js.map +0 -1
  108. package/dist/chunk-KDZER3PU.cjs.map +0 -1
  109. package/dist/chunk-N5MKAD7J.cjs.map +0 -1
  110. package/dist/chunk-QE4VLQYN.cjs.map +0 -1
  111. package/dist/chunk-R6MO3QIP.js.map +0 -1
  112. package/dist/chunk-U2ROR6AY.cjs.map +0 -1
  113. 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
- # Cloudflare R2 Storage
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
- # Site Info
78
- NEXTBLOGKIT_SITE_URL=https://yourdomain.com
79
- NEXTBLOGKIT_SITE_NAME="Your Site Name"
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 it to `AdminLayout`:
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
- If you want to try NextBlogKit locally without Cloudflare R2, images will fall back to `URL.createObjectURL` (browser-only, non-persistent). For a fully working local setup:
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. **R2** — Create a free Cloudflare R2 bucket at [dash.cloudflare.com](https://dash.cloudflare.com). The free tier includes 10 GB storage and 10 million reads/month.
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)