Files
roboco/panel
58354a364e [e56e6543] Reorder sidebar, rename A2A, remove Notifications entry, 2-col objectives (#394)
* [11e82f2e] Frontend: sidebar reorder, A2A rename, Notifications removal, 2-col objectives (#393)

* [946802b2] Objectives editor: 2-column desktop grid, 1-column mobile (#385)

* [946802b2] feat(goals-tab): objectives editor 2-col grid on desktop, 1-col mobile

* [946802b2] docs(goals-tab): document ObjectivesEditor responsive grid layout

Added comprehensive JSDoc comment explaining the 2-column desktop / 1-column mobile responsive grid layout for objective cards. Documents the grid-cols-1 / md:grid-cols-2 classes, the gap spacing, and clarifies that the '+ Add objective' button sits as a full-width sibling below the grid rather than as a grid item. Includes a visual layout structure for future reference.

---------

Co-authored-by: Frontend Developer 2 <fe-dev-2@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>

* [639c0d54] Sidebar: reorder + dividers + A2A rename + remove Notifications (#389)

* [639c0d54] feat(panel): sidebar dividers, A2A rename, remove Notifications entry

Group navItems into six sections rendered with a visible Separator
between each group in SidebarNav (shared by desktop + mobile Sheet),
rename the /a2a entry from "A2A Live" to "A2A", and drop the
Notifications entry from the sidebar (/notifications stays reachable
via the header's NotificationBell). Adds sidebar.test.tsx covering
group dividers, the rename, the removed entry, item order, and the
collapsed icon-only state.

* [639c0d54] docs(sidebar): add navigation structure and grouping documentation

Document the six-group sidebar organization with dividers, the A2A rename
from "A2A Live", and the removal of Notifications from the sidebar. Covers
visual behavior across desktop expanded/collapsed and mobile states,
data structure rationale, and testing. Explains that Notifications remains
accessible via the header NotificationBell.

---------

Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>

---------

Co-authored-by: Frontend Developer 2 <fe-dev-2@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>
Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>

* [92a46054] Fix sidebar: exact flat order + move Business to footer (#415)

* [11a612e2] Flatten sidebar nav order + move Business to footer (#413)

* [11a612e2] fix(panel): flatten sidebar navItems + move Business to footer

* [11a612e2] docs(sidebar): update navigation structure documentation for flat navItems + Business in footer

---------

Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>

* [dc518639] revert(business): drop out-of-scope 2-col objectives grid from PR #415 (#418)

Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>

---------

Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>

* [e2b50b06] Re-implement 2-column objectives grid in goals-tab.tsx (#435)

Branch rebuilt from the root fork point so the assembled delta against
master contains ONLY this task's work: the responsive objectives grid
(grid-cols-1 md:grid-cols-2) and its test. The prior branch inherited the
root's sidebar work into the against-master view, which the PR gate
correctly flagged as an AC4 violation.

Co-authored-by: Renn F <rennf93@users.noreply.github.com>

---------

Co-authored-by: Frontend Developer 2 <fe-dev-2@roboco.tech>
Co-authored-by: Frontend Documenter <fe-doc@roboco.tech>
Co-authored-by: Frontend Developer 1 <fe-dev-1@roboco.tech>
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-11 07:42:37 +02:00
..
2026-07-02 15:36:49 +02:00
2026-04-20 15:10:54 +02:00
2026-06-29 05:38:21 +02:00
2026-07-10 10:25:21 +02:00
2026-05-09 03:15:09 +02:00

RoboCo Control Panel

Next.js 16 control panel for the RoboCo AI agent system. Formerly a separate repository (rennf93/roboco-panel), now vendored under panel/ in this monorepo so docker compose up -d brings up the whole stack from one place.

Stack

  • Next.js 16 (App Router, standalone output)
  • TypeScript
  • Tailwind CSS
  • Radix UI primitives
  • dnd-kit for drag/drop (kanban)
  • pnpm for package management

Running in production (the normal path)

Use the root-level Docker Compose:

# from the repo root (one level up from this directory)
docker compose up -d

The panel is built as part of the compose stack via docker/panel.Dockerfile and served internally on port 3000. Nginx (also in the compose stack) is the single externally-exposed service on http://localhost:3000 and routes:

  • /api/* and /ws/* → orchestrator (FastAPI, port 8000)
  • everything else → the Next.js panel

The panel uses relative URLs (/api/v1, /ws) so nothing here needs a backend URL in .env.

Running the panel alone for UI development

cd panel
pnpm install
pnpm dev

That gives you Next dev-server on localhost:3000, but you still need the orchestrator reachable at localhost:8000 (or via nginx) for API calls to work. Easiest: docker compose up -d the backend services, then run pnpm dev against that.

Build scripts

  • pnpm dev — development server with hot reload
  • pnpm build — production build (outputs .next/standalone/)
  • pnpm start — run the standalone build
  • pnpm lint — ESLint

Where things live

  • src/app/ — Next.js App Router pages
  • src/components/ — React components (organized by feature: tasks, agents, channels, …)
  • src/lib/api/ — typed API client (thin wrappers over fetch)
  • src/lib/ — constants, utilities, WebSocket hooks
  • src/types/ — shared TypeScript types mirroring backend schemas
  • src/hooks/ — reusable React hooks (see Frontend hooks)

Hooks

The panel exposes public hooks under @/hooks. See Frontend hooks for full API reference and examples.

usePageRefresh

Page-scoped refresh coordinator. Pages register data-refetch callbacks; the navbar refresh button in src/components/layout/header.tsx calls refresh() and reflects the combined loading/disabled state. The button is disabled when no callbacks are registered (the registry is empty) and while a refresh is in progress.

import { usePageRefresh } from "@/hooks";

const { register, unregister, refresh, loading, disabled } = usePageRefresh();
  • disabled is true when no callbacks are registered (there is nothing to refresh)
  • disabled becomes false once a callback is registered
  • disabled returns to true when all callbacks are unregistered

Wrap your page or layout in PageRefreshProvider from @/components/providers before consuming the hook. Dashboard pages should register their refetch callbacks and avoid adding inline "Refresh" buttons; see docs/frontend/components/page-refresh-provider.md for the full wiring list and examples.

Dependency Management

Version Alignment

When bumping Next.js, always update eslint-config-next to match the same version. These packages must stay in sync. See UPGRADE.md for detailed procedures and troubleshooting.

Backend schema changes

When the backend changes response shapes, mirror them in src/types/ and the relevant src/lib/api/ module. Keep API paths relative so nginx routing keeps working.