create-nextly-app 0.0.2-alpha.74 → 0.0.2-alpha.75

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/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_nextly = require("./create-nextly-Decg8dye.cjs");
2
+ const require_create_nextly = require("./create-nextly-DdIL2e9E.cjs");
3
3
  exports.createNextly = require_create_nextly.createNextly;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export { t as createNextly } from "./create-nextly-ChHdzG83.mjs";
1
+ export { t as createNextly } from "./create-nextly-N_COehCu.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nextly-app",
3
- "version": "0.0.2-alpha.74",
3
+ "version": "0.0.2-alpha.75",
4
4
  "description": "CLI to scaffold Nextly in your Next.js project",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,10 +37,10 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@babel/types": "^7.29.7",
40
- "@nextlyhq/eslint-plugin": "0.0.2-alpha.74",
41
- "@nextlyhq/module-specifiers": "0.0.2-alpha.74",
42
- "@nextlyhq/telemetry": "0.0.2-alpha.74",
43
- "@nextlyhq/tsconfig": "0.0.2-alpha.74",
40
+ "@nextlyhq/eslint-plugin": "0.0.2-alpha.75",
41
+ "@nextlyhq/module-specifiers": "0.0.2-alpha.75",
42
+ "@nextlyhq/telemetry": "0.0.2-alpha.75",
43
+ "@nextlyhq/tsconfig": "0.0.2-alpha.75",
44
44
  "@testing-library/react": "^16.3.0",
45
45
  "@types/fs-extra": "^11.0.4",
46
46
  "@types/node": "^22.20.5",
@@ -7,7 +7,7 @@ description: >-
7
7
  code, and extra fields on users. Also use when asked to add login or
8
8
  sign-up to a Nextly site, so the answer matches what Nextly provides.
9
9
  metadata:
10
- nextly-version: 0.0.2-alpha.74
10
+ nextly-version: 0.0.2-alpha.75
11
11
  ---
12
12
 
13
13
  # Authentication and access in Nextly
@@ -9,7 +9,7 @@ description: >-
9
9
  not appear in the admin, a field change does not reach the database, or a
10
10
  page reading content fails to build.
11
11
  metadata:
12
- nextly-version: 0.0.2-alpha.74
12
+ nextly-version: 0.0.2-alpha.75
13
13
  ---
14
14
 
15
15
  # Define a collection in Nextly
@@ -8,7 +8,7 @@ description: >-
8
8
  Also use when a deployed Nextly app has missing tables, refuses to start,
9
9
  or loses uploaded files.
10
10
  metadata:
11
- nextly-version: 0.0.2-alpha.74
11
+ nextly-version: 0.0.2-alpha.75
12
12
  ---
13
13
 
14
14
  # Deploy a Nextly project
@@ -8,7 +8,7 @@ description: >-
8
8
  Nextly install shows no collections, fails to load nextly.config.ts, or its
9
9
  admin panel misbehaves after setup.
10
10
  metadata:
11
- nextly-version: 0.0.2-alpha.74
11
+ nextly-version: 0.0.2-alpha.75
12
12
  ---
13
13
 
14
14
  # Install Nextly into an existing Next.js app
@@ -1,13 +1,43 @@
1
1
  import { connection } from "next/server";
2
2
  import { Suspense } from "react";
3
- import { getBrandingCss } from "nextly/config";
4
- import { checkAdminComponents } from "nextly/runtime";
3
+ import {
4
+ ADMIN_BRANDING_ELEMENT_ID,
5
+ adminBrandingJson,
6
+ adminMetadataFor,
7
+ getBrandingCss,
8
+ } from "nextly/config";
5
9
 
6
10
  import config from "../../../../nextly.config";
7
11
  import { registeredComponentPaths } from "../../../types/generated/plugin-admin-components.generated";
8
12
 
9
13
  const brandingCss = getBrandingCss(config.admin?.branding);
14
+ // The configured logo, name and favicon, read by the admin before any request
15
+ // answers, so they are right from the first paint.
16
+ const brandingJson = adminBrandingJson(config.admin?.branding);
10
17
 
