Local Development#

Warning

Project Neo is currently in Technical Preview. Features described in this section may change before general availability.

This page explains how the development environment works, covering the two-server architecture, live reload, environment variables, and common workflows.

How the Dev Server Works#

Running nextgen dev starts two processes in parallel.

Dev Proxy (Port 5555)#

The proxy is a lightweight Node.js server that does three things:

  1. Serves the pre-built host application

    The core Project Neo application (chat, search, collections) is already bundled inside @squirro/nextgen-core. The proxy serves it as static files.

    Note

    The host application version is tied to your installed version of @squirro/nextgen-core. To avoid unexpected behavior, make sure that version matches the Project Neo version running on your target Squirro instance. Run npm list @squirro/nextgen-core to check your installed version.

  2. Mocks authentication

    You do not need to log in. The proxy always reports the session as authenticated and injects your refresh token (from .env) into outgoing API requests as a valid access token. That token carries the full permissions of the account it belongs to. To test permission-restricted scenarios, use a real Squirro instance with an account that has the appropriate role.

  3. Proxies Squirro API calls

    Requests to /api/*, /v0/*, /service/*, /studio/*, and /storage/* are forwarded to your Squirro instance with authentication headers injected automatically.

Warning

The dev proxy bypasses authentication entirely. Do not expose port 5555 to untrusted networks. Run it on localhost only. If you are working in a cloud development environment or on shared Wi-Fi, make sure the port is not publicly reachable.

Extension Dev Server (Port 3001)#

Rsbuild compiles your extension code and serves it via Module Federation. The host loads your extension manifest from http://localhost:3001/mf-manifest.json and your dashboard components from the chunks served on port 3001.

Live Reload#

The dev proxy watches your src/ directory. When any file changes:

  1. The proxy detects the change within approximately 300ms.

  2. It sends a reload signal to the browser via a Server-Sent Events connection.

  3. The browser performs a full page reload.

  4. The host fetches the latest extension chunks from the dev server.

Each change triggers a full page reload, not hot module replacement. That choice is intentional. Module Federation and HMR do not combine reliably. Reloads are fast because the host application is pre-built and served from a local file cache.

Environment Variables#

All configuration lives in .env at the project root. Edit it with nextgen config or open the file directly.

Variable

Default

Required

Description

SQUIRRO_API_URL

None

Yes

Your Squirro instance URL, for example https://your-instance.example.com.

SQUIRRO_TOKEN

None

Yes

Refresh token from your Squirro profile.

EXTENSION_PORT

3001

No

Port for the extension dev server.

DEV_PROXY_PORT

5555

No

Port for the dev proxy. Open this port in your browser.

VITE_PROJECT_ID

demo-project

No

Default project ID used by the standalone preview at port 3001. It is not used by the full host at port 5555, which derives the project ID from the URL.

Updating Credentials#

nextgen config

Select API credentials from the menu. The CLI validates the new token before saving.

If your token expires during a development session, nextgen dev will begin returning 401 errors from the API. Run nextgen config to refresh the token, then restart the dev server.

Checking Your Extension Is Running#

Open http://localhost:3001/mf-manifest.json in a browser tab. If you see JSON like this, the extension server is running correctly:

{
  "id": "my_dashboards",
  "name": "my_dashboards",
  "exposes": {
    "./manifest": "./src/manifest.ts"
  }
}

If that URL returns an error or times out, the extension dev server is not running. Restart nextgen dev.

Running the Dev Server for a Specific Project#

By default, the standalone preview at port 3001 uses a placeholder project ID. To develop against a real Squirro project, set VITE_PROJECT_ID in .env:

VITE_PROJECT_ID=your-actual-project-id

This value is used only by the standalone preview at port 3001. The full host at port 5555 derives the project ID from the URL and ignores VITE_PROJECT_ID. The project ID is passed to your dashboard components as the projectId prop, and your API calls target the real project.

Finding Your Project ID#

The project ID appears in the URL after /neo/ when you navigate to any page inside a project in Project Neo. Open your Squirro instance in a browser, select a project, and read the ID from the address bar:

https://your-instance.example.com/neo/<project-id>/chat
                                      ^^^^^^^^^^^^

Copy that value and paste it into VITE_PROJECT_ID in your .env file.

Port Conflicts#

If either port is already in use when you run nextgen dev, the command exits immediately:

✗ Extension port 3001 is already in use.
  Set a different port in .env (EXTENSION_PORT=<port>) or run `nextgen config`.

To find the process using a port (macOS and Linux):

lsof -i :3001

To stop it if safe to do so:

kill $(lsof -ti :3001)

To change the port in .env instead:

nextgen config

Running Multiple Extension Projects#

Each project uses two ports. To run two extension projects at the same time:

  1. Change EXTENSION_PORT and DEV_PROXY_PORT to unused port numbers in the second project .env.

  2. Run nextgen dev in both project directories.

Each dev proxy serves an independent host instance, so you can work on multiple extensions without conflicts.

Typical Development Workflow#

# 1. Start everything
nextgen dev

# 2. In a second terminal, add a dashboard
nextgen create dashboard MyNewDashboard

# 3. Open http://localhost:5555 in your browser
#    Navigate to the new dashboard in the sidebar

# 4. Edit src/dashboards/MyNewDashboard.tsx and save
#    The browser reloads to show your changes

# 5. Check types
npx tsc --noEmit

# 6. Lint and format
npm run lint
npm run format

Debugging#

Source Maps#

nextgen dev generates source maps automatically. When an error occurs in your dashboard, the browser DevTools Sources panel and stack traces point to the original TypeScript file and line number, not the compiled output. Source maps are not generated by nextgen build, so production bundles show minified code only.

React DevTools#

The React DevTools browser extension works with extension dashboards. Extensions share the host React instance, so the component tree in DevTools includes both host components and your dashboard components together.

Name your components explicitly so they appear with readable labels:

// Avoid — shows as "Anonymous" in DevTools
export default ({ projectId }: Props) => <div></div>;

// Prefer — shows as "Analytics" in DevTools
export default function Analytics({ projectId }: Props) {
  return <div></div>;
}

Network Tab#

To inspect which extension files the host loaded, open the DevTools Network tab while running nextgen dev:

  • Filter by 3001 to isolate extension requests.

  • On first page load, look for mf-manifest.json. A 200 response confirms the extension server is reachable.

  • On first navigation to a dashboard, look for a [hash].js request from localhost:3001. That is the dashboard chunk loading on demand.

In production, the same requests come from the Squirro backend. Filter by ui_bundles to find them:

/v0/workspaces/<domain>/ui_bundles/<project-name>/dist/mf-manifest.json
/v0/workspaces/<domain>/ui_bundles/<project-name>/dist/[hash].js

A 404 on mf-manifest.json means the bundle was not uploaded or the project configuration does not point to the correct bundle name.

Extension Load Errors#

When the host fails to load an extension, it logs a structured message to the browser console with the [extensions] prefix:

[extensions] ════════════════════════════════════════════════════════════
  ✖  BUNDLE LOAD FAILED
  /v0/workspaces/<domain>/ui_bundles/<project-name>/dist/mf-manifest.json
  ...error message...
[extensions] ════════════════════════════════════════════════════════════

Open the Console tab and filter by [extensions] to catch these without noise from other sources.

React Query DevTools#

To inspect query state, cached data, and request timing, add the React Query DevTools panel to a dashboard component. Install the package first:

npm install --save-dev @tanstack/react-query-devtools

Then add it to the component:

import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

export default function Analytics({ projectId }: { projectId: string }) {
  return (
    <>
      {/* your dashboard content */}
      <ReactQueryDevtools initialIsOpen={false} />
    </>
  );
}

The panel appears as a floating button in the bottom corner of the page. Remove the import before deploying to production.