Skip to main content

Monorepo layout

genie/ is a pnpm workspace (pnpm@9.15.4). pnpm-workspace.yaml includes apps/*, infra/* and packages/*. Workspace packages are consumed as TypeScript or JavaScript source through file: or workspace: dependencies; there is no separate library build step.

Workspace layout​

PathPackage namePurposeKey files
apps/standalonestandaloneThe Genie frontend: Vite + React 19 + React Router 7. Used by the local web app, the desktop renderer and the cloud web build.vite.config.ts, src/App.tsx (routes), src/app/lib/appConfig.ts, src/app/GenomeBrowserPanel.tsx, src/app/projects/[projectId]/ProjectWorkspaceScreen.tsx, src/app/projects/[projectId]/agentModes/*.ts, src/app/lib/eg3TrackMapping.ts, public/genie-runtime-config.js
apps/backendgenie-backendLocal backend host. A thin wrapper that resolves options from the environment and starts @genie/backend-core.server.js, localServer.js (createLocalBackendOptions, startLocalBackend), integration-server.js
apps/desktopgenie-desktopElectron 35 desktop app. Starts the backend in-process and loads the renderer from it.src/bootstrap.cjs, src/main.js, src/preload.cjs, scripts/prepare-backend-resources.mjs
apps/genome-track-demogenome-track-demoVite demo of the native GenomeBrowser with the standard tracks.src/App.tsx, src/scenarios.ts
apps/docsgenie-docsThis documentation site (Docusaurus).docusaurus.config.ts, sidebars.ts, docs/, tests/
packages/backend-core@genie/backend-coreHTTP server, WebSocket /ws, Codex app-server bridge, tool handlers, storage.src/server.js, src/assetCatalog.js, src/analysisState.js, src/genome/{toolHandlers,regionData,browserState,pluginCompiler}.js
packages/chat-core@genie/chat-coreChat types, ChatStore, ChatSession.src/types.ts, src/store.ts, src/session.ts
packages/chat-ui@genie/chat-uiChatView React component with Markdown rendering and citation chips.src/ChatView.tsx
packages/codex-runtime@genie/codex-runtimeBrowser-side WebSocket transport to the backend.src/client/webSocketTransport.ts, src/types.ts
packages/genome-browser@genie/genome-browserNative GenomeBrowser, TrackConfig, TrackRegistry, standard track registrations, shared track types.src/GenomeBrowser.tsx, src/TrackConfig.ts, src/TrackRegistry.ts, src/types.ts, src/standard/*
packages/genome-track-container@genie/genome-track-containerRegion and navigation models, viewport with pan and zoom, prefetch logic.src/model/*.ts, src/GenomeTrackViewport.tsx, src/pan/prefetch.ts
packages/genome-tracks-standard@genie/genome-tracks-standardSVG track renderers, data sources (bigWig, bigBed, tabix, gene API), genome helpers, StandardTrackContainer.src/StandardTrackContainer.tsx, src/render/*, src/sources/*, src/genomes/*, src/egreact/trackTypes.ts
packages/genome-catalog@genie/genome-catalogGenerated genome assembly catalog (plain JavaScript with type declarations).src/index.js, src/index.d.ts, src/generatedCatalog.js, scripts/generate-from-egreact.mjs
infra/aws-cdk@genie/aws-cdkCDK app for the cloud web build and project API.bin/genie-cloud.ts, lib/genie-cloud-stack.ts, lambda/api/index.mjs
vendor/eg3@eg3/tracks, @eg3/adapterPre-built eg3 engine and adapter. Do not edit.README.md, wuepgg3-track/, eg-adapter/dist/
ref/Reference notes.codex-app-server.md, standalone-action-menu-system.md
scripts/Workspace scripts.dev-web-cloud.mjs, build-igvf-genome-bundle.mjs, igvf-genome-bundle.entry.ts, igvf-genome-bundle.d.ts
session-data/Runtime data written by the local backend. Not source.projects.json, sessions.json, projects/<projectId>/...

apps/standalone still contains some names from an earlier Next.js setup ("use client" directives, [projectId] folder names, the NEXT_PUBLIC_ variable prefix and the .next-desktop output folder). They are plain Vite code now.

@genie/genome-browser​

The native browser stack. In the project workspace, Genie renders with eg3 and uses this package only for types (TrackModel, TrackInspectorSnapshot, TrackMenuComponent) and the re-exported region models. The full component is used by the public landing browser in static builds, the developer pages, the demo app and the IGVF bundle.

Exports:

ExportKindNotes
GenomeBrowserReact componentProps include registry, tracks, viewRegion, onViewRegionChange(start, end), legendWidth, interactionMode ("pan", "zoom", "highlight"), browserRef, widthPx, heightPx and feature, inspector and context-menu callbacks
GenomeBrowserHandleTypeexportImage(options?) resolves to { blob, width, height, pixelRatio }, where blob is a PNG image
TrackConfigAbstract classOne instance per track; defines data source, renderer and fetch rules
TrackRegistryClassMaps a lower-cased track type to a TrackConfig constructor
DataSourceInterfacegetData(dataRegion, basesPerPixel, options, signal), optional getMeta, getLastRequestInfo, cleanUp
registerStandardTracks(registry)FunctionRegisters the built-in track types
TrackModel, TrackComponent, TrackComponentProps, inspector, feature and menu typesTypes
ChromosomeInterval, DisplayedRegionModel, Feature, NavigationContext, OpenInterval, RegionExpanderRe-exportsFrom @genie/genome-track-container

TrackConfig methods​

MethodDefaultPurpose
initDataSource()nullCreate the track's DataSource. Kept for the life of the track unless shouldRecreateDataSource(prev, next) returns true.
getComponent()AbstractThe React component that draws the track
formatData(raw)IdentityTurn the data source payload into renderer data
getInitialData()nullData shown before the first fetch
getDefaultHeightPx()nullHeight when the track has no heightPx (the browser falls back to 60 px)
usesDefaultFrame()trueWrap the renderer in the standard frame (label, loading badge, error band, pan transforms)
getMenuComponents()[]Track-specific context-menu components
shouldFetch(prev, next)Region or JSON changeRefetch when start, end or bases per pixel change, or when options or config change
trackNeedsFetch()trueReturn false for tracks without data (such as the ruler)

TrackRegistry.createTrackConfig(track) looks up track.type, or track.filetype if type is empty, and throws Unknown track type: <type> when nothing is registered.

Example: a custom track type​

This example registers a gcbins track that fetches binned values from a JSON endpoint and draws them as bars. It uses the same coordinate conversion as the standard renderers: genome intervals are converted to navigation-context coordinates, then to pixels with the drawing model.

import {
ChromosomeInterval,
GenomeBrowser,
TrackConfig,
TrackRegistry,
registerStandardTracks,
type DataSource,
type DisplayedRegionModel,
type TrackComponentProps,
type TrackModel,
} from "@genie/genome-browser";
import { makeGenomeDefaultViewRegion } from "@genie/genome-tracks-standard";
import { useState, type ReactElement } from "react";

type GcBin = { chr: string; start: number; end: number; value: number };
type GcOptions = { color?: string };

class GcBinsSource implements DataSource<GcOptions, GcBin[]> {
constructor(private readonly endpoint: string) {}

async getData(
dataRegion: DisplayedRegionModel,
basesPerPixel: number,
_options: GcOptions | undefined,
signal?: AbortSignal,
): Promise<GcBin[]> {
const bins: GcBin[] = [];
for (const locus of dataRegion.getGenomeIntervals()) {
const params = new URLSearchParams({
chr: locus.chr,
start: String(locus.start),
end: String(locus.end),
bpp: String(basesPerPixel),
});
const response = await fetch(`${this.endpoint}?${params.toString()}`, { signal });
if (!response.ok) {
throw new Error(`GC request failed with status ${response.status}`);
}
bins.push(...((await response.json()) as GcBin[]));
}
return bins;
}
}

function GcBinsTrack(props: TrackComponentProps<GcBin[], GcOptions>): ReactElement {
const { data, drawModel, heightPx, track } = props;
const navContext = drawModel.getViewRegion().getNavigationContext();
const color: string = track.options?.color ?? "#0000FF";
const maxValue: number = Math.max(1, ...(data ?? []).map((bin: GcBin) => bin.value));

return (
<svg width={drawModel.getDrawWidth()} height={heightPx}>
{(data ?? []).flatMap((bin: GcBin, index: number) =>
navContext
.convertGenomeIntervalToBases(new ChromosomeInterval(bin.chr, bin.start, bin.end))
.map((span, spanIndex: number) => {
const xSpan = drawModel.baseSpanToXSpan(span);
const barHeight: number = (bin.value / maxValue) * heightPx;
return (
<rect
key={`${index}-${spanIndex}`}
x={xSpan.start}
y={heightPx - barHeight}
width={Math.max(1, xSpan.end - xSpan.start)}
height={barHeight}
fill={color}
/>
);
}),
)}
</svg>
);
}

class GcBinsTrackConfig extends TrackConfig<GcOptions, unknown, GcBin[], GcBin[]> {
initDataSource(): DataSource<GcOptions, GcBin[]> {
const endpoint: string | undefined = this.track.url;
if (!endpoint) {
throw new Error("gcbins track requires a url");
}
return new GcBinsSource(endpoint);
}

getComponent() {
return GcBinsTrack;
}

getInitialData(): GcBin[] {
return [];
}

getDefaultHeightPx(): number | null {
return 50;
}

shouldRecreateDataSource(prev: TrackModel<GcOptions>, next: TrackModel<GcOptions>): boolean {
return prev.url !== next.url;
}
}

const registry = new TrackRegistry();
registerStandardTracks(registry);
registry.registerTrackType("gcbins", GcBinsTrackConfig);

const tracks: TrackModel[] = [
{ id: "ruler", type: "ruler", name: "Ruler" },
{ id: "gc", type: "gcbins", name: "GC content", url: "https://example.org/api/gc", options: { color: "#6501A8" } },
];

export function GcDemo(): ReactElement {
const [viewRegion, setViewRegion] = useState<DisplayedRegionModel>(() => makeGenomeDefaultViewRegion("hg38"));
return (
<GenomeBrowser
registry={registry}
tracks={tracks}
viewRegion={viewRegion}
onViewRegionChange={(start: number, end: number) => setViewRegion(viewRegion.clone().setRegion(start, end))}
legendWidth={120}
/>
);
}
note

Custom track types registered this way work in the native stack only. The project workspace renders with eg3, which accepts its own fixed list of track types (see Browser engine). The agent's custom track tools are disabled for the same reason.

@genie/genome-track-container​

Region and viewport primitives, adapted from the eg-react models.

ExportWhat it does
NavigationContextJoins features (usually chromosomes) end to end into one coordinate space. parse(str) accepts an exact feature name (returns a 6 bp window at its centre) or anything ChromosomeInterval.parse accepts. convertGenomeIntervalToBases(interval) maps chromosome coordinates to context coordinates.
DisplayedRegionModelThe visible window [start, end) in context coordinates. setRegion (clamped), pan, panLeft, panRight (one window), zoom(factor, focalPoint = 0.5), getGenomeIntervals(), currentRegionAsString() (1-based start: a region stored 0-based as chr7:27053396-27373765 prints as chr7:27053397-27373765).
ChromosomeIntervalA chr, start, end interval. ChromosomeInterval.parse strips commas and matches chr, start and end separated by any non-word characters. If the string contains :, the start is treated as 1-based and converted to 0-based. chr7:27,053,397-27,373,765 and chr7 27053396 27373765 give the same interval.
RegionExpanderExpands the visible window so off-screen data is fetched (default 2 window widths on each side).
LinearDrawingModelBase-to-pixel conversion for a region and a drawing width.
GenomeTrackViewport, GenomeTrackContainerViewport with pan, zoom and highlight modes; resize-aware wrapper.
computeNextTargetWindowPan prefetch logic.

@genie/genome-tracks-standard​

ExportWhat it does
StandardTrackContainerA self-contained browser for ruler, gene annotation, bigWig, bedGraph, bigBed, RepeatMasker, BED and a few annotation types. Used by the public landing browser.
BigWigSource, BigBedSource, TabixSourceData sources built on @gmod/bbi and @gmod/tabix
fetchGeneAnnotations, fetchGeneNameMatches, GENE_ANNOTATION_API_DEFAULTGene annotation API client (https://lambda.epigenomegateway.org/v3)
makeGenomeNavContext, makeGenomeDefaultViewRegion, getGenomeDefaultTracks, getGenomePublicHubManifestGenome helpers built on the catalog
EG_REACT_TRACK_TYPES, isEgReactTrackType, normalizeEgReactTrackTypeThe eg-react track type list used by the UI
RulerTrackBody, GeneAnnotationTrackBody, BigWigTrackBody, BigBedTrackBody, RepeatMaskerTrackBody, StandardTrackFrameSVG renderers and the standard frame

@genie/genome-catalog​

A generated catalog of genome assemblies used by the frontend and the backend. It exports DEFAULT_GENOME_ID ("hg38"), allGenomeIds, genomeCatalog, treeOfLife, isKnownGenomeId, normalizeGenomeId, getGenomeCatalogEntry, getGenomeDisplayName (for example "human (hg38)"), getGenomeSummaries, cloneDefaultTracksForGenome and clonePublicHubManifestForGenome.

The raw catalog holds 60 assemblies. The genome picker shows only the 57 that eg3 supports (see Genome assemblies).

src/generatedCatalog.js is generated from eg-react's allGenomes.ts. To regenerate it, point the generator at an eg-react frontend folder:

EG_REACT_FRONTEND_ROOT=/path/to/eg-react/frontend pnpm --filter @genie/genome-catalog generate

Without the variable, the script looks for ../../eg-react-master/frontend relative to the genie/ folder.

Chat packages​

PackageExports
@genie/chat-coreTypes (ChatMessage, ChatCitation, ChatToolDefinition, ChatToolCall, ChatEvent, ChatTransport, ChatState, ...), ChatStore, ChatSession, createChatSession
@genie/chat-uiChatView and ChatViewProps
@genie/codex-runtimeTypes and WebSocketChatTransport (also at the @genie/codex-runtime/client subpath). The transport waits up to 30 seconds for the backend's ready message. Files under src/server/ are older code that the app does not use.

Root scripts​

Run these from genie/.

ScriptWhat it runs
pnpm devVite dev server for standalone (local mode) and the backend, in parallel
pnpm dev:backendThe backend only (node server.js, no file watching)
pnpm dev:webVite in web mode (cloud configuration, assistant off)
pnpm dev:web-cloudgenie-local-cloud with simulated latency plus dev:web
pnpm dev:local-cloudgenie-local-cloud (sibling checkout)
pnpm dev:local-cloud:latencygenie-local-cloud with 800 ms latency and 400 ms jitter
pnpm desktop:devBuild the desktop renderer, prepare backend resources, start Electron
pnpm desktop:packSame build, then electron-builder --dir (unpacked app)
pnpm desktop:distSame build, then macOS dmg and zip (unsigned)
pnpm build, pnpm build:webvite build --mode web to apps/standalone/dist
pnpm build:desktop-rendererDesktop renderer build to apps/standalone/.next-desktop
pnpm cdk:synthcdk synth in infra/aws-cdk
pnpm verify:backend@genie/backend-core tests, then the backend WebSocket smoke test
pnpm lintESLint for standalone
pnpm typechecktsc --noEmit for standalone
pnpm testpnpm -r test across the workspace
pnpm bundle:igvf-genomeBundle the native browser for the IGVF catalog (needs --outdir)
pnpm docs:dev, docs:build, docs:serve, docs:testThis documentation site (see Docs site)

See Testing for what the test scripts cover.