our order, not NPM's — and the two sections this is heading towards

the order is a claim about what people come here for: proxy hosts,
certificates, streams, then the rest. this file argued the opposite yesterday
— "NPM's words in NPM's order" — and half of that was wrong. the VOCABULARY is
worth keeping, because somebody will end up in NPM's UI eventually and better
names just mean learning both. the ORDER is an accident of how NPM grew, and
reproducing it gives up the one thing a plugin is for.

and two new entries, listed and not built: Domains, and DNS Providers. they sit
below a line, with Connection, because they are OFFICER's own rather than
things NPM owns — what it knows about your domains, and the registrar keys it
holds.

shown rather than hidden on purpose. a nav that shows them says what this is
FOR, including to whoever opens it in six months wondering what was decided.
the pane says plainly that it does not exist and then what it will be — "not
built" alone reads as an error, a description alone reads as something broken,
and together they read as a plan.

the planned check runs BEFORE the connection check: "you have not connected
NPM" is not why Domains is empty, and would be a misleading thing to be told.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-25 19:11:47 +00:00
co-authored by Claude Opus 5
parent 66383aa9a4
commit 219625ec82
4 changed files with 120 additions and 23 deletions
+10 -1
View File
@@ -1,11 +1,12 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router';
import { useClient } from 'hooks/useClient';
import { DEFAULT_SECTION, isSectionKey, type SectionKey } from './sections';
import { DEFAULT_SECTION, SECTIONS, isSectionKey, type SectionKey } from './sections';
import { HostsPanel } from './HostsPanel';
import { CertificatesPanel } from './CertificatesPanel';
import { ConnectionPanel } from './ConnectionPanel';
import { ListSection, REDIRECTIONS, STREAMS, DEAD_HOSTS, ACCESS_LISTS } from './ListSection';
import { PlannedSection } from './PlannedSection';
import { useNpmChanged } from './channel';
/**
@@ -56,6 +57,11 @@ export const DetailPanel = () => {
return <div className="flex size-full items-center justify-center p-6 text-sm text-muted-foreground">Loading…</div>;
}
// A planned section says so before anything else — including before the connection check, because "you
// have not connected NPM" is not why Domains is empty and would be a misleading thing to be told.
const planned = SECTIONS.find((s) => s.key === section && s.planned);
if (planned) return <PlannedSection section={planned} />;
if (!configured || section === 'connection') return <ConnectionPanel />;
switch (section) {
@@ -71,5 +77,8 @@ export const DetailPanel = () => {
return <ListSection {...DEAD_HOSTS} />;
case 'access-lists':
return <ListSection {...ACCESS_LISTS} />;
default:
// `domains` and `dns-providers` are handled above; this keeps the switch total without a cast.
return null;
}
};