@xcript-dev/next 0.1.2 → 0.1.3

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 (2) hide show
  1. package/README.md +130 -58
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,18 +1,38 @@
1
1
  # @xcript-dev/next
2
2
 
3
- > Next.js integration for [Xcript](https://xcript.dev) middleware, React hooks, and server utilities for license validation.
3
+ **Protect your Next.js app with license validation in 2 minutes.**
4
+
5
+ Edge middleware · React hooks · Server utilities · Zero boilerplate.
4
6
 
5
7
  [![npm](https://img.shields.io/npm/v/@xcript-dev/next)](https://www.npmjs.com/package/@xcript-dev/next)
6
8
  [![bundle size](https://img.shields.io/bundlephobia/minzip/@xcript-dev/next)](https://bundlephobia.com/package/@xcript-dev/next)
7
- [![license](https://img.shields.io/npm/l/@xcript-dev/next)](https://github.com/xcript/xcript-js/blob/main/LICENSE)
8
9
 
9
- ## Install
10
+ ---
11
+
12
+ ## Why This Instead of the Core SDK?
13
+
14
+ | | `@xcript-dev/sdk` | `@xcript-dev/next` |
15
+ |--|---|---|
16
+ | Validate a license | ✅ Manual call | ✅ **Automatic** at the edge |
17
+ | Cache results | ✅ Disk file | ✅ **httpOnly cookie** (no disk, no state) |
18
+ | Protect routes | ❌ Build it yourself | ✅ **One line** — `protectedRoutes: ['/dashboard/*']` |
19
+ | React UI gating | ❌ Build it yourself | ✅ **`useLicense()` hook** |
20
+ | Server Actions | ❌ Build it yourself | ✅ **`requireLicense()`** |
21
+ | Works with App Router | — | ✅ Built for it |
22
+
23
+ **If you use Next.js, use this package.** It saves you hours of glue code.
24
+
25
+ ---
26
+
27
+ ## Quick Start — 2 Minutes
28
+
29
+ ### 1. Install
10
30
 
11
31
  ```bash
12
32
  npm install @xcript-dev/next
13
33
  ```
14
34
 
15
- ## 1. Middleware — Protect Routes
35
+ ### 2. Add Middleware
16
36
 
17
37
  ```typescript
18
38
  // middleware.ts
@@ -30,100 +50,152 @@ export const config = {
30
50
  }
31
51
  ```
32
52
 
33
- Validates once, caches in a cookie, re-validates every 5 minutes. If invalid → redirects to `onInvalid`.
53
+ ### 3. Done.
34
54
 
35
- ## 2. React Hook Conditional UI
55
+ Every request to `/dashboard/*` now validates the license automatically. Invalid? Redirected. Valid? Passes through. Cached for 5 minutes.
36
56
 
37
- ```tsx
38
- 'use client'
39
- import { useLicense } from '@xcript-dev/next/client'
57
+ ---
40
58
 
41
- function PremiumFeature() {
42
- const { isValid, config, isLoading } = useLicense()
59
+ ## What You Get
43
60
 
44
- if (isLoading) return <Spinner />
45
- if (!isValid) return <UpgradePrompt />
61
+ - **🛡️ Edge validation** — License checked before your page even renders
62
+ - **🍪 Automatic caching** — Result stored in httpOnly cookie, re-validates every 5 min
63
+ - **⚛️ React hook** — `useLicense()` for conditional UI in client components
64
+ - **🔒 Server utilities** — `requireLicense()` for protected Server Actions
65
+ - **🎛️ Feature flags** — `config['max_users']` from your dashboard, no redeploy
66
+ - **🚫 Kill switch** — Revoke access instantly, middleware blocks on next request
67
+ - **📦 5 KB** — Tiny. No bloat.
46
68
 
47
- return <PremiumContent maxUsers={config.max_users} />
48
- }
69
+ ---
70
+
71
+ ## Full Example: Protected SaaS Dashboard
72
+
73
+ ### `middleware.ts` — Gate all dashboard routes
74
+
75
+ ```typescript
76
+ import { withXcript } from '@xcript-dev/next'
77
+
78
+ export default withXcript({
79
+ apiKey: process.env.XCRIPT_API_KEY!,
80
+ licenseKey: process.env.XCRIPT_LICENSE_KEY!,
81
+ protectedRoutes: ['/dashboard/*'],
82
+ onInvalid: '/license-expired',
83
+ revalidateInterval: 300, // Re-check every 5 min
84
+ })
85
+
86
+ export const config = { matcher: ['/dashboard/:path*'] }
49
87
  ```
50
88
 
51
- ## 3. Provider Wrap Your Layout
89
+ ### `app/layout.tsx`Provide license context
52
90
 
53
91
  ```tsx
54
- // app/layout.tsx
55
92
  import { XcriptProvider } from '@xcript-dev/next/client'
56
93
 
57
- export default function Layout({ children }) {
94
+ export default function DashboardLayout({ children }) {
58
95
  return <XcriptProvider>{children}</XcriptProvider>
59
96
  }
60
97
  ```
61
98
 
62
- ## 4. Server Utilities Protect Actions
99
+ ### `app/dashboard/reports/page.tsx` Gate UI by features
63
100
 
64
- ```typescript
65
- // Server Action or Route Handler
66
- import { requireLicense } from '@xcript-dev/next/server'
101
+ ```tsx
102
+ 'use client'
103
+ import { useLicense } from '@xcript-dev/next/client'
104
+
105
+ export default function ReportsPage() {
106
+ const { isValid, config, isLoading } = useLicense()
67
107
 
68
- export async function POST() {
69
- const license = await requireLicense() // Throws if invalid
70
- const maxReports = license.config['max_reports']
71
- return Response.json({ ok: true })
108
+ if (isLoading) return <p>Loading...</p>
109
+ if (!isValid) return <p>License required. <a href="/pricing">Upgrade</a></p>
110
+
111
+ const canExport = config['features']?.includes('export')
112
+
113
+ return (
114
+ <div>
115
+ <h1>Reports</h1>
116
+ <p>Max users: {config['max_users'] || '∞'}</p>
117
+ {canExport && <button>Export CSV</button>}
118
+ </div>
119
+ )
72
120
  }
73
121
  ```
74
122
 
75
- ### Other server utilities
123
+ ### `app/actions/generate.ts` — Protect server logic
76
124
 
77
125
  ```typescript
78
- import { getLicense, getLicenseConfig } from '@xcript-dev/next/server'
126
+ 'use server'
127
+ import { requireLicense } from '@xcript-dev/next/server'
128
+
129
+ export async function generateReport(data: FormData) {
130
+ const license = await requireLicense() // Throws 403 if invalid
131
+
132
+ const maxReports = parseInt(license.config['max_reports'] || '10')
133
+ // ... generate report
134
+ }
135
+ ```
136
+
137
+ ---
79
138
 
80
- // Returns null if invalid (no throw)
81
- const license = await getLicense()
139
+ ## How It Works
82
140
 
83
- // Get a single config value
84
- const maxUsers = await getLicenseConfig('max_users')
85
141
  ```
142
+ Request hits your app
143
+
144
+
145
+ Middleware checks cookie (__xcript_status)
146
+
147
+ ├── ✅ Cookie valid + fresh (<5 min) → Pass through
148
+
149
+ ├── ⏰ Cookie expired → Re-validate against Xcript API
150
+ │ ├── ✅ Valid → Update cookie → Pass through
151
+ │ └── ❌ Invalid → Redirect to /license-expired
152
+
153
+ └── 🆕 No cookie → Validate against Xcript API
154
+ ├── ✅ Valid → Set cookie → Pass through
155
+ └── ❌ Invalid → Redirect to /license-expired
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Configuration
86
161
 
87
- ## Middleware Options
162
+ ### Middleware Options
88
163
 
89
- | Option | Type | Required | Default | Description |
90
- |--------|------|----------|---------|-------------|
91
- | `apiKey` | `string` | | — | Your API key (`xk_...`) |
92
- | `licenseKey` | `string` | | — | License key to validate |
93
- | `publicKey` | `string` | — | — | Ed25519 public key (hex) |
94
- | `protectedRoutes` | `string[]` | — | All routes | Glob patterns (`*` wildcard) |
95
- | `onInvalid` | `string` | — | Returns 403 | Redirect path on failure |
96
- | `revalidateInterval` | `number` | — | `300` (5 min) | Re-validation interval in seconds |
164
+ | Option | Type | Default | Description |
165
+ |--------|------|---------|-------------|
166
+ | `apiKey` | `string` | Required | Your API key (`xk_...`) |
167
+ | `licenseKey` | `string` | Required | License key to validate |
168
+ | `publicKey` | `string` | — | Ed25519 public key for signature verification |
169
+ | `protectedRoutes` | `string[]` | All routes | Glob patterns to protect |
170
+ | `onInvalid` | `string` | Returns 403 | Redirect path on invalid license |
171
+ | `revalidateInterval` | `number` | `300` (5 min) | Seconds between re-validations |
172
+ | `baseUrl` | `string` | `https://api.xcript.dev` | API base URL |
97
173
 
98
- ## Environment Variables
174
+ ### Environment Variables
99
175
 
100
176
  ```env
101
177
  XCRIPT_API_KEY=xk_your_api_key
102
178
  XCRIPT_LICENSE_KEY=XCR-XXXX-XXXX-XXXX
179
+ XCRIPT_PUBLIC_KEY=ed25519_hex_optional
103
180
  ```
104
181
 
105
- ## How It Works
106
-
107
- ```
108
- Request → Middleware checks cookie
109
- ├── Cookie valid + fresh → Pass through ✅
110
- ├── Cookie expired → Re-validate against API
111
- │ ├── Valid → Update cookie, pass through ✅
112
- │ └── Invalid → Redirect to onInvalid ❌
113
- └── No cookie → Validate against API
114
- ├── Valid → Set cookie, pass through ✅
115
- └── Invalid → Redirect to onInvalid ❌
116
- ```
182
+ ---
117
183
 
118
184
  ## Requirements
119
185
 
120
- - Next.js ≥ 14
186
+ - Next.js ≥ 14 (App Router)
121
187
  - React ≥ 18
122
188
 
123
189
  ## Core SDK
124
190
 
125
- This package uses [`@xcript-dev/sdk`](https://www.npmjs.com/package/@xcript-dev/sdk) under the hood. For non-Next.js projects, install the SDK directly.
191
+ For non-Next.js projects [`@xcript-dev/sdk`](https://www.npmjs.com/package/@xcript-dev/sdk)
192
+
193
+ ## Links
194
+
195
+ - 🌐 [xcript.dev](https://xcript.dev)
196
+ - 📖 [Documentation](https://xcript.dev/docs)
197
+ - 🐛 [Issues](https://github.com/xcript/xcript-js/issues)
126
198
 
127
- ## License
199
+ ---
128
200
 
129
- MIT [xcript.dev](https://xcript.dev)
201
+ MIT © [Xcript](https://xcript.dev)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcript-dev/next",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Next.js integration for Xcript — middleware, hooks, and server utilities for license validation",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",