@druxt-contrib/node-preview 0.1.0-dev.20261030024907 → 0.1.0-dev.20261109195239
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/CHANGELOG.md +7 -1
- package/README.md +101 -226
- package/dist/index.esm.js +281 -6
- package/dist/index.ssr.js +281 -6
- package/package.json +4 -2
- package/templates/plugin.js +177 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.0-dev.
|
|
3
|
+
## 0.1.0-dev.20261109195239
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
7
|
- 6b39690: Add the DruxtNodePreview module. It renders an unsaved Drupal node in a Druxt site, in Consumer Node Preview's Frontend tab, from the JSON:API Node Preview document.
|
|
8
|
+
- 0ac6a76: Read a preview with Consumer Node Preview's `[preview_token]` from the URL fragment, so a frontend on another domain or a tunnel previews without the editor's session. The new `register.token` option registers that form of the target URL, and `register.backend` registers on a Drupal site other than `druxt.baseUrl`, with its own secret.
|
|
9
|
+
- 2c2f5a4: Add automatic registration. With the new `register` option, the frontend adds its own preview target to its Drupal consumer when Nuxt starts, over Consumer Node Preview's targets API with a Simple OAuth client credentials token. The requests go through a `DruxtClient`, so the site's `druxt.axios` options apply, and they never follow a redirect. The target sends the preview's address as a path, `[jsonapi_node_preview_path]`, so it works for an editor on Drupal's host or on the frontend's. It sends a PATCH, so the consumer's other targets stay and Drupal records the time, and it sends it again every 6 hours while Nuxt runs, so a running frontend's target stays active. The secret comes only from the `DRUXT_NODE_PREVIEW_CLIENT_SECRET` environment variable.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- adeeb35: The `origins` option now ignores an origin whose host has characters other than letters, digits, dots, hyphens and `_`, unless it is an IPv6 address in brackets. The page fetches from a listed origin without the Druxt client, whose headers and auth are for `druxt.baseUrl`, unless that origin is the page's own or `druxt.baseUrl`'s. A preview read with a token takes the token out of the page's address as soon as it starts. Where the browser allows session storage, the tab keeps the token there for a reload, until it expires.
|
package/README.md
CHANGED
|
@@ -8,10 +8,7 @@
|
|
|
8
8
|
# @druxt-contrib/node-preview
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/@druxt-contrib/node-preview)
|
|
11
|
-
[](https://www.npmjs.com/package/@druxt-contrib/node-preview/v/dev)
|
|
12
11
|
[](https://github.com/druxt-contrib/druxt-node-preview/actions/workflows/ci.yml)
|
|
13
|
-
[](https://codecov.io/gh/druxt-contrib/druxt-node-preview)
|
|
14
|
-
[](https://snyk.io/test/github/druxt-contrib/druxt-node-preview?targetFile=package.json)
|
|
15
12
|
[](https://discord.druxtjs.org)
|
|
16
13
|
|
|
17
14
|
> Node Preview module for Druxt
|
|
@@ -22,40 +19,54 @@ show it, paragraphs included.
|
|
|
22
19
|
|
|
23
20
|

|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
## Contents
|
|
26
23
|
|
|
27
|
-
- [
|
|
28
|
-
|
|
29
|
-
- [
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
- [Features](#features)
|
|
25
|
+
- [How it works](#how-it-works)
|
|
26
|
+
- [Requirements](#requirements)
|
|
27
|
+
- [Quick start](#quick-start)
|
|
28
|
+
- [Options](#options)
|
|
29
|
+
- [Troubleshooting](#troubleshooting)
|
|
30
|
+
- [More documentation](#more-documentation)
|
|
32
31
|
|
|
33
|
-
##
|
|
32
|
+
## Features
|
|
34
33
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
34
|
+
- Renders the unsaved node with the site's own Druxt components.
|
|
35
|
+
- Includes unsaved paragraphs, and the media they reference.
|
|
36
|
+
- Lets the editor pick a Nuxt layout, such as a bare one for embedded content.
|
|
37
|
+
- Wraps the preview in a component of your own, for a title or a container.
|
|
38
|
+
- Reads the preview with a Simple OAuth token on a frontend on another domain.
|
|
39
|
+
- Can add its own preview target to Drupal each time Nuxt starts up.
|
|
37
40
|
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
The frontend needs:
|
|
41
|
+
## How it works
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
1. The editor presses Preview in Drupal. The Frontend tab of
|
|
44
|
+
[Consumer Node Preview](https://www.drupal.org/project/consumer_node_preview)
|
|
45
|
+
opens this module's page in a frame.
|
|
46
|
+
2. The page reads the preview's JSON:API address from the part of its URL
|
|
47
|
+
after the `#`. Browsers do not send that part to the frontend's server.
|
|
48
|
+
3. The page fetches the preview, from
|
|
49
|
+
[JSON:API Node Preview](https://www.drupal.org/project/jsonapi_node_preview),
|
|
50
|
+
with the editor's Drupal session, or with a token from the URL for a
|
|
51
|
+
frontend on another domain. It puts the document in the Druxt store.
|
|
52
|
+
4. `DruxtEntity` renders the node from the store. The unsaved content goes
|
|
53
|
+
through the same components as the live site.
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
## Requirements
|
|
46
56
|
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
- Nuxt 2, with Druxt 0.25 and Druxt Entity 0.29 or later, through `druxt-site`
|
|
58
|
+
0.15.
|
|
59
|
+
- Node 16 for the build. Druxt's schema build fails on newer Node.
|
|
60
|
+
- Drupal 10.3 or 11, with Consumer Node Preview and JSON:API Node Preview. See
|
|
61
|
+
[Consumer Node Preview's requirements](https://git.drupalcode.org/project/consumer_node_preview/-/blob/1.0.x/README.md#requirements)
|
|
62
|
+
for the JSON:API Node Preview fixes it needs.
|
|
63
|
+
- The frontend and Drupal on one parent domain, such as `www.example.com` and
|
|
64
|
+
`cms.example.com`. Otherwise, see [Previews with a
|
|
65
|
+
token](docs/preview-request.md#previews-with-a-token).
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
`cms.example.com` for Drupal. The editor's Drupal session cookie does not
|
|
56
|
-
reach a frontend on another domain.
|
|
67
|
+
## Quick start
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
On the frontend:
|
|
59
70
|
|
|
60
71
|
```sh
|
|
61
72
|
npm install druxt-site @druxt-contrib/node-preview
|
|
@@ -67,245 +78,109 @@ export default {
|
|
|
67
78
|
modules: ['@druxt-contrib/node-preview', 'druxt-site'],
|
|
68
79
|
druxt: {
|
|
69
80
|
baseUrl: 'https://cms.example.com',
|
|
70
|
-
nodePreview: {
|
|
71
|
-
include: { 'node--page': ['field_content.field_media'] },
|
|
72
|
-
origins: ['https://cms.example.com'],
|
|
73
|
-
layouts: ['default', 'preview'],
|
|
74
|
-
},
|
|
75
81
|
},
|
|
76
82
|
}
|
|
77
83
|
```
|
|
78
84
|
|
|
79
85
|
A site without `druxt-site` lists `druxt-entity` in `modules` instead.
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
All options are optional.
|
|
84
|
-
|
|
85
|
-
| Option | Type | Default | Description |
|
|
86
|
-
| --------------------------- | ------------------- | ----------------------- | -------------------------------------------------------------------------- |
|
|
87
|
-
| `druxt.nodePreview.path` | `string` | `'/druxt/node/preview'` | The preview page's path. |
|
|
88
|
-
| `druxt.nodePreview.include` | `array` or `object` | `[]` | Relationships to add to the preview request. |
|
|
89
|
-
| `druxt.nodePreview.origins` | `array` | `[]` | More origins the preview may come from. Each is a full URL. |
|
|
90
|
-
| `druxt.nodePreview.layouts` | `array` | `[]` | Nuxt layouts the preview may use. See [Preview layouts](#preview-layouts). |
|
|
91
|
-
|
|
92
|
-
**include.** Consumer Node Preview already includes a node's paragraphs. Add
|
|
93
|
-
what the paragraphs reference, such as `field_content.field_media`. JSON:API
|
|
94
|
-
refuses a path that the previewed type does not have. Key a path by type when
|
|
95
|
-
only some bundles have it, as in the example above.
|
|
96
|
-
|
|
97
|
-
**origins.** Any link can put an endpoint in the page's URL. So the page only
|
|
98
|
-
fetches from this site, from `druxt.baseUrl`, and from `origins`. The editor's
|
|
99
|
-
session cookie goes with each request to those origins.
|
|
87
|
+
On Drupal:
|
|
100
88
|
|
|
101
|
-
|
|
102
|
-
module ignores it. The page's route name is `druxt-node-preview`.
|
|
89
|
+
1. Install the modules:
|
|
103
90
|
|
|
104
|
-
|
|
91
|
+
```sh
|
|
92
|
+
composer require drupal/jsonapi_node_preview:^1.0@beta drupal/consumer_node_preview
|
|
93
|
+
drush en consumer_node_preview
|
|
94
|
+
```
|
|
105
95
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
edit the frontend's consumer. Under **Preview targets**, add a label and
|
|
110
|
-
this URL template, with your frontend's host:
|
|
96
|
+
2. Go to **Administration > Configuration > Web services > Consumers**, and
|
|
97
|
+
add or edit the frontend's consumer. Under **Preview targets**, add a label
|
|
98
|
+
and this URL, with your frontend's host:
|
|
111
99
|
|
|
112
100
|
```text
|
|
113
|
-
https://www.example.com/druxt/node/preview?vm=[view_mode]
|
|
101
|
+
https://www.example.com/druxt/node/preview?vm=[view_mode]#[jsonapi_node_preview_path]
|
|
114
102
|
```
|
|
115
103
|
|
|
116
104
|
Drupal fills in the parts in square brackets when the editor presses
|
|
117
|
-
Preview. Keep them as they are.
|
|
118
|
-
|
|
119
|
-
3. Optional: under **Preview layouts**, add one layout name in each box. Put
|
|
120
|
-
`default` first, because the preview opens in the first one. See
|
|
121
|
-
[Preview layouts](#preview-layouts).
|
|
122
|
-
4. In the site's `services.yml`, such as `sites/default/services.yml`, allow
|
|
123
|
-
the frontend's origin with credentials. Name the origin. Do not use `'*'`.
|
|
124
|
-
|
|
125
|
-
```yaml
|
|
126
|
-
parameters:
|
|
127
|
-
cors.config:
|
|
128
|
-
enabled: true
|
|
129
|
-
allowedHeaders: ['*']
|
|
130
|
-
allowedMethods: ['GET']
|
|
131
|
-
allowedOrigins: ['https://www.example.com']
|
|
132
|
-
supportsCredentials: true
|
|
133
|
-
```
|
|
105
|
+
Preview. Keep them as they are. The frontend can also add this target
|
|
106
|
+
itself. See [Automatic registration](docs/registration.md).
|
|
134
107
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
108
|
+
3. Allow the frontend's origin, with credentials, in the CORS settings in
|
|
109
|
+
`services.yml`. [Consumer Node Preview's
|
|
110
|
+
configuration](https://git.drupalcode.org/project/consumer_node_preview/-/blob/1.0.x/README.md#configuration)
|
|
111
|
+
has the YAML.
|
|
112
|
+
4. Let Drupal show the preview page in a frame. On the preview page's route
|
|
113
|
+
only, remove any `X-Frame-Options` header, and add Drupal's origin to its
|
|
114
|
+
`frame-ancestors` rule. Keep the frontend's other pages as they are.
|
|
141
115
|
|
|
142
116
|
To check it, edit a node, change something and press Preview. The Frontend
|
|
143
117
|
tab shows the change.
|
|
144
118
|
|
|
145
|
-
|
|
146
|
-
README](https://www.drupal.org/project/consumer_node_preview) lists the other
|
|
147
|
-
URL tokens, and how to set targets in `settings.php`.
|
|
148
|
-
|
|
149
|
-
## How it works
|
|
150
|
-
|
|
151
|
-
1. The editor presses Preview in Drupal. The Frontend tab opens this module's
|
|
152
|
-
page in a frame.
|
|
153
|
-
2. The page reads the preview's JSON:API address from the part of its URL
|
|
154
|
-
after the `#`. Browsers do not send that part to the frontend's server.
|
|
155
|
-
3. The page fetches the preview with the editor's Drupal session. It puts the
|
|
156
|
-
document in the Druxt store.
|
|
157
|
-
4. `DruxtEntity` renders the node from the store, inside a `DruxtNodePreview`
|
|
158
|
-
wrapper. The unsaved content goes through the same components as the live
|
|
159
|
-
site.
|
|
160
|
-
|
|
161
|
-
## Preview layouts
|
|
162
|
-
|
|
163
|
-
The page uses the layout that `?layout=` names, but only if `layouts` lists
|
|
164
|
-
it. If not, the page uses the default layout. A preview URL cannot pick any
|
|
165
|
-
other layout.
|
|
166
|
-
|
|
167
|
-
Each listed layout must be a file in the site's `layouts/` folder that renders
|
|
168
|
-
`<Nuxt />`. A bare layout suits content that sits inside other pages. It has
|
|
169
|
-
the site's type and spacing, but no header or footer.
|
|
170
|
-
|
|
171
|
-
A site that picks layouts somewhere else can call
|
|
172
|
-
`$druxtNodePreview.layout(name)`. It makes the same check.
|
|
173
|
-
|
|
174
|
-
## Theming the preview
|
|
175
|
-
|
|
176
|
-
A live page often adds a title or a container around the node. The preview
|
|
177
|
-
gets the same from a wrapper component, picked like any Druxt wrapper. For a
|
|
178
|
-
`node--doc_page` previewed in `full`, the page uses the first of these that
|
|
179
|
-
exists:
|
|
180
|
-
|
|
181
|
-
1. `DruxtNodePreviewDocPageFull`
|
|
182
|
-
2. `DruxtNodePreviewDocPage`
|
|
183
|
-
3. `DruxtNodePreviewDefault`
|
|
184
|
-
|
|
185
|
-
If none of them exists, the node renders in Druxt's plain wrapper.
|
|
186
|
-
|
|
187
|
-
A wrapper gets any of these props that it declares:
|
|
188
|
-
|
|
189
|
-
- `document`: the whole JSON:API preview document.
|
|
190
|
-
- `entity`: the previewed resource, with `attributes` such as the title.
|
|
191
|
-
- `mode`, `type` and `uuid`.
|
|
192
|
-
|
|
193
|
-
Its default slot renders the node with `DruxtEntity`:
|
|
194
|
-
|
|
195
|
-
```vue
|
|
196
|
-
<!-- components/druxt/node-preview/DocPageFull.vue -->
|
|
197
|
-
<template>
|
|
198
|
-
<article class="prose">
|
|
199
|
-
<h1>{{ entity.attributes.title }}</h1>
|
|
200
|
-
<slot />
|
|
201
|
-
</article>
|
|
202
|
-
</template>
|
|
203
|
-
|
|
204
|
-
<script>
|
|
205
|
-
export default {
|
|
206
|
-
// The props it does not declare would otherwise land on <article>.
|
|
207
|
-
inheritAttrs: false,
|
|
208
|
-
props: {
|
|
209
|
-
entity: { type: Object, required: true },
|
|
210
|
-
},
|
|
211
|
-
}
|
|
212
|
-
</script>
|
|
213
|
-
```
|
|
119
|
+
## Options
|
|
214
120
|
|
|
215
|
-
|
|
216
|
-
every view mode. Put page parts such as a title in the `<Bundle>Full` wrapper,
|
|
217
|
-
as above, or check the `mode` prop.
|
|
121
|
+
All options are optional, and go under `druxt.nodePreview`.
|
|
218
122
|
|
|
219
|
-
|
|
123
|
+
| Option | Default | Description |
|
|
124
|
+
| ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
125
|
+
| `path` | `'/druxt/node/preview'` | The preview page's path. |
|
|
126
|
+
| `include` | `[]` | Relationships to add to the preview request. Key them by type when only some bundles have them. |
|
|
127
|
+
| `origins` | `[]` | More origins the preview may come from, as full URLs. |
|
|
128
|
+
| `layouts` | `[]` | Nuxt layouts the preview may use. See [Layouts and theming](docs/layouts-and-theming.md). |
|
|
129
|
+
| `register` | `false` | Adds the frontend's preview target to Drupal on start up. See [Automatic registration](docs/registration.md). |
|
|
220
130
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
131
|
+
**include.** Consumer Node Preview already includes a node's paragraphs. Add
|
|
132
|
+
what the paragraphs reference, such as `field_content.field_media`. JSON:API
|
|
133
|
+
refuses a path that the previewed type does not have, so key it by type when
|
|
134
|
+
only some bundles have it:
|
|
224
135
|
|
|
225
136
|
```js
|
|
226
|
-
|
|
137
|
+
include: { 'node--page': ['field_content.field_media'] }
|
|
227
138
|
```
|
|
228
139
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
The page fetches through the Druxt client, `$druxt.axios`, with credentials.
|
|
238
|
-
The site's request interceptors apply, such as one that adds a workspace
|
|
239
|
-
header. Without the Druxt client, the page uses `window.fetch`.
|
|
240
|
-
|
|
241
|
-
A preview address that is a path stays a path. The Druxt client resolves it
|
|
242
|
-
against its own base URL, and interceptors that match by path still match it.
|
|
243
|
-
This suits a frontend that reaches Drupal through a proxy on its own origin.
|
|
244
|
-
The editor must then sign in through that proxy too, because the session
|
|
245
|
-
cookie belongs to the host the editor signed in on. Druxt's
|
|
246
|
-
`proxy: { api: true }` forwards the API but not Drupal's sign-in pages, so it
|
|
247
|
-
is not enough on its own.
|
|
248
|
-
|
|
249
|
-
Without a proxy, the request goes to Drupal's origin. Drupal then needs the
|
|
250
|
-
CORS settings from [Drupal setup](#drupal-setup). The session cookie is
|
|
251
|
-
`SameSite=Lax`, so the frontend and Drupal need one parent domain.
|
|
140
|
+
**origins.** Any link can put an address in the page's URL. So the page only
|
|
141
|
+
fetches from this site, from `druxt.baseUrl`, and from `origins`. A request to
|
|
142
|
+
an origin in `origins` goes without the Druxt client, whose headers and auth
|
|
143
|
+
are for `druxt.baseUrl`, unless that origin is the frontend's own or
|
|
144
|
+
`druxt.baseUrl`'s. An origin whose host has characters other than
|
|
145
|
+
letters, digits, dots, hyphens and `_` is ignored, unless it is an IPv6 address
|
|
146
|
+
in brackets, such as `http://[::1]:3000`.
|
|
252
147
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
resource in it must have a JSON:API type and a UUID. If a check fails, the
|
|
256
|
-
page shows an error and puts nothing in the store.
|
|
257
|
-
|
|
258
|
-
## Server rendering and static sites
|
|
259
|
-
|
|
260
|
-
The page only works in the browser. A server render shows "Loading
|
|
261
|
-
preview..." and the browser fills it in. A statically generated page has the
|
|
262
|
-
default layout, so the page switches to the listed layout in the browser.
|
|
148
|
+
A value the module cannot use shows a warning in the build output, and the
|
|
149
|
+
module ignores it.
|
|
263
150
|
|
|
264
151
|
## Troubleshooting
|
|
265
152
|
|
|
266
153
|
The page shows "Preview unavailable" and a message.
|
|
267
154
|
|
|
268
|
-
- **HTTP 404.** Drupal has no preview of this node for the editor. Check
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
use one host name for both: `localhost` and `127.0.0.1` count as
|
|
273
|
-
different.
|
|
274
|
-
3. The CORS settings in `services.yml` name the frontend's origin.
|
|
155
|
+
- **HTTP 404.** Drupal has no preview of this node for the editor. Check that
|
|
156
|
+
the editor pressed Preview, and that the frontend and Drupal share a parent
|
|
157
|
+
domain. On your own computer, use one host name for both: `localhost` and
|
|
158
|
+
`127.0.0.1` count as different. Then check the CORS settings.
|
|
275
159
|
- **"The preview endpoint is not on this site or its Drupal site".** Add the
|
|
276
160
|
preview's origin to the `origins` option.
|
|
277
|
-
- **"The URL fragment has no preview endpoint".**
|
|
278
|
-
|
|
161
|
+
- **"The URL fragment has no preview endpoint".** Make the target URL end in
|
|
162
|
+
`#[jsonapi_node_preview_path]` or `#[jsonapi_node_preview]`.
|
|
279
163
|
- **HTTP 400.** An `include` path that the previewed type does not have. Key
|
|
280
164
|
that path by type.
|
|
281
165
|
|
|
282
|
-
If
|
|
283
|
-
|
|
284
|
-
1. Check that the content type has a display for the previewed view mode, on
|
|
285
|
-
its **Manage display** tab.
|
|
286
|
-
2. Make sure Drupal is up, then restart the frontend. Nuxt builds the schema
|
|
287
|
-
when it starts, and `.nuxt` can hold an old one.
|
|
288
|
-
|
|
289
|
-
The [end to end troubleshooting
|
|
290
|
-
notes](https://github.com/druxt-contrib/druxt-node-preview/blob/0.x/test/e2e/TROUBLESHOOTING.md)
|
|
291
|
-
cover the test stack.
|
|
292
|
-
|
|
293
|
-
## Writing another frontend
|
|
166
|
+
If the Frontend tab stays blank, check the frame headers from step 4 of the
|
|
167
|
+
[Quick start](#quick-start), because the frontend refused the frame.
|
|
294
168
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
frontend reads the preview address from the URL, including the `https:/`
|
|
298
|
-
repair that some routers need. Before it renders anything, a frontend makes
|
|
299
|
-
the same checks as this module. See [The preview request](#the-preview-request).
|
|
169
|
+
For automatic registration and schema errors, see
|
|
170
|
+
[Troubleshooting](docs/troubleshooting.md).
|
|
300
171
|
|
|
301
|
-
|
|
302
|
-
query parameters. They change only how the preview looks. The JSON:API
|
|
303
|
-
document is the same for each.
|
|
172
|
+
## More documentation
|
|
304
173
|
|
|
305
|
-
|
|
174
|
+
- [Automatic registration](docs/registration.md), and its [Drupal
|
|
175
|
+
setup](docs/registration-drupal-setup.md)
|
|
176
|
+
- [Layouts and theming](docs/layouts-and-theming.md)
|
|
177
|
+
- [The preview request](docs/preview-request.md), including previews with a
|
|
178
|
+
token
|
|
179
|
+
- [Troubleshooting](docs/troubleshooting.md)
|
|
180
|
+
- [Writing another frontend](docs/other-frontends.md)
|
|
306
181
|
|
|
307
|
-
|
|
308
|
-
|
|
182
|
+
The [example](https://github.com/druxt-contrib/druxt-node-preview/tree/0.x/example)
|
|
183
|
+
pairs a Drupal site and a Nuxt site.
|
|
309
184
|
|
|
310
185
|
## Licence
|
|
311
186
|
|