GeoLibre npm Workspaces Monorepo Structure: Apps, Packages, and Workers Explained

The GeoLibre repository uses an npm workspaces monorepo with three workspace globs—apps/*, packages/*, and workers/*—to organize a React desktop app, reusable UI libraries, and Cloudflare Workers under a single dependency tree.

The opengeos/GeoLibre project is organized as a single npm-workspaces monorepo, enabling code sharing between a React-based desktop application, shared component libraries, and serverless edge workers. This structure eliminates version mismatches and allows cross-package imports without publishing to npm.

How the Workspace Globs Are Defined

The top-level package.json declares three workspace patterns that partition the codebase by responsibility:

{
  "workspaces": [
    "apps/*",
    "packages/*",
    "workers/*"
  ]
}

Source: [package.json](https://github.com/opengeos/GeoLibre/blob/main/package.json)

Running npm install from the repository root installs dependencies for all workspaces simultaneously, creating symlinks that let each workspace import from others as if they were published packages.

The apps/* Workspace: End-User Applications

The apps/* directory contains the primary user-facing application. Currently, this houses a single multi-target React app.

apps/geolibre-desktop

apps/geolibre-desktop is a React + Vite project compiling to three distinct targets:

Target Build Command Output Location
Web (browser) npm run build apps/geolibre-desktop/dist/
Desktop (Tauri) npm run tauri:build apps/geolibre-desktop/src-tauri/
Jupyter (embed) npm run build:embed Bundled into Python package

The main entry point is [apps/geolibre-desktop/src/main.tsx](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/main.tsx).

The packages/* Workspace: Shared Libraries

Reusable code lives under packages/* as versioned workspace packages. These are imported using scoped names like @geolibre/ui.

Package Purpose Key File
@geolibre/ui UI primitives (buttons, dialogs, tables) packages/ui/src/components/button.tsx
@geolibre/plugins Extensible plugin system for map layers packages/plugins/src/plugins/maplibre-vector.ts
@geolibre/processing Client-side algorithms & Whitebox tool catalog packages/processing/src/...
@geolibre/core (planned) Zustand store, types, .geolibre.json schema —

Because these are workspace packages, the app imports them directly:

import { Button } from '@geolibre/ui';

export function MyToolbar() {
  return <Button onClick={() => console.log('clicked')}>Launch</Button>;
}

Plugin registration follows the same pattern:

import { registerPlugin } from '@geolibre/plugins';

registerPlugin('maplibre-vector', {
  source: () => import('@geolibre/plugins/src/plugins/maplibre-vector')
});

The workers/* Workspace: Cloudflare Edge Services

The workers/* directory houses Cloudflare Workers that run background services at the edge. Each worker is its own workspace with independent TypeScript and Wrangler configurations.

Worker Role
viewer Serves map-viewer assets and proxies vector data requests
ai-proxy Lightweight AI endpoint for chat-like assistance

Each worker maintains its own toolchain:

How the npm Workspaces Monorepo Fits Together

  1. Single dependency installation — npm install at the repository root resolves and links all workspace dependencies.
  2. Cross-package imports — Workspace packages reference each other by name (@geolibre/ui, @geolibre/plugins) without npm publishing.
  3. Unified command interface — Top-level scripts delegate to workspace-specific scripts using npm run <script> -w <workspace>.

Common Development Workflows

Install everything once:

npm install

Start the web dev server (runs geolibre-desktop in browser mode):

npm run dev

# Equivalent to: npm run dev -w geolibre-desktop

Build the desktop installer:

npm run tauri:build

Run a worker locally:

cd workers/viewer
npm run dev    # Uses wrangler dev under the hood

Run the full CI pipeline:

npm run ci    # Builds app, runs tests, type-checks workers, checks Rust crate

Key Benefits of This Structure

  • Code reuse — UI components, plugins, and processing tools are shared across web, desktop, and worker contexts
  • Consistent type safety — All workspaces inherit from the same TypeScript configuration hierarchy
  • Simplified CI/CD — Single pipeline builds, tests, and validates the entire stack including the Rust Tauri backend

Summary

  • GeoLibre uses npm workspaces with three globs: apps/*, packages/*, and workers/*
  • apps/geolibre-desktop is the sole UI application, building to web, desktop (Tauri), and Jupyter embed targets
  • packages/* contains reusable libraries (@geolibre/ui, @geolibre/plugins, @geolibre/processing) imported via workspace resolution
  • workers/* houses Cloudflare Workers (viewer, ai-proxy) with independent deployment configs
  • Cross-package imports use scoped package names without npm publishing
  • A single npm install and unified scripts keep the developer experience simple

Frequently Asked Questions

What is an npm workspaces monorepo?

An npm workspaces monorepo is a single repository containing multiple Node.js packages that share a common node_modules directory and dependency tree. The root package.json declares workspace globs, and npm automatically creates symlinks between workspaces so they can import each other by package name. GeoLibre uses this to coordinate its app, libraries, and workers under one dependency management system.

How do packages in packages/* get imported by the app?

Packages in packages/* are declared as workspaces with their own package.json files and scoped names like @geolibre/ui. When npm install runs, npm creates symlinks in the root node_modules pointing to each workspace. The app then imports them using standard ES module syntax: import { Button } from '@geolibre/ui'. No npm publishing is required for internal workspace dependencies.

Why separate workers into their own workspace?

Cloudflare Workers require distinct Wrangler configurations, TypeScript compiler settings, and deployment targets compared to browser or Node.js code. Isolating them in workers/* lets each worker define its own wrangler.jsonc, tsconfig.json, and build pipeline while still sharing utilities from packages/* via workspace imports. This separation prevents worker-specific tooling from leaking into the main application build.

Can I add new packages or workers to the monorepo?

Yes. Create a new directory under apps/, packages/, or workers/ with a valid package.json including a name field. The package automatically becomes available as a workspace. For packages intended for cross-workspace import, use the @geolibre/ scope for consistency. Run npm install after adding any workspace to regenerate symlinks.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →