IU Core 4000x — 03 Nuxt UI deploy-ready package · boundary · residual
03 — Nuxt UI deploy-ready package · authoring · boundary · residual
1. What 3000x left
3000x recorded NUXT_FRONTEND_AUTHORING_FOR_THREE_AXIS_ADMIN_SCREEN as the single exact blocker outside IU Core scope. Doc 04 of 3000x said the VPS Nuxt deploy mount-point /opt/incomex/deploys/nuxt-output/ is a compiled .output bundle with zero IU Core source references; redeploying incomex-nuxt was a no-op for IU Core because no Nuxt route consumed any IU Core env.
2. 4000x re-discovery
The 4000x macro did a fresh search and found a Nuxt source repository on the VPS at /opt/incomex/docker/nuxt-repo/web — a full Nuxt 3 codebase with pages/admin/*.vue, composables/, layers/, modules/directus/. Its Dockerfile (NITRO_PRESET=node-server) builds the .output that gets mounted into incomex-nuxt. Its conventions:
- Directus client wired via
modules/directus/runtime/composables/useDirectus.ts(useDirectus<T>(readItems(...))pattern); admin pages also useconst { $directus } = useNuxtApp()directly (e.g.pages/admin/knowledge-tree.vue). - Schema-driven tables via
composables/useDirectusTable.ts(S101 rule). useRuntimeConfig().public.<x>for env-driven config.definePageMeta({ middleware: 'auth' })on admin pages.
A grep -r 'iu_three_axis_envelope|IU_CORE' on the source tree confirmed still zero IU Core references — the 3000x finding "the admin screen has not yet been authored" is correct.
3. Why this macro authors a package, not a deploy
The Nuxt repo is a separate codebase (its own main branch, HEAD f690c7f auto-snapshot 2026-05-12T16:00). It is built by a separate image pipeline and restarted via docker compose up -d --build nuxt. The 4000x mission rule "no broad service restart; no restart except incomex-nuxt" lets us restart that one container, but:
- a forced
--buildof the Nuxt container is a long, fragile operation (pnpm install, full Nuxt build, Sentry / Firebase plugin checks); - the Nuxt repo is owned by frontend / DevOps — pushing files into it from an IU Core macro is outside the scope, mirror of how IU Core does not push to Directus / Qdrant beyond its registered surfaces;
- the right deliverable from an IU Core macro is a deploy-ready package that follows the existing conventions and can be merged + built by the responsible team in a single short slice.
This is the same DONE_WITH_EXTERNAL_BLOCKER pattern the 2400x macro used for Directus REST apply (admin token required) and 2000x used for the Qdrant apply step (api-key + embedder required).
4. What was authored
ui-package/nuxt-iu-three-axis/ in the iu-cutter repo:
ui-package/nuxt-iu-three-axis/
├── README.md # contract + deploy steps
├── pages/admin/iu-three-axis.vue # the screen (3 tabs, health card)
├── composables/useIuThreeAxis.ts # wraps useDirectus<>(readItems(...))
├── runtimeConfig.snippet.ts # additive nuxt.config.ts patch
└── compose.snippet.yml # additive docker-compose env entry
Boundary properties (each is a passing test in tests/test_iu_core_4000x_auto_refresh_trigger_ui_runtime.py::TestNuxtUiPackageDeployReady):
- No direct PG access. The Vue page imports nothing from PG; the composable imports only
@directus/sdk(readItems,aggregate). - No hardcoded collection name. Collection name read from
useRuntimeConfig().public.iuCoreDirectusCollectionpopulated from theIU_CORE_DIRECTUS_COLLECTIONenv. The compose snippet supplies the defaultiu_three_axis_envelope. - No business logic. Filters and sorts are sent to Directus via
readItems(collection, { filter, sort, fields, limit, page }). Grouping for the three tabs is pure presentation logic — derived from the rows already fetched, not new state. - Read-only. No
createItem/updateItem/deleteItemcalls. The package never writes back to Directus or PG. - No image / port / volume change. The compose snippet adds one env variable to the existing
nuxt:service; nothing about how the container is built or networked changes.
5. Three tabs covered
| Tab | Source columns | Display |
|---|---|---|
| Axis A — Original text | axis_a_doc_code, axis_a_section_code, axis_a_sort_order |
Documents grouped by axis_a_doc_code, sections sorted by axis_a_sort_order. Uses the same linear-key contract as v_iu_source_outline / fn_iu_reconstruct_source. |
| Axis B — Semantic | axis_b_tags, axis_b_tags_by_source |
Inverted index — for every tag, the IUs carrying it. Sorted by count desc. Matches the 120x derived metadata layer (iu_metadata_tag_registry vocab). |
| Axis C — Hierarchy | axis_c_parent_id, axis_c_depth, axis_c_ancestors, axis_c_ancestor_addresses |
Tree built client-side from the flat list. Matches fn_iu_subtree lineage. |
A header card shows the row count + a Refresh button (re-calls useAsyncData(...) against Directus, no PG access, no envelope refresh — the auto-refresh trigger handles cache freshness server-side).
6. Deploy steps (frontend developer responsibility)
Recorded verbatim in ui-package/nuxt-iu-three-axis/README.md §"Deploy steps". Summary:
cp pages/admin/iu-three-axis.vue → /opt/incomex/docker/nuxt-repo/web/pages/admin/cp composables/useIuThreeAxis.ts → /opt/incomex/docker/nuxt-repo/web/composables/- merge
runtimeConfig.snippet.tsintonuxt.config.ts - merge
compose.snippet.ymlinto/opt/incomex/docker/docker-compose.yml cd /opt/incomex/docker && docker compose up -d --build nuxtdot_iu_nuxt_config_verify(already a 3000x operator command) confirms the env reached the running container.- smoke
http://incomex-nuxt:3000/admin/iu-three-axis.
7. Residual
NUXT_FRONTEND_DEPLOY_FOR_THREE_AXIS_ADMIN_SCREEN — copy + image rebuild + single-container restart, no IU Core code change required. This is the narrowest possible residual: the screen exists, the contract is verified, the deploy command sequence is one short shell block.