Skip to content

Frontend Development Guide

Status: Current

Last reviewed: 2026-05-13

This guide records frontend rules for nexus-frontend. It is intended for human review and AI-assisted edits.

Stack

  • Next.js App Router.
  • Tailwind CSS.
  • shadcn/ui source components under src/components/ui.
  • Lucide icons through lucide-react.
  • Local i18n JSON under src/i18n.
  • API helpers under src/lib/api.ts.

Use existing project components and helper functions before adding new patterns.

Layout Rules

  • Dashboard pages use the existing sidebar/header shell.
  • Page content should fit inside the existing max-width container.
  • Prefer dense operational layouts over marketing-style sections.
  • Avoid nested cards. Use cards for repeated objects, dialogs, and framed tools only.
  • Dialogs need accessible titles and should keep action footers fixed when the form body scrolls.
  • Use semantic tokens such as text-muted-foreground, bg-card, border-border, and text-foreground.

Table Rules

All data tables should follow one visual system.

Status Column

  • Status cells use a single size-2 rounded color dot.
  • Do not render status text in ordinary table status cells.
  • Provide text through title for simple tables such as L3, L4, and upstreams.
  • On pages that already use a tooltip, such as nodes, the tooltip can provide the status text.

Example:

tsx
<span
  title={enabled ? t("common.enabled") : t("common.disabled")}
  className={cn(
    "block size-2 rounded-full",
    enabled ? "bg-emerald-500" : "bg-muted-foreground/40"
  )}
/>

Name Column

  • Do not use font-medium in table name cells.
  • Use default text-foreground for the primary name.
  • Use text-muted-foreground for secondary metadata columns so hierarchy comes from contrast, not font weight.

Example:

tsx
<TableCell className="text-foreground">{name}</TableCell>

Badge Cleanup

Avoid Badge for plain table metadata.

  • L4 chains protocol column uses plain font-mono text-xs.
  • L4 chains topology column uses plain font-mono text-xs text.
  • TLS expiration date uses text, not Badge.
  • User status uses text, not Badge.
  • Audit action uses text, not Badge.

Use Badge only when the value is truly a label/chip, not routine table text.

Font Size

  • Do not use text-[10px] or text-[11px] inside tables.
  • Use text-xs for compact table metadata.
  • Use text-sm only when a table cell intentionally follows body sizing.

Endpoint Text

L4 upstream endpoint values are not decorated code blocks.

Use:

tsx
<TableCell className="font-mono text-xs text-muted-foreground">
  {endpoint}
</TableCell>

Do not use <code> with gray background, padding, or rounded block styling for endpoint cells.

Actions

  • Use icon buttons for row actions.
  • Provide aria-label for icon-only buttons.
  • Keep destructive actions muted until hover, then use destructive color.
  • For multi-action overflow, use DropdownMenu with grouped items.

Forms

  • Keep labels concise and stable.
  • Use Input, Select, Switch, Tabs, Dialog, and Button from existing UI components.
  • Preserve required markers for required fields.
  • Validate in the frontend when it prevents a known backend error, but keep backend validation authoritative.
  • Use toast.success, toast.warning, or toast.error for submit outcomes.

Copyable Secrets

  • Node control PSKs are one-time values. Display them in the creation/reset dialog only.
  • Provide copy buttons for secrets, environment blocks, and fingerprints.
  • Do not log secret values.
  • Make the UI copy block wrap and scroll safely on narrow screens.

i18n

  • Add user-facing strings to src/i18n/en.json and zh-CN.json when touching localized pages.
  • Prefer existing keys such as common.create, common.save, and common.delete.
  • Fallback helper functions are acceptable for incomplete translations, but new features should add proper keys.

API Usage

  • Use src/lib/api.ts helpers when available.
  • Use getErrorMessage for toast errors from Axios responses.
  • Use unwrapApiData for API envelopes when a page needs the data field.
  • Paginated pages should use usePaginatedApi and the shared Pagination component.

Accessibility

  • Icon-only buttons require aria-label.
  • Dialogs require DialogTitle.
  • Inputs need labels with htmlFor where practical.
  • Status dots need title or tooltip text.
  • Do not rely on color alone when the state is part of a critical workflow; provide tooltip/title or surrounding context.

Review Checklist

Before merging frontend UI changes:

  • Tables follow the status, name, Badge, font-size, and endpoint rules above.
  • No table cell uses text-[10px] or text-[11px].
  • No table name cell uses font-medium.
  • Routine metadata is not rendered as Badge.
  • Icon buttons have accessible labels.
  • New strings are localized.
  • Mutating actions show success or error feedback.

NexusNet documentation