Sub-ticket of epic #346. Depends on #347 (API contracts); demo-able end-to-end once #348 lands. Can start against P1 endpoints in parallel with P2–P4.
What: the student-facing Art Studio on learn.spikersoft.com — a new feature library presenting the pipeline as a guided journey (concept → model → texture → rig → animate → export) so the educational structure of a real 3D pipeline is the UI, not hidden behind it.
Scope:
New libraries/features/art-studio lib copying the trellis-3d-generator structure (project.json tags layer:feature, barrel src/index.ts, tsconfig.base.json path alias @spikersoft/feature-art-studio); signals-in-root-service state (pattern: threed-generator.service.ts)
Lazy route in projects/spikersoft/src/routes.ts behind [AuthGuard] (students + staff); staff-only affordances via hasAnyRole(...) from role.guard.ts
Submission wizard: asset type (character / prop), prompt or drawing upload (FormData multipart, reuse book-upload patterns), model/preset choices kept simple for students
Pipeline progress view: per-stage timeline fed by SignalR (accessTokenFactory + skipNegotiation pattern from system-notification.service.ts), including queue position / "waiting for GPU" state — single shared card means honest waiting UX
three.js viewer (extend the trellis component's GLTFLoader/OrbitControls usage): textured model orbit view, skeleton overlay toggle after rigging, animation clip playback after animation stage; per-stage artifact tabs (concept image, texture maps, previews)
My Assets library: paged grid with thumbnails, stage status chips, restart-from-stage / cancel / delete actions, GLB (and texture-pack) download
Transloco i18n from day one (en + es — see the pain in #288/#289/#296); Storybook stories + specs per repo convention
Note: the existing trellis-3d-generator route should redirect into the studio (or be absorbed) once parity is reached — decide here, don't leave two 3D entry points.
Acceptance: a student submits a prompt, watches stages advance live with queue position shown, orbits the textured model, toggles the skeleton, plays the walk preset, and downloads the GLB — all in both languages; another student's assets are never visible.
Sub-ticket of epic #346. Depends on #347 (API contracts); demo-able end-to-end once #348 lands. Can start against P1 endpoints in parallel with P2–P4.
**What:** the student-facing Art Studio on learn.spikersoft.com — a new feature library presenting the pipeline as a guided journey (concept → model → texture → rig → animate → export) so the educational structure of a real 3D pipeline is the UI, not hidden behind it.
**Scope:**
- [ ] New `libraries/features/art-studio` lib copying the `trellis-3d-generator` structure (`project.json` tags `layer:feature`, barrel `src/index.ts`, `tsconfig.base.json` path alias `@spikersoft/feature-art-studio`); signals-in-root-service state (pattern: `threed-generator.service.ts`)
- [ ] Lazy route in `projects/spikersoft/src/routes.ts` behind `[AuthGuard]` (students + staff); staff-only affordances via `hasAnyRole(...)` from `role.guard.ts`
- [ ] Submission wizard: asset type (character / prop), prompt or drawing upload (`FormData` multipart, reuse `book-upload` patterns), model/preset choices kept simple for students
- [ ] Pipeline progress view: per-stage timeline fed by SignalR (`accessTokenFactory` + `skipNegotiation` pattern from `system-notification.service.ts`), including **queue position / "waiting for GPU"** state — single shared card means honest waiting UX
- [ ] three.js viewer (extend the trellis component's GLTFLoader/OrbitControls usage): textured model orbit view, skeleton overlay toggle after rigging, animation clip playback after animation stage; per-stage artifact tabs (concept image, texture maps, previews)
- [ ] My Assets library: paged grid with thumbnails, stage status chips, restart-from-stage / cancel / delete actions, GLB (and texture-pack) download
- [ ] Transloco i18n from day one (en + es — see the pain in #288/#289/#296); Storybook stories + specs per repo convention
**Note:** the existing `trellis-3d-generator` route should redirect into the studio (or be absorbed) once parity is reached — decide here, don't leave two 3D entry points.
**Acceptance:** a student submits a prompt, watches stages advance live with queue position shown, orbits the textured model, toggles the skeleton, plays the walk preset, and downloads the GLB — all in both languages; another student's assets are never visible.
Frontend direction from Joey (2026-07-04): Angular-native composable components — no monolithic page. The studio lives under the Tools section alongside the other dev tools, built as a series of small standalone components in the spirit of ProArt's own decomposition (asset types → stage pipeline → per-stage artifacts → library), composed by a thin shell:
art-prompt-composer — asset type + prompt/drawing submission
art-stage-timeline — the pipeline as a visible, honest sequence (queue position, per-stage state) — the educational spine of the UI
art-asset-card / art-asset-library — my-assets grid with status chips + actions
art-studio-shell — routed page composing the above; each piece independently reusable (e.g. the viewer alone can be embedded in gallery #353 or game playgrounds)
Each component standalone, signals-based, individually exportable from @spikersoft/feature-art-studio so P7 (gallery, games handoff) and the playground shell can reuse them without dragging in the whole studio.
Implementation starting against the PR spikersoft-backend#61 API contract; live progress remains polling-abstracted until #349's SignalR events exist.
Frontend direction from Joey (2026-07-04): **Angular-native composable components** — no monolithic page. The studio lives **under the Tools section** alongside the other dev tools, built as a series of small standalone components in the spirit of ProArt's own decomposition (asset types → stage pipeline → per-stage artifacts → library), composed by a thin shell:
- `art-prompt-composer` — asset type + prompt/drawing submission
- `art-stage-timeline` — the pipeline as a visible, honest sequence (queue position, per-stage state) — the educational spine of the UI
- `art-asset-viewer` — three.js GLB orbit view; skeleton toggle + clip playback arrive with P4 stages
- `art-artifact-panel` — per-stage outputs (concept image, texture maps, previews)
- `art-asset-card` / `art-asset-library` — my-assets grid with status chips + actions
- `art-studio-shell` — routed page composing the above; each piece independently reusable (e.g. the viewer alone can be embedded in gallery #353 or game playgrounds)
Each component standalone, signals-based, individually exportable from `@spikersoft/feature-art-studio` so P7 (gallery, games handoff) and the playground shell can reuse them without dragging in the whole studio.
Implementation starting against the PR [spikersoft-backend#61](https://git.spikersoft.com/spikerj/spikersoft-backend/pulls/61) API contract; live progress remains polling-abstracted until #349's SignalR events exist.
First slice up: spikersoft-angular PR #112 — the full composable component set (art-prompt-composer, art-stage-timeline, art-asset-viewer, art-artifact-panel, art-asset-card/art-asset-library, art-studio-shell), registered under /tools (tools outlet + tools-shell entry, palette icon), signals service against the merged P1 API, polling progress behind the ART_ASSET_PROGRESS_SOURCE token for #349's SignalR swap, en+es i18n. Locally verified: lib build/lint, 21/21 vitest, full app dev build.
Ticket stays open for the later slices: SignalR source (#349), viewer skeleton/animation modes (needs P4 stages), quota display (needs #352), real thumbnails, delete confirmation.
First slice up: spikersoft-angular PR [#112](https://git.spikersoft.com/spikerj/spikersoft-angular/pulls/112) — the full composable component set (`art-prompt-composer`, `art-stage-timeline`, `art-asset-viewer`, `art-artifact-panel`, `art-asset-card`/`art-asset-library`, `art-studio-shell`), registered under `/tools` (tools outlet + tools-shell entry, palette icon), signals service against the merged P1 API, polling progress behind the `ART_ASSET_PROGRESS_SOURCE` token for #349's SignalR swap, en+es i18n. Locally verified: lib build/lint, 21/21 vitest, full app dev build.
Ticket stays open for the later slices: SignalR source (#349), viewer skeleton/animation modes (needs P4 stages), quota display (needs #352), real thumbnails, delete confirmation.
SignalR live-progress slice up for merge: backend PR #63 (worker publishes art.asset.stage.*/asset lifecycle events; API relay to NotificationsHub group user-{owner}, mirroring the existing Trellis3D mechanism) + Angular PR #113 (SignalRArtAssetProgressSource behind the existing token, automatic polling fallback, zero component changes). 157/157 backend + 28/28 frontend tests locally.
Deferred with rationale: queue-position — the GpuCoordinator lease AcquireAsync blocks with no queue index exposed, so honest queue position needs the coordinator to emit it; suggest a small follow-up ticket on GpuCoordinator rather than faking it worker-side. The timeline's queuePosition input stays plumbed and unfed until then.
SignalR live-progress slice up for merge: backend PR [#63](https://git.spikersoft.com/spikerj/spikersoft-backend/pulls/63) (worker publishes `art.asset.stage.*`/asset lifecycle events; API relay to `NotificationsHub` group `user-{owner}`, mirroring the existing Trellis3D mechanism) + Angular PR [#113](https://git.spikersoft.com/spikerj/spikersoft-angular/pulls/113) (`SignalRArtAssetProgressSource` behind the existing token, automatic polling fallback, zero component changes). 157/157 backend + 28/28 frontend tests locally.
Deferred with rationale: **queue-position** — the GpuCoordinator lease `AcquireAsync` blocks with no queue index exposed, so honest queue position needs the coordinator to emit it; suggest a small follow-up ticket on GpuCoordinator rather than faking it worker-side. The timeline's `queuePosition` input stays plumbed and unfed until then.
All three delivery PRs are merged to master: #112 (composable component set under Tools + polling progress), #113 (SignalR progress source with fallback), #115 (viewer skeleton overlay + animation playback, verified against real P4 rigged/animated GLBs). Acceptance is met end-to-end on the local stack: submit → live stage updates → orbit the textured model → toggle skeleton → play the walk clip → download the GLB, en+es throughout, ownership enforced.
Remaining polish (queue position — blocked on a GpuCoordinator emit, card thumbnails, delete confirm) is split out to the follow-up ticket just filed so this phase ticket can reflect reality. Closing.
All three delivery PRs are merged to `master`: #112 (composable component set under Tools + polling progress), #113 (SignalR progress source with fallback), #115 (viewer skeleton overlay + animation playback, verified against real P4 rigged/animated GLBs). Acceptance is met end-to-end on the local stack: submit → live stage updates → orbit the textured model → toggle skeleton → play the walk clip → download the GLB, en+es throughout, ownership enforced.
Remaining polish (queue position — blocked on a GpuCoordinator emit, card thumbnails, delete confirm) is split out to the follow-up ticket just filed so this phase ticket can reflect reality. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Sub-ticket of epic #346. Depends on #347 (API contracts); demo-able end-to-end once #348 lands. Can start against P1 endpoints in parallel with P2–P4.
What: the student-facing Art Studio on learn.spikersoft.com — a new feature library presenting the pipeline as a guided journey (concept → model → texture → rig → animate → export) so the educational structure of a real 3D pipeline is the UI, not hidden behind it.
Scope:
libraries/features/art-studiolib copying thetrellis-3d-generatorstructure (project.jsontagslayer:feature, barrelsrc/index.ts,tsconfig.base.jsonpath alias@spikersoft/feature-art-studio); signals-in-root-service state (pattern:threed-generator.service.ts)projects/spikersoft/src/routes.tsbehind[AuthGuard](students + staff); staff-only affordances viahasAnyRole(...)fromrole.guard.tsFormDatamultipart, reusebook-uploadpatterns), model/preset choices kept simple for studentsaccessTokenFactory+skipNegotiationpattern fromsystem-notification.service.ts), including queue position / "waiting for GPU" state — single shared card means honest waiting UXNote: the existing
trellis-3d-generatorroute should redirect into the studio (or be absorbed) once parity is reached — decide here, don't leave two 3D entry points.Acceptance: a student submits a prompt, watches stages advance live with queue position shown, orbits the textured model, toggles the skeleton, plays the walk preset, and downloads the GLB — all in both languages; another student's assets are never visible.
Frontend direction from Joey (2026-07-04): Angular-native composable components — no monolithic page. The studio lives under the Tools section alongside the other dev tools, built as a series of small standalone components in the spirit of ProArt's own decomposition (asset types → stage pipeline → per-stage artifacts → library), composed by a thin shell:
art-prompt-composer— asset type + prompt/drawing submissionart-stage-timeline— the pipeline as a visible, honest sequence (queue position, per-stage state) — the educational spine of the UIart-asset-viewer— three.js GLB orbit view; skeleton toggle + clip playback arrive with P4 stagesart-artifact-panel— per-stage outputs (concept image, texture maps, previews)art-asset-card/art-asset-library— my-assets grid with status chips + actionsart-studio-shell— routed page composing the above; each piece independently reusable (e.g. the viewer alone can be embedded in gallery #353 or game playgrounds)Each component standalone, signals-based, individually exportable from
@spikersoft/feature-art-studioso P7 (gallery, games handoff) and the playground shell can reuse them without dragging in the whole studio.Implementation starting against the PR spikersoft-backend#61 API contract; live progress remains polling-abstracted until #349's SignalR events exist.
First slice up: spikersoft-angular PR #112 — the full composable component set (
art-prompt-composer,art-stage-timeline,art-asset-viewer,art-artifact-panel,art-asset-card/art-asset-library,art-studio-shell), registered under/tools(tools outlet + tools-shell entry, palette icon), signals service against the merged P1 API, polling progress behind theART_ASSET_PROGRESS_SOURCEtoken for #349's SignalR swap, en+es i18n. Locally verified: lib build/lint, 21/21 vitest, full app dev build.Ticket stays open for the later slices: SignalR source (#349), viewer skeleton/animation modes (needs P4 stages), quota display (needs #352), real thumbnails, delete confirmation.
SignalR live-progress slice up for merge: backend PR #63 (worker publishes
art.asset.stage.*/asset lifecycle events; API relay toNotificationsHubgroupuser-{owner}, mirroring the existing Trellis3D mechanism) + Angular PR #113 (SignalRArtAssetProgressSourcebehind the existing token, automatic polling fallback, zero component changes). 157/157 backend + 28/28 frontend tests locally.Deferred with rationale: queue-position — the GpuCoordinator lease
AcquireAsyncblocks with no queue index exposed, so honest queue position needs the coordinator to emit it; suggest a small follow-up ticket on GpuCoordinator rather than faking it worker-side. The timeline'squeuePositioninput stays plumbed and unfed until then.All three delivery PRs are merged to
master: #112 (composable component set under Tools + polling progress), #113 (SignalR progress source with fallback), #115 (viewer skeleton overlay + animation playback, verified against real P4 rigged/animated GLBs). Acceptance is met end-to-end on the local stack: submit → live stage updates → orbit the textured model → toggle skeleton → play the walk clip → download the GLB, en+es throughout, ownership enforced.Remaining polish (queue position — blocked on a GpuCoordinator emit, card thumbnails, delete confirm) is split out to the follow-up ticket just filed so this phase ticket can reflect reality. Closing.