nerdsystem 0.0.23 → 0.0.24

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/api.d.ts CHANGED
@@ -53,6 +53,8 @@ export interface Project {
53
53
  name: string;
54
54
  scriptName: string;
55
55
  url: string;
56
+ /** The address on the owner's own domain, once one is verified. Absent from an older platform. */
57
+ customUrl?: string | null;
56
58
  }
57
59
  export interface Deployment {
58
60
  id: string;
@@ -46,6 +46,8 @@ export declare function checksMetadata(results: GateResult[]): {
46
46
  export interface ShipResult {
47
47
  deployment: Deployment;
48
48
  url: string;
49
+ /** The app's address on the owner's own domain, once one is verified; null otherwise. */
50
+ customUrl: string | null;
49
51
  migrations: {
50
52
  applied: string[];
51
53
  skipped: string[];
@@ -185,11 +185,14 @@ export async function shipBuild(args) {
185
185
  }
186
186
  const { deployment } = await api.post(projectPath(nerd, "/deployments"), form);
187
187
  const { project } = await api.get(projectPath(nerd));
188
- log.ok(`Deployed ${deployment.id} (${deployment.status}) → ${project.url}`);
188
+ log.ok(`Deployed ${deployment.id} (${deployment.status}) → ${project.customUrl ?? project.url}`);
189
+ // The owner knows the app by their own domain; the platform address is the one that is probed, because it always resolves.
190
+ if (project.customUrl)
191
+ log.info(`Also at ${project.url}`);
189
192
  if (!opts["skip-probe"] && deployment.status === "live")
190
193
  log.step(`Probing ${project.url}`);
191
194
  const probes = await probeAfterDeploy(root, deployment, project.url, Boolean(opts["skip-probe"]));
192
- return { deployment, url: project.url, migrations: mig, probes, source, sourceSkipped, lineage, warnings: pack.warnings };
195
+ return { deployment, url: project.url, customUrl: project.customUrl ?? null, migrations: mig, probes, source, sourceSkipped, lineage, warnings: pack.warnings };
193
196
  }
194
197
  /** The one line about the code after a live deploy, keyed on what the API recorded, not on what we sent. */
195
198
  export function sourceLine(r) {
@@ -230,7 +233,7 @@ export async function deploy(opts) {
230
233
  const wantReview = r.deployment.status === "live" && Boolean(r.source);
231
234
  if (opts.json) {
232
235
  const review = wantReview ? await platformReview(api, `${projectPath(nerd)}/sources/${r.source.id}`, reviewPage) : null;
233
- return printJson({ deployment: r.deployment, url: r.url, migrations: r.migrations, probes: r.probes, source: r.source, sourceSkipped: r.sourceSkipped, lineage: r.lineage.passed, warnings: r.warnings, review });
236
+ return printJson({ deployment: r.deployment, url: r.url, customUrl: r.customUrl, migrations: r.migrations, probes: r.probes, source: r.source, sourceSkipped: r.sourceSkipped, lineage: r.lineage.passed, warnings: r.warnings, review });
234
237
  }
235
238
  printProbe(r.url, r.probes);
236
239
  if (r.deployment.status === "live") {
@@ -243,7 +246,7 @@ export async function deploy(opts) {
243
246
  log.step("Your app is live. Asking for a model review of how it is put together (up to a minute or two; safe to stop waiting)");
244
247
  printReview(await platformReview(api, `${projectPath(nerd)}/sources/${r.source.id}`, reviewPage));
245
248
  }
246
- log.info(`First time? Sign up on your app at ${r.url}, then make yourself admin in the dashboard's Auth tab: ${dashboardUrl(api.apiUrl)}/app/${nerd.org}/projects/${nerd.project}/auth`);
249
+ log.info(`First time? Sign up on your app at ${r.customUrl ?? r.url}, then make yourself admin in the dashboard's Auth tab: ${dashboardUrl(api.apiUrl)}/app/${nerd.org}/projects/${nerd.project}/auth`);
247
250
  }
248
251
  export async function deployments(opts) {
249
252
  const nerd = readNerdJson(findProjectRoot());
@@ -192,4 +192,4 @@ export async function init(dir, args) {
192
192
  log.ok(`Ready. Next:\n cd ${dir}\n pnpm install\n nerd dev\n\nThen open the folder in your coding agent and ask it to build the first feature; the nerdsystem skill walks it through.\nDeploys go to ${project.url}`);
193
193
  }
194
194
  // Kept in sync with packages/sdk/package.json by the release script.
195
- const SDK_VERSION = "0.0.23";
195
+ const SDK_VERSION = "0.0.24";
@@ -52,6 +52,16 @@ export function setupText(s) {
52
52
  "If you are a coding agent: give the owner these steps as they are, numbered, and nothing else to decide. Do not ask which company they use (it was looked up) and do not offer other record types. When they say it is done, run `nerd domains` until the status is active, then open the address to confirm.",
53
53
  ].join("\n");
54
54
  }
55
+ /** Whether the domain without www forwards to the app yet, in words an agent can pass on. */
56
+ function bareText(b) {
57
+ if (!b)
58
+ return "";
59
+ if (b.status === "forwarding")
60
+ return `${b.hostname} forwards here`;
61
+ if (b.status === "starting")
62
+ return `${b.hostname} is starting (certificate, under a minute)`;
63
+ return `${b.hostname} does not point here yet`;
64
+ }
55
65
  export async function domainsList(opts) {
56
66
  const nerd = readNerdJson(findProjectRoot());
57
67
  const r = await ApiClient.fromConfig().get(projectPath(nerd, "/domains"));
@@ -59,7 +69,7 @@ export async function domainsList(opts) {
59
69
  return printJson(r);
60
70
  if (!r.domains.length)
61
71
  return log.info(`No custom domains. Add one: nerd domains add example.com`);
62
- table(r.domains.map((d) => ({ hostname: d.hostname, status: d.status, ssl: d.sslStatus ?? "", does: d.redirectTo ? `forwards to ${d.redirectTo}` : "the app", error: d.lastError ?? "", id: d.id })), ["hostname", "status", "ssl", "does", "error", "id"]);
72
+ table(r.domains.map((d) => ({ hostname: d.hostname, status: d.status, ssl: d.sslStatus ?? "", does: d.redirectTo ? `forwards to ${d.redirectTo}` : "the app", "bare name": bareText(d.bare), error: d.lastError ?? "", id: d.id })), ["hostname", "status", "ssl", "does", "bare name", "error", "id"]);
63
73
  // Only addresses still waiting for their DNS records have steps left to do.
64
74
  for (const s of r.setups ?? [])
65
75
  log.info(`\n${setupText(s)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nerdsystem",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "description": "nerd: start, check, and deploy a web app on nerdsystem from the terminal or a coding agent.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -184,7 +184,7 @@ Paid plans only; on Free the command answers with the plan that includes it, so
184
184
 
185
185
  1. Run `nerd domains add example.com` with the bare domain the owner gives you. The platform makes `www.example.com` the app's address and sets the bare name up to forward to it. It also looks up which company runs the domain's DNS and prints the exact steps for that company.
186
186
  2. Give the owner those steps as printed, numbered. Do not ask who their registrar is, do not show a table of record types, and do not offer alternatives: the platform already chose. The steps are things only they can do (signing in where the domain is managed).
187
- 3. When they say it is done, run `nerd domains` every minute or two until the status is `active`, then open the address and confirm it loads with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
187
+ 3. When they say it is done, run `nerd domains` every minute or two until the status is `active` and the "bare name" column says it forwards here, then open both addresses and confirm they load with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
188
188
  4. Tell them two things once it is live: they sign in once more on the new address (same account, same data), and links to the old `.nerdsystem.app` address keep working.
189
189
 
190
190
  For a subdomain such as `app.example.com`, the same command gives a single record to add.
@@ -2,7 +2,7 @@
2
2
  description: How to build, run, and deploy this app on nerdsystem. Applies to server, database, auth, and deploy work.
3
3
  alwaysApply: true
4
4
  ---
5
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (1794b8a1a530); edit the skill, then run: nerd agents sync -->
5
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (e9b33e090df6); edit the skill, then run: nerd agents sync -->
6
6
 
7
7
  # Building on nerdsystem
8
8
 
@@ -185,7 +185,7 @@ Paid plans only; on Free the command answers with the plan that includes it, so
185
185
 
186
186
  1. Run `nerd domains add example.com` with the bare domain the owner gives you. The platform makes `www.example.com` the app's address and sets the bare name up to forward to it. It also looks up which company runs the domain's DNS and prints the exact steps for that company.
187
187
  2. Give the owner those steps as printed, numbered. Do not ask who their registrar is, do not show a table of record types, and do not offer alternatives: the platform already chose. The steps are things only they can do (signing in where the domain is managed).
188
- 3. When they say it is done, run `nerd domains` every minute or two until the status is `active`, then open the address and confirm it loads with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
188
+ 3. When they say it is done, run `nerd domains` every minute or two until the status is `active` and the "bare name" column says it forwards here, then open both addresses and confirm they load with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
189
189
  4. Tell them two things once it is live: they sign in once more on the new address (same account, same data), and links to the old `.nerdsystem.app` address keep working.
190
190
 
191
191
  For a subdomain such as `app.example.com`, the same command gives a single record to add.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (1794b8a1a530); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (e9b33e090df6); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -181,7 +181,7 @@ Paid plans only; on Free the command answers with the plan that includes it, so
181
181
 
182
182
  1. Run `nerd domains add example.com` with the bare domain the owner gives you. The platform makes `www.example.com` the app's address and sets the bare name up to forward to it. It also looks up which company runs the domain's DNS and prints the exact steps for that company.
183
183
  2. Give the owner those steps as printed, numbered. Do not ask who their registrar is, do not show a table of record types, and do not offer alternatives: the platform already chose. The steps are things only they can do (signing in where the domain is managed).
184
- 3. When they say it is done, run `nerd domains` every minute or two until the status is `active`, then open the address and confirm it loads with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
184
+ 3. When they say it is done, run `nerd domains` every minute or two until the status is `active` and the "bare name" column says it forwards here, then open both addresses and confirm they load with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
185
185
  4. Tell them two things once it is live: they sign in once more on the new address (same account, same data), and links to the old `.nerdsystem.app` address keep working.
186
186
 
187
187
  For a subdomain such as `app.example.com`, the same command gives a single record to add.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (1794b8a1a530); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (e9b33e090df6); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -181,7 +181,7 @@ Paid plans only; on Free the command answers with the plan that includes it, so
181
181
 
182
182
  1. Run `nerd domains add example.com` with the bare domain the owner gives you. The platform makes `www.example.com` the app's address and sets the bare name up to forward to it. It also looks up which company runs the domain's DNS and prints the exact steps for that company.
183
183
  2. Give the owner those steps as printed, numbered. Do not ask who their registrar is, do not show a table of record types, and do not offer alternatives: the platform already chose. The steps are things only they can do (signing in where the domain is managed).
184
- 3. When they say it is done, run `nerd domains` every minute or two until the status is `active`, then open the address and confirm it loads with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
184
+ 3. When they say it is done, run `nerd domains` every minute or two until the status is `active` and the "bare name" column says it forwards here, then open both addresses and confirm they load with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
185
185
  4. Tell them two things once it is live: they sign in once more on the new address (same account, same data), and links to the old `.nerdsystem.app` address keep working.
186
186
 
187
187
  For a subdomain such as `app.example.com`, the same command gives a single record to add.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (1794b8a1a530); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (e9b33e090df6); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -181,7 +181,7 @@ Paid plans only; on Free the command answers with the plan that includes it, so
181
181
 
182
182
  1. Run `nerd domains add example.com` with the bare domain the owner gives you. The platform makes `www.example.com` the app's address and sets the bare name up to forward to it. It also looks up which company runs the domain's DNS and prints the exact steps for that company.
183
183
  2. Give the owner those steps as printed, numbered. Do not ask who their registrar is, do not show a table of record types, and do not offer alternatives: the platform already chose. The steps are things only they can do (signing in where the domain is managed).
184
- 3. When they say it is done, run `nerd domains` every minute or two until the status is `active`, then open the address and confirm it loads with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
184
+ 3. When they say it is done, run `nerd domains` every minute or two until the status is `active` and the "bare name" column says it forwards here, then open both addresses and confirm they load with https. If it is still pending after an hour, run `nerd domains` and read the steps again with them; the usual cause is a leftover parking record.
185
185
  4. Tell them two things once it is live: they sign in once more on the new address (same account, same data), and links to the old `.nerdsystem.app` address keep working.
186
186
 
187
187
  For a subdomain such as `app.example.com`, the same command gives a single record to add.