18
+ /**
19
+ * The admin is never a page for search results: `noindex, nofollow` in the
20
+ * head of the first HTML the server sends, whatever plugins the site runs,
21
+ * and the configured favicon's link beside it.
22
+ */
23
+ export const metadata = adminMetadataFor(config.admin?.branding);
24
+
25
+ /**
26
+ * `/admin` itself is built ahead, so it is served from the build's files. The
27
+ * admin's other paths are drawn by the same page in the browser, and are
28
+ * served the same prebuilt shell.
29
+ */
30
+ export function generateStaticParams(): { params: string[] }[] {
31
+ return [{ params: [] }];
32
+ }
33
+
34
+ /**
35
+ * Prebuilt in production: the same page for every visitor, built once, with
36
+ * no request-time work and nothing read from the database. Everything about
37
+ * the person comes from the admin's own requests once it loads, so a CDN or
38
+ * the browser may keep the page, and it is served while the server is still
39
+ * starting.
40
+ */
11
41
  export default function AdminLayout({
12
42
  children,
13
43
  }: {
@@ -18,25 +48,39 @@ export default function AdminLayout({
18
48
  {brandingCss && (
19
49
  <style dangerouslySetInnerHTML={{ __html: brandingCss }} />
20
50
  )}
21
- <Suspense fallback={null}>
22
- <ForThisRequest>{children}</ForThisRequest>
23
- </Suspense>
51
+ {brandingJson && (
52
+ <script
53
+ type="application/json"
54
+ id={ADMIN_BRANDING_ELEMENT_ID}
55
+ dangerouslySetInnerHTML={{ __html: brandingJson }}
56
+ />
57
+ )}
58
+ {process.env.NODE_ENV === "development" ? (
59
+ <Suspense fallback={null}>
60
+ <ComponentMapKeptCurrent>{children}</ComponentMapKeptCurrent>
61
+ </Suspense>
62
+ ) : (
63
+ children
64
+ )}
24
65
  </>
25
66
  );
26
67
  }
27
68
 
28
69
  /**
29
- * The admin renders for each request, never from a cache another user's
30
- * request filled. Beneath the layout's Suspense boundary, so under Cache
31
- * Components the shell above it still prerenders: request work outside a
32
- * boundary fails the build, in development too, where `checkAdminComponents`
33
- * boots nextly.
70
+ * Development only: before any admin page, the generated component map is
71
+ * written again when it falls behind the config. A production build serves
72
+ * the map it was built with, so it drops this, and the page with it is
73
+ * prebuilt. Beneath a Suspense boundary, as request work outside one fails a
74
+ * Cache Components build, in development too. The check is loaded here, so a
75
+ * production page never loads the runtime it lives in.
34
76
  */
35
- async function ForThisRequest({ children }: { children: React.ReactNode }) {
77
+ async function ComponentMapKeptCurrent({
78
+ children,
79
+ }: {
80
+ children: React.ReactNode;
81
+ }) {
36
82
  await connection();
37
- // In development, the generated component map is written again when it
38
- // falls behind the config, so a plugin added while `next dev` runs draws
39
- // its components without a command. In production it does nothing.
83
+ const { checkAdminComponents } = await import("nextly/runtime");
40
84
  await checkAdminComponents({ config, registeredComponentPaths });
41
85
  return children;
42
86
  }
@@ -3,6 +3,7 @@
3
3
  * string (pages, settings, views, slots, field-type editors) so they load
4
4
  * without manual host imports. */
5
5
 
6
+ import { registerComponentMap } from "@nextlyhq/admin";
6
7
  import { registeredComponentPaths as listed } from "./plugin-admin-components.generated";
7
8
 
8
9
  const registered = {};
@@ -29,4 +30,5 @@ if (
29
30
  );
30
31
  }
31
32
 
33
+ registerComponentMap(registered);
32
34
  export const registeredComponentPaths = listed;
@@ -26,8 +26,11 @@ export async function register(): Promise<void> {
26
26
  // Next.js writes its Cache Components setting into this file as it builds
27
27
  // it. Nextly, loaded from node_modules, cannot read that for itself. With
28
28
  // it off, Nextly warns at start; with it on, a cached read that finds no
29
- // "use cache" read function says so.
29
+ // "use cache" read function says so. The same holds for the build's newest
30
+ // migration, which withNextly sets: a production start compares it with
31
+ // the database's schema version and warns when the database is behind.
30
32
  await createRegister(config, {
31
33
  cacheComponents: process.env.__NEXT_CACHE_COMPONENTS,
34
+ buildSchemaVersion: process.env.NEXTLY_BUILD_SCHEMA_VERSION,
32
35
  })();
33
36
  }
@@ -41,8 +41,8 @@ working on an app.
41
41
  - **Plugin APIs come from `@nextlyhq/plugin-sdk`; schema APIs come from
42
42
  `nextly/config`.** The SDK is the stability boundary for everything a plugin
43
43
  does AS a plugin: `definePlugin`, field factories, `pluginField` and
44
- `NextlyError` from `@nextlyhq/plugin-sdk`; `registerComponents` and
45
- `registerKnownPlugin` from `@nextlyhq/plugin-sdk/admin`; `createTestNextly`
44
+ `NextlyError` from `@nextlyhq/plugin-sdk`; `registerComponents` from
45
+ `@nextlyhq/plugin-sdk/admin`; `createTestNextly`
46
46
  from `@nextlyhq/plugin-sdk/testing`. Collections and singles are defined the same way an app defines
47
47
  them, with `defineCollection` from `nextly/config` — which is what
48
48
  `src/collections/example.ts` does.
@@ -10,9 +10,12 @@ export async function register(): Promise<void> {
10
10
  // Next.js writes its Cache Components setting into this file as it builds
11
11
  // it. Nextly, loaded from node_modules, cannot read that for itself. With
12
12
  // it off, Nextly warns at start; with it on, a cached read that finds no
13
- // "use cache" read function says so.
13
+ // "use cache" read function says so. The same holds for the build's newest
14
+ // migration, which withNextly sets: a production start compares it with
15
+ // the database's schema version and warns when the database is behind.
14
16
  await createRegister(config, {
15
17
  cacheComponents: process.env.__NEXT_CACHE_COMPONENTS,
18
+ buildSchemaVersion: process.env.NEXTLY_BUILD_SCHEMA_VERSION,
16
19
  })();
17
20
 
18
21
  // Create the user admin.devAutoLogin signs in as (see seed-dev-user.ts).
@@ -3,7 +3,7 @@
3
3
  * string (pages, settings, views, slots, field-type editors) so they load
4
4
  * without manual host imports. */
5
5
 
6
- import { registerComponents } from "@nextlyhq/admin";
6
+ import { registerComponentMap } from "@nextlyhq/admin";
7
7
  import * as _p0 from "{{pluginName}}/admin";
8
8
  import { registeredComponentPaths as listed } from "./plugin-admin-components.generated";
9
9
 
@@ -33,5 +33,5 @@ if (
33
33
  );
34
34
  }
35
35
 
36
- registerComponents(registered);
36
+ registerComponentMap(registered);
37
37
  export const registeredComponentPaths = listed;
@@ -1,24 +1,14 @@
1
1
  /**
2
- * Admin component registration (D19/D60). Importing this module registers the
3
- * React components referenced by `contributes.admin` string paths so the host
4
- * admin can resolve them. The host's generated import map imports this for you;
5
- * the eager + lazy registration below is the fallback.
2
+ * Admin component registration. Importing this module registers the React
3
+ * components referenced by `contributes.admin` string paths so the host admin
4
+ * can resolve them. The host's generated component map imports it for you.
6
5
  */
7
- import {
8
- registerComponents,
9
- registerKnownPlugin,
10
- } from "@nextlyhq/plugin-sdk/admin";
6
+ import { registerComponents } from "@nextlyhq/plugin-sdk/admin";
11
7
 
12
8
  import { SettingsPage } from "./SettingsPage";
13
9
 
14
10
  const SETTINGS_PATH = "{{pluginName}}/admin#SettingsPage";
15
11
 
16
- // Eager: register on module load.
17
12
  registerComponents({ [SETTINGS_PATH]: SettingsPage });
18
13
 
19
- // Lazy fallback: the host can trigger registration on demand by package prefix.
20
- registerKnownPlugin("{{pluginName}}", async () => {
21
- registerComponents({ [SETTINGS_PATH]: SettingsPage });
22
- });
23
-
24
14
  export { SettingsPage };
@@ -1,24 +0,0 @@
1
- import { connection } from "next/server";
2
- import { Suspense } from "react";
3
-
4
- export default function AdminLayout({
5
- children,
6
- }: {
7
- children: React.ReactNode;
8
- }) {
9
- return (
10
- <Suspense fallback={null}>
11
- <ForThisRequest>{children}</ForThisRequest>
12
- </Suspense>
13
- );
14
- }
15
-
16
- /**
17
- * The admin renders for each request, never from a cache another user's
18
- * request filled. Beneath the layout's Suspense boundary, so under Cache
19
- * Components the rest of the page still prerenders.
20
- */
21
- async function ForThisRequest({ children }: { children: React.ReactNode }) {
22
- await connection();
23
- return children;
24
- }