hd-prism-app

/home/avalon/.hermes/skills/devops/hd-prism-app/SKILL.md · raw

HD Prism App Development

Architecture

Nginx Config

Adding public paths

When adding any path that must be publicly accessible without auth (share links, webhooks, etc.), add a dedicated location block with auth_basic off BEFORE the catch-all location /. Example:

location /share/ {
    auth_basic off;
    proxy_pass http://127.0.0.1:3010;
    # ... standard proxy headers
}

Known Gotchas

  1. Port mismatch: The Next.js client runs on port 3010, NOT 3000. Always verify with pm2 logs hd-prism-client or ss -tlnp.
  2. Static files path must match the live build: Nginx should serve _next/static from /home/avalon/apps/hd-prism/apps/hdprism/.next/static/. If it points at an old deploy directory, new builds will not actually reach users and PWA updates will appear stuck.
  3. PWA cannot sit behind nginx basic auth: Standalone PWAs do not reliably carry HTTP Basic Auth. If auth_basic is enabled on location /, the installed app may open to a blank or broken screen. Keep nginx basic auth off for the main app and use app-level auth instead.
  4. Share links need public routing: If nginx auth is ever reintroduced, /share/ still needs a dedicated public location block or share pages will fail.
  5. URL sync: The app uses ?chart=<id> query param to track the current chart in the URL. The HdprismShell component syncs currentChartId to the URL and reads it on initial load (priority: URL param > localStorage > most recent chart).
  6. Library/I Ching mandala uses app-consistent gate order: If you add or edit the custom I Ching SVG view, keep apps/hdprism/lib/ichingWheelData.js GATE_RING_ORDER identical to components/RaveMandala.tsx gate order/direction. A visually plausible reverse order is WRONG for this app.
  7. I Ching build rings are not repeated 64 times: The inner study rings must render only 4 / 8 / 16 / 32 visible figures, centered in their parent sectors. Do not repeat the 2/3/4/5-line stacks at every outer wedge.
  8. I Ching build logic is bottom-preserving, top-adding: Each next ring keeps the previous ring as the LOWER lines and adds exactly one NEW TOP line. If the progression looks plausible but cannot be followed radially from inner to outer rings, the build order is wrong.
  9. Gate info panels must use King Wen line patterns, not radial wedge mapping: The I Ching mandala ring helpers (GATE_RING_ORDER, getRingFigure) are correct for the radial/library view but can be WRONG for a gate detail card. If a gate panel shows the right gate title/glyph but the wrong six-line stack, use a direct King Wen mapping keyed by gate/hexagram number for the figure and keep the mandala helpers only for the wheel visualization.
  10. Environment uses Design South Node, not Design Sun: When adding Human Design Environment to bodygraph JSON, UI, filters, or reports, compute it from activations.Design.SouthNodeColor selects the environment family and Tone < 4 determines left/right subtype. A common bug is using Design.Sun.Tone; that produces wrong environment variants. See references/environment-and-chart-storage.md.

Human Design Environment wiring

Known Gotchas

Reusable implementation pattern: add a library/reference section

When adding a library-style reference area to HD Prism:

  1. Create a dedicated component such as components/LibraryView.tsx for the landing screen and any subviews.
  2. Add new app-level view modes in ChartContext.tsx (for example library and iching).
  3. In Sidebar.tsx, add the new navigation button in the bottom row next to Settings / Theme and route it through switchViewMode(...).
  4. In HdprismShell.tsx, render the new view components near the top-level return and guard existing chart/compare/reading/transit sections with !showLibraryView / !showIChingView so the new screens fully replace the main surfaces.
  5. Verify with: - node --test apps/hdprism/lib/<your-helper>.test.mjs for any pure helper logic - npm run build in apps/hdprism (lint currently has many pre-existing unrelated failures, so build is the reliable gate) - pm2 restart hd-prism-client
  6. After restart, if browser automation still only shows Loading..., treat that as a possible stale client/runtime state and also hard-refresh or reopen the PWA before assuming the new UI is missing.
  7. Sidebar naming collision: components/Sidebar.tsx already has a local view toggle for saved lists ("single" | "compare"). If you also pull viewMode from ChartContext to add app-level views (chart/reading/transits/library/etc.), DO NOT reuse the name viewMode for the local sidebar state or the Next build will fail with the name "viewMode" is defined multiple times. Rename the local state to something like listViewMode / setListViewMode.
  8. Verification workflow: npm run lint currently reports many pre-existing repo-wide errors/warnings unrelated to most feature work. For targeted UI changes, use build as the primary gate (cd apps/hdprism && npm run build) after running any targeted tests you add, and only treat new errors in touched files as regressions you introduced.

Key Components

Gate panel hexagram figure pattern

Frontend ↔ Backend Request Pattern

Sharing System (added Apr 2026)

Reading generation performance

API Routes

Bulk chart import workflow absorbed from hd-prism-bulk-import

Use the existing app internals to insert charts directly without triggering reading generation.

Key modules under apps/api/src/: - models/bodygraph.tscreateBodygraph(name, dateUtc, location) - descriptions/descriptionDb.tscreateSavedChart(...), listSavedChartsForUser(...) - interpretation/chartFingerprint.tscomputeChartFingerprint(...)

Pattern: 1. parse source birth records 2. convert local civil time + timezone to UTC before calling createBodygraph 3. attach provenance like timezone/UTC to the bodygraph JSON if useful 4. compute chart fingerprint 5. dedupe against existing saved charts 6. persist with createSavedChart

Important lesson: readings are generated separately, so direct bodygraph/chart insertion is the safe path for bulk imports.

Library / I Ching View (added Apr 2026)

Important implementation pitfall

The inner build rings must NOT repeat symbols at all 64 outer wedge positions.

Correct structure: - 2-line ring: exactly 4 visible figures - 3-line ring: exactly 8 visible figures - 4-line ring: exactly 16 visible figures - 5-line ring: exactly 32 visible figures - number ring: 64 positions - outer ring: 64 hexagrams

The right approach is: - keep the outer 64-gate/hexagram wheel intact - center each inner-ring figure in its parent sector using helper placements (see getDisplayRingPlacements()) - do NOT render 64 repeated parent-pattern stacks for the 2/3/4/5-line rings

Sidebar.tsx already had local list state named viewMode for single vs compare chart lists. When adding app-level viewMode from ChartContext, this caused a build-breaking duplicate identifier. Rename the sidebar-local state (for example listViewMode) instead of reusing viewMode.