@nxisai/nxis 2.1.1
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/.github/workflows/deploy.yml +110 -0
- package/README.md +401 -0
- package/bin/deploy.sh +2 -0
- package/build/api.d.ts +244 -0
- package/build/auth.d.ts +91 -0
- package/build/core.d.ts +56 -0
- package/build/index.cjs.js +423 -0
- package/build/index.d.ts +33 -0
- package/build/index.esm.js +417 -0
- package/build/nxis.js +1 -0
- package/build/server.d.ts +77 -0
- package/docs/ssr.md +606 -0
- package/nxisbucket.json +16 -0
- package/package.json +53 -0
- package/rollup.config.js +50 -0
- package/src/api.ts +281 -0
- package/src/auth.ts +171 -0
- package/src/client.ts +104 -0
- package/src/core.ts +124 -0
- package/src/index.ts +33 -0
- package/src/server.ts +106 -0
- package/tsconfig.json +66 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: Deploy nxis.js to S3 and GitHub Packages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-deploy:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout code
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Setup Node.js
|
|
18
|
+
uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '20'
|
|
21
|
+
cache: 'npm'
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: npm ci
|
|
25
|
+
|
|
26
|
+
- name: Build project
|
|
27
|
+
env:
|
|
28
|
+
NXIS_API_HOST: ${{ vars.NXIS_API_HOST || secrets.NXIS_API_HOST }}
|
|
29
|
+
run: npx rollup --config rollup.config.js
|
|
30
|
+
|
|
31
|
+
- name: Configure AWS credentials
|
|
32
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
33
|
+
with:
|
|
34
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
35
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
36
|
+
aws-region: ${{ vars.AWS_REGION || secrets.AWS_REGION }}
|
|
37
|
+
|
|
38
|
+
- name: Deploy to S3
|
|
39
|
+
run: aws s3 cp build/nxis.js s3://nxis-ai-static/nxis.js
|
|
40
|
+
|
|
41
|
+
publish-npm:
|
|
42
|
+
needs: build-and-deploy
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
packages: write
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- name: Checkout code
|
|
50
|
+
uses: actions/checkout@v4
|
|
51
|
+
|
|
52
|
+
- name: Setup Node.js for GitHub Packages
|
|
53
|
+
uses: actions/setup-node@v4
|
|
54
|
+
with:
|
|
55
|
+
node-version: '20'
|
|
56
|
+
cache: 'npm'
|
|
57
|
+
registry-url: 'https://npm.pkg.github.com'
|
|
58
|
+
scope: '@nxisai'
|
|
59
|
+
|
|
60
|
+
- name: Install dependencies
|
|
61
|
+
run: npm ci
|
|
62
|
+
|
|
63
|
+
- name: Build SSR package
|
|
64
|
+
env:
|
|
65
|
+
NXIS_API_HOST: ${{ vars.NXIS_API_HOST || secrets.NXIS_API_HOST }}
|
|
66
|
+
run: |
|
|
67
|
+
npx rollup --config rollup.config.js --environment NXIS_API_HOST:$NXIS_API_HOST
|
|
68
|
+
npm run build:types
|
|
69
|
+
|
|
70
|
+
- name: Scope package for GitHub Packages
|
|
71
|
+
run: npm pkg set name='@nxisai/nxis'
|
|
72
|
+
|
|
73
|
+
- name: Publish to GitHub Packages
|
|
74
|
+
run: npm publish
|
|
75
|
+
env:
|
|
76
|
+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
+
|
|
78
|
+
publish-npmjs:
|
|
79
|
+
needs: publish-npm
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
|
|
82
|
+
steps:
|
|
83
|
+
- name: Checkout code
|
|
84
|
+
uses: actions/checkout@v4
|
|
85
|
+
|
|
86
|
+
- name: Setup Node.js for npm
|
|
87
|
+
uses: actions/setup-node@v4
|
|
88
|
+
with:
|
|
89
|
+
node-version: '20'
|
|
90
|
+
cache: 'npm'
|
|
91
|
+
registry-url: 'https://registry.npmjs.org'
|
|
92
|
+
scope: '@nxisai'
|
|
93
|
+
|
|
94
|
+
- name: Install dependencies
|
|
95
|
+
run: npm ci
|
|
96
|
+
|
|
97
|
+
- name: Build package
|
|
98
|
+
env:
|
|
99
|
+
NXIS_API_HOST: ${{ vars.NXIS_API_HOST || secrets.NXIS_API_HOST }}
|
|
100
|
+
run: |
|
|
101
|
+
npx rollup --config rollup.config.js --environment NXIS_API_HOST:$NXIS_API_HOST
|
|
102
|
+
npm run build:types
|
|
103
|
+
|
|
104
|
+
- name: Scope package for npm
|
|
105
|
+
run: npm pkg set name='@nxisai/nxis'
|
|
106
|
+
|
|
107
|
+
- name: Publish to npm
|
|
108
|
+
run: npm publish --access public
|
|
109
|
+
env:
|
|
110
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# Nxis.js
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Nxis.js is a lightweight JavaScript client designed to integrate with the Nxis AI platform. It dynamically injects JSON-LD structured data into web pages to enhance visibility for search engines, AI agents, and large language models (LLMs). By embedding this structured data, Nxis.js helps transform standard web content into semantic data that is easily discoverable and consumable across the modern search and AI ecosystem.
|
|
5
|
+
|
|
6
|
+
Nxis.js supports **both client-side (browser)** and **server-side rendering (SSR)** environments, making it compatible with modern web frameworks.
|
|
7
|
+
|
|
8
|
+
## Supported Frameworks
|
|
9
|
+
|
|
10
|
+
| Framework | Rendering | Method |
|
|
11
|
+
|-----------|-----------|--------|
|
|
12
|
+
| **Static HTML / WordPress / Shopify** | Client-side | `<script>` tag |
|
|
13
|
+
| **Next.js** (App Router & Pages Router) | SSR / SSG | `NxisClient` |
|
|
14
|
+
| **Nuxt 3** | SSR / SSG | `NxisClient` |
|
|
15
|
+
| **Remix** | SSR | `NxisClient` |
|
|
16
|
+
| **Astro** | SSR / SSG | `NxisClient` |
|
|
17
|
+
| **SvelteKit** | SSR / SSG | `NxisClient` |
|
|
18
|
+
| **Express / Node.js** | Server | `NxisClient` |
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
Nxis.js supports two integration paths — **client-side (browser)** and **server-side rendering (SSR)**.
|
|
23
|
+
|
|
24
|
+
### Client-Side (Browser)
|
|
25
|
+
|
|
26
|
+
1. **Script Loading**: Your page loads `nxis.js` via a `<script>` tag from the Nxis CDN with a signed Nxis JWT token as a query parameter.
|
|
27
|
+
2. **Request**: On execution, the script sends a request to the Nxis AI Proxy (`/v1/nxis:inject`) with the current page URI, referrer, and session context.
|
|
28
|
+
3. **Validation & Retrieval**: The Proxy validates the JWT token, and retrieves JSON-LD structured data from the Structured Data Service.
|
|
29
|
+
4. **Injection**: On success, `nxis.js` creates a `<script type="application/ld+json">` element and appends it to the document `<head>`.
|
|
30
|
+
|
|
31
|
+
### Server-Side Rendering (SSR)
|
|
32
|
+
|
|
33
|
+
1. **Initialize**: Your application creates a `NxisClient` with OAuth client credentials. Tokens are managed automatically.
|
|
34
|
+
2. **Request**: At render time, the client calls the Nxis AI Proxy (`/v1/nxis:ssr`) with the page URI and a Bearer access token.
|
|
35
|
+
3. **Validation & Retrieval**: The Proxy validates the token, authorizes the requesting domain, and retrieves the structured data.
|
|
36
|
+
4. **Embedding**: The returned JSON-LD object is serialized directly into a `<script type="application/ld+json">` tag in the initial HTML response — visible to search engines, LLMs, and AI agents without requiring JavaScript execution.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Client-Side Installation (Browser)
|
|
41
|
+
|
|
42
|
+
Add the script tag to the head of your HTML document. Replace `${TOKEN}` with your Nxis JWT token.
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<script
|
|
46
|
+
type="text/javascript"
|
|
47
|
+
async
|
|
48
|
+
src="https://cdn.nxis.ai/nxis.js?token=${TOKEN}"
|
|
49
|
+
crossorigin="anonymous">
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The JWT token contains your organization and site configuration. No additional data attributes are needed — the CDN extracts everything from the token claims and injects it into the script automatically.
|
|
54
|
+
|
|
55
|
+
This works with any static HTML page, CMS (WordPress, Shopify, Squarespace), or client-rendered SPA.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Server-Side Rendering (SSR)
|
|
60
|
+
|
|
61
|
+
For SSR frameworks, Nxis.js provides a `NxisClient` class that fetches JSON-LD at render time so structured data is present in the initial HTML response — no client-side JavaScript required.
|
|
62
|
+
|
|
63
|
+
**Why SSR matters:** While search engines like Google can render JavaScript, large language models and LLM-based agents do not consistently execute JavaScript when crawling web pages. If structured data is only injected client-side (via the browser `<script>` tag), LLMs and AI agents may never see it. SSR ensures that JSON-LD is embedded directly in the initial HTML response, making your structured data immediately visible to every consumer — from traditional search engine crawlers to LLM training pipelines and AI agents browsing on behalf of users.
|
|
64
|
+
|
|
65
|
+
The SSR client uses **OAuth 2.0 client credentials** for authentication. Access tokens are managed automatically — cached in memory and refreshed before expiration.
|
|
66
|
+
|
|
67
|
+
### Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install @nxisai/nxis
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Environment Setup
|
|
74
|
+
|
|
75
|
+
Set these environment variables on your server:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
NXIS_API_HOST=https://api.nxis.ai
|
|
79
|
+
NXIS_CLIENT_ID=nxis_cid_... # Your OAuth client ID
|
|
80
|
+
NXIS_CLIENT_SECRET=nxis_sec_... # Your OAuth client secret
|
|
81
|
+
NXIS_SITE_ID=... # Your site identifier
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### API Reference
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
88
|
+
|
|
89
|
+
const nxis = new NxisClient({
|
|
90
|
+
clientId: string, // OAuth client ID
|
|
91
|
+
clientSecret: string, // OAuth client secret
|
|
92
|
+
tokenUrl?: string, // Optional token endpoint URL (defaults to NXIS_TOKEN_URL env var)
|
|
93
|
+
scope?: string, // Optional OAuth scope (defaults to "jsonld:read")
|
|
94
|
+
apiHost?: string, // Optional API host override (defaults to NXIS_API_HOST env var)
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const jsonLd: Record<string, unknown> = await nxis.getStructuredData({
|
|
98
|
+
uri: string, // The full URI of the page being rendered
|
|
99
|
+
siteId: string, // The site identifier
|
|
100
|
+
userAgent?: string, // Optional User-Agent for bot detection
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Returns a `Promise<Record<string, unknown>>` — a JSON-LD object ready to be serialized into a `<script type="application/ld+json">` tag.
|
|
105
|
+
|
|
106
|
+
### Token Lifecycle
|
|
107
|
+
|
|
108
|
+
Access tokens are managed automatically by `NxisClient`:
|
|
109
|
+
|
|
110
|
+
- **Lazy initialization**: No token is fetched until the first `getStructuredData` call.
|
|
111
|
+
- **In-memory cache**: Tokens are cached and reused for subsequent requests.
|
|
112
|
+
- **Auto-refresh**: Tokens are refreshed 60 seconds before expiration.
|
|
113
|
+
- **Concurrency-safe**: Multiple concurrent requests during a refresh all await the same token fetch.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### Next.js (App Router)
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
// app/page.tsx
|
|
121
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
122
|
+
import { headers } from 'next/headers';
|
|
123
|
+
|
|
124
|
+
const nxis = new NxisClient({
|
|
125
|
+
clientId: process.env.NXIS_CLIENT_ID!,
|
|
126
|
+
clientSecret: process.env.NXIS_CLIENT_SECRET!,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export default async function Page() {
|
|
130
|
+
const headersList = await headers();
|
|
131
|
+
const host = headersList.get('host') ?? 'localhost:3000';
|
|
132
|
+
const proto = headersList.get('x-forwarded-proto') ?? 'http';
|
|
133
|
+
const pageUri = `${proto}://${host}/`;
|
|
134
|
+
|
|
135
|
+
const jsonLd = await nxis.getStructuredData({
|
|
136
|
+
uri: pageUri,
|
|
137
|
+
siteId: process.env.NXIS_SITE_ID!,
|
|
138
|
+
userAgent: headersList.get('user-agent') ?? undefined,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<script
|
|
144
|
+
type="application/ld+json"
|
|
145
|
+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
|
146
|
+
/>
|
|
147
|
+
<main>{/* page content */}</main>
|
|
148
|
+
</>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Next.js (Pages Router)
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
// pages/index.tsx
|
|
157
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
158
|
+
import Head from 'next/head';
|
|
159
|
+
import { GetServerSideProps } from 'next';
|
|
160
|
+
|
|
161
|
+
const nxis = new NxisClient({
|
|
162
|
+
clientId: process.env.NXIS_CLIENT_ID!,
|
|
163
|
+
clientSecret: process.env.NXIS_CLIENT_SECRET!,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export const getServerSideProps: GetServerSideProps = async (context) => {
|
|
167
|
+
const jsonLd = await nxis.getStructuredData({
|
|
168
|
+
uri: `https://yoursite.com${context.resolvedUrl}`,
|
|
169
|
+
siteId: process.env.NXIS_SITE_ID!,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return { props: { jsonLd } };
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export default function Page({ jsonLd }: { jsonLd: Record<string, unknown> }) {
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
<Head>
|
|
179
|
+
<script
|
|
180
|
+
type="application/ld+json"
|
|
181
|
+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
|
182
|
+
/>
|
|
183
|
+
</Head>
|
|
184
|
+
<main>{/* page content */}</main>
|
|
185
|
+
</>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Nuxt 3
|
|
191
|
+
|
|
192
|
+
```html
|
|
193
|
+
<!-- pages/index.vue -->
|
|
194
|
+
<script setup lang="ts">
|
|
195
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
196
|
+
|
|
197
|
+
const config = useRuntimeConfig();
|
|
198
|
+
const nxis = new NxisClient({
|
|
199
|
+
clientId: config.nxisClientId,
|
|
200
|
+
clientSecret: config.nxisClientSecret,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const { data: jsonLd } = await useAsyncData('nxis-jsonld', () =>
|
|
204
|
+
nxis.getStructuredData({
|
|
205
|
+
uri: `https://yoursite.com${useRoute().fullPath}`,
|
|
206
|
+
siteId: config.nxisSiteId,
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
useHead({
|
|
211
|
+
script: [
|
|
212
|
+
{
|
|
213
|
+
type: 'application/ld+json',
|
|
214
|
+
innerHTML: JSON.stringify(jsonLd.value),
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
});
|
|
218
|
+
</script>
|
|
219
|
+
|
|
220
|
+
<template>
|
|
221
|
+
<main><!-- page content --></main>
|
|
222
|
+
</template>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Remix
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
// app/routes/_index.tsx
|
|
229
|
+
import { json, type LoaderFunctionArgs } from '@remix-run/node';
|
|
230
|
+
import { useLoaderData } from '@remix-run/react';
|
|
231
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
232
|
+
|
|
233
|
+
const nxis = new NxisClient({
|
|
234
|
+
clientId: process.env.NXIS_CLIENT_ID!,
|
|
235
|
+
clientSecret: process.env.NXIS_CLIENT_SECRET!,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
export async function loader({ request }: LoaderFunctionArgs) {
|
|
239
|
+
const jsonLd = await nxis.getStructuredData({
|
|
240
|
+
uri: request.url,
|
|
241
|
+
siteId: process.env.NXIS_SITE_ID!,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
return json({ jsonLd });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export default function Index() {
|
|
248
|
+
const { jsonLd } = useLoaderData<typeof loader>();
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<>
|
|
252
|
+
<script
|
|
253
|
+
type="application/ld+json"
|
|
254
|
+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
|
255
|
+
/>
|
|
256
|
+
<main>{/* page content */}</main>
|
|
257
|
+
</>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Astro
|
|
263
|
+
|
|
264
|
+
```astro
|
|
265
|
+
---
|
|
266
|
+
// src/pages/index.astro
|
|
267
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
268
|
+
|
|
269
|
+
const nxis = new NxisClient({
|
|
270
|
+
clientId: import.meta.env.NXIS_CLIENT_ID,
|
|
271
|
+
clientSecret: import.meta.env.NXIS_CLIENT_SECRET,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const jsonLd = await nxis.getStructuredData({
|
|
275
|
+
uri: Astro.url.href,
|
|
276
|
+
siteId: import.meta.env.NXIS_SITE_ID,
|
|
277
|
+
});
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
<html>
|
|
281
|
+
<head>
|
|
282
|
+
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
|
|
283
|
+
</head>
|
|
284
|
+
<body>
|
|
285
|
+
<!-- page content -->
|
|
286
|
+
</body>
|
|
287
|
+
</html>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### SvelteKit
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// src/routes/+page.server.ts
|
|
294
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
295
|
+
import { env } from '$env/static/private';
|
|
296
|
+
import type { PageServerLoad } from './$types';
|
|
297
|
+
|
|
298
|
+
const nxis = new NxisClient({
|
|
299
|
+
clientId: env.NXIS_CLIENT_ID,
|
|
300
|
+
clientSecret: env.NXIS_CLIENT_SECRET,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
export const load: PageServerLoad = async ({ url }) => {
|
|
304
|
+
const jsonLd = await nxis.getStructuredData({
|
|
305
|
+
uri: url.href,
|
|
306
|
+
siteId: env.NXIS_SITE_ID,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
return { jsonLd };
|
|
310
|
+
};
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```html
|
|
314
|
+
<!-- src/routes/+page.svelte -->
|
|
315
|
+
<script lang="ts">
|
|
316
|
+
export let data;
|
|
317
|
+
</script>
|
|
318
|
+
|
|
319
|
+
<svelte:head>
|
|
320
|
+
{@html `<script type="application/ld+json">${JSON.stringify(data.jsonLd)}</script>`}
|
|
321
|
+
</svelte:head>
|
|
322
|
+
|
|
323
|
+
<main><!-- page content --></main>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Express / Node.js
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
const express = require('express');
|
|
330
|
+
const { NxisClient } = require('@nxisai/nxis');
|
|
331
|
+
|
|
332
|
+
const nxis = new NxisClient({
|
|
333
|
+
clientId: process.env.NXIS_CLIENT_ID,
|
|
334
|
+
clientSecret: process.env.NXIS_CLIENT_SECRET,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const app = express();
|
|
338
|
+
|
|
339
|
+
app.get('*', async (req, res) => {
|
|
340
|
+
const jsonLd = await nxis.getStructuredData({
|
|
341
|
+
uri: `https://yoursite.com${req.originalUrl}`,
|
|
342
|
+
siteId: process.env.NXIS_SITE_ID,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
res.send(`
|
|
346
|
+
<!DOCTYPE html>
|
|
347
|
+
<html>
|
|
348
|
+
<head>
|
|
349
|
+
<script type="application/ld+json">${JSON.stringify(jsonLd)}</script>
|
|
350
|
+
</head>
|
|
351
|
+
<body><!-- page content --></body>
|
|
352
|
+
</html>
|
|
353
|
+
`);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
app.listen(3000);
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Adding Nxis SSR with Claude Code
|
|
362
|
+
|
|
363
|
+
You can use [Claude Code](https://docs.anthropic.com/en/docs/claude-code) to automatically add Nxis SSR to an existing Next.js project. Paste the following prompt into Claude Code from your project's root directory:
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
Install the @nxisai/nxis package and add server-side structured data injection to my
|
|
367
|
+
Next.js App Router project. Here's what I need:
|
|
368
|
+
|
|
369
|
+
1. Install the @nxisai/nxis npm package
|
|
370
|
+
2. Add NXIS_API_HOST, NXIS_CLIENT_ID, and NXIS_CLIENT_SECRET to my .env.local
|
|
371
|
+
3. Create a shared NxisClient instance using `NxisClient` from `@nxisai/nxis/ssr`
|
|
372
|
+
initialized with the OAuth client credentials from environment variables
|
|
373
|
+
4. Update my root layout (or individual pages) to:
|
|
374
|
+
- Import `headers` from `next/headers`
|
|
375
|
+
- Derive the page URI from the incoming request's `host` and
|
|
376
|
+
`x-forwarded-proto` headers
|
|
377
|
+
- Pass the `user-agent` header for bot detection
|
|
378
|
+
- Inject the returned JSON-LD as a <script type="application/ld+json"> tag
|
|
379
|
+
|
|
380
|
+
Here's the API reference:
|
|
381
|
+
|
|
382
|
+
import { NxisClient } from '@nxisai/nxis/ssr';
|
|
383
|
+
|
|
384
|
+
const nxis = new NxisClient({
|
|
385
|
+
clientId: process.env.NXIS_CLIENT_ID!,
|
|
386
|
+
clientSecret: process.env.NXIS_CLIENT_SECRET!,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
const jsonLd: Record<string, unknown> = await nxis.getStructuredData({
|
|
390
|
+
uri: pageUri,
|
|
391
|
+
siteId: process.env.NXIS_SITE_ID!,
|
|
392
|
+
userAgent: headersList.get('user-agent') ?? undefined,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
Tokens are managed automatically — no manual token handling needed.
|
|
396
|
+
Make sure JSON-LD is present in the initial HTML response so it's visible
|
|
397
|
+
to search engines, LLMs, and AI agents that don't render JavaScript.
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
This will guide Claude Code to install the package, configure environment variables, and wire up SSR structured data injection across your pages.
|
|
401
|
+
|
package/bin/deploy.sh
ADDED