Workspaces
A workspace is the top-level organizational container in Meridian. Each workspace has its own systems, domains, dependency graph, team members, and upload history — completely isolated from other workspaces.
What is a workspace?
Think of a workspace as a project or an organization boundary. When you upload an inventory, resolve dependencies, and visualize a graph, all of that data lives inside a specific workspace. Teams typically create one workspace per platform, product, or business unit.
Each workspace has a unique slug that appears in the URL:/w/my-workspace/graph. All navigation within the app is scoped to the current workspace.
Creating a workspace
Navigate to /workspaces after signing in. Click New workspace. You will be prompted for:
- Name — human-readable display name (e.g., “My Platform”)
- Slug — URL-safe identifier, auto-generated from the name but editable (lowercase letters, numbers, and hyphens only, e.g.,
my-platform) - Description — optional short description shown on the workspace card
After creation you are redirected to /w/[slug]/dashboard and automatically assigned the OWNER role.
Roles & permissions
Every workspace member holds one of three roles. Roles control what actions a member can perform:
| Role | View graph & systems | Upload inventory | Create & edit docs | Manage members | Change settings |
|---|---|---|---|---|---|
OWNER | Yes | Yes | Yes | Yes | Yes |
EDITOR | Yes | Yes | Yes | No | No |
VIEWER | Yes | No | No | No | No |
Navigation & switching workspaces
The top header shows the name of the current workspace. Click it to open a dropdown that lists all workspaces you belong to. Select any workspace to switch to it immediately.
The header navigation bar contains the following pages for each workspace:
- Dashboard — metrics, charts, and recent activity
- Graph — interactive dependency graph
- Systems — searchable list of all registered systems
- Upload — inventory upload (EDITOR and OWNER only)
- Settings — workspace settings and members (EDITOR and OWNER only)
Dashboard
The dashboard is the first page you see when you enter a workspace. It gives you a high-level overview of the health, structure, and recent activity of your platform.
Stat cards
Four metric cards at the top of the dashboard summarize the current state of your workspace at a glance:
| Card | What it shows |
|---|---|
| Domains | Total number of business domains registered in the workspace |
| Systems | Total number of systems (services, workers, jobs, etc.) in the workspace |
| Dependencies | Total number of resolved dependency edges between systems |
| HIGH + CRITICAL Risks | Count of risk entries with severity HIGH or CRITICAL across all systems |
Charts
Two horizontal bar charts show the distribution of your platform at a glance:
- Languages distribution — number of systems per programming language. Helps identify the predominant tech stack and outliers.
- Dependency types — count of resolved edges per dependency type (HTTP, Kafka, shared database, etc.). Shows which integration patterns are most common.
Top connected systems
A ranked table listing the systems with the most dependency connections (inbound + outbound combined). These high-coupling systems are often the most critical nodes in your architecture and deserve special attention when planning changes.
Click any system name to navigate directly to its detail page.
Risks & recent uploads
Two additional tables give you visibility into recent activity:
- Recent risks — the latest 5 risk entries with HIGH or CRITICAL severity. Each row shows the risk title, the system it belongs to, and a color-coded severity badge.
- Recent uploads — the last 5 inventory upload attempts, showing the filename, processing status (
PENDING,PROCESSING,COMPLETED,FAILED), the number of systems affected, and the upload timestamp.
Inventory Upload
Meridian ingests your architecture as structured JSON files called inventories. Each file describes one or more systems — their services, databases, integrations, message topics, packages, and risks. After upload, Meridian automatically resolves dependency edges between systems and updates the graph.
Drag-and-drop upload
Navigate to Upload in the workspace header. The page displays a drop zone where you can drag and drop one or more .json files. You can also click the zone to open a file picker.
After selecting your files, Meridian will:
- Validate the JSON structure against the inventory schema
- Upsert domains and systems (create or update based on slug)
- Replace all nested components (services, databases, integrations, etc.)
- Re-run dependency resolution and update all edges in the graph
- Create an upload record with status
COMPLETEDorFAILED
JSON schema reference
The inventory file must contain a top-level systems array with at least one entry. Each system requires a name and a slug. All other fields are optional but provide richer graph resolution and documentation.
{
"systems": [
{
// Required fields
"name": "string", // Human-readable system name
"slug": "string", // URL-safe identifier: ^[a-z0-9]+(?:-[a-z0-9]+)*$
// Optional metadata
"domainName": "string", // Business domain (e.g., "Payments")
"purpose": "string", // Short description of what this system does
"language": "string", // Primary programming language (e.g., "TypeScript")
"framework": "string", // Framework name (e.g., "NestJS")
"frameworkVersion": "string",
"repositoryUrl": "string", // Valid URL to the source code repository
// Services exposed by the system
"services": [
{
"name": "string", // Required
"slug": "string", // Optional, same pattern as system slug
"type": "API | WORKER | CRONJOB | BACKGROUND_SERVICE", // Required
"port": 3000, // Optional, positive integer
"path": "string" // Optional, e.g., "/api"
}
],
// Databases this system owns or connects to
"databases": [
{
"name": "string", // Required (e.g., "payments_db")
"provider": "string", // Required (e.g., "PostgreSQL", "MongoDB")
"version": "string", // Optional
"orm": "string" // Optional (e.g., "Prisma", "SQLAlchemy")
}
],
// Outbound integrations to other systems
"integrations": [
{
"targetSystem": "string", // Required - target system name or slug
"type": "HTTP_API | DATABASE_DIRECT | GRPC | MESSAGE_QUEUE | EVENT_STREAM | FILE_TRANSFER | SDK | OTHER",
"description": "string" // Optional
}
],
// Message broker topics this system produces or consumes
"messageTopics": [
{
"name": "string", // Required (e.g., "payment.completed")
"role": "PRODUCER | CONSUMER | BOTH", // Required
"broker": "KAFKA | RABBITMQ | SQS | SNS | OTHER", // Required
"metadata": { // Optional
"consumerGroup": "string",
"exchange": "string",
"routingKey": "string",
"dlqEnabled": true,
"retryPolicy": "string"
}
}
],
// External and internal package dependencies
"packages": [
{
"name": "string", // Required (e.g., "stripe")
"version": "string", // Optional (e.g., "^14.0.0")
"type": "INTERNAL | OPEN_SOURCE | TEST" // Optional
}
],
// HTTP API endpoints exposed by the system
"apiEndpoints": [
{
"path": "string", // Required (e.g., "/payments/charge")
"method": "string", // Required (e.g., "POST")
"description": "string" // Optional
}
],
// Known risks and technical debt
"risks": [
{
"title": "string", // Required
"description": "string", // Optional
"severity": "LOW | MEDIUM | HIGH | CRITICAL" // Required
}
]
}
]
}Complete example
The following example shows a complete inventory for a payments service with HTTP and gRPC outbound integrations, Kafka producer topics, a PostgreSQL database, external and internal packages, API endpoints, and two risks:
{
"systems": [
{
"name": "Payments Service",
"slug": "payments-service",
"domainName": "Payments",
"purpose": "Processes payment transactions and emits events to downstream systems",
"language": "TypeScript",
"framework": "NestJS",
"frameworkVersion": "10.3.0",
"repositoryUrl": "https://github.com/acme/payments-service",
"services": [
{
"name": "payments-api",
"slug": "payments-api",
"type": "API",
"port": 3001,
"path": "/api"
},
{
"name": "charge-worker",
"slug": "charge-worker",
"type": "WORKER"
}
],
"databases": [
{
"name": "payments_db",
"provider": "PostgreSQL",
"version": "15",
"orm": "Prisma"
}
],
"integrations": [
{
"targetSystem": "orders-service",
"type": "HTTP_API",
"description": "Fetches order details before processing payment"
},
{
"targetSystem": "fraud-service",
"type": "GRPC",
"description": "Real-time fraud scoring"
}
],
"messageTopics": [
{
"name": "payment.completed",
"role": "PRODUCER",
"broker": "KAFKA",
"metadata": {
"dlqEnabled": true,
"retryPolicy": "exponential-backoff"
}
},
{
"name": "payment.failed",
"role": "PRODUCER",
"broker": "KAFKA"
}
],
"packages": [
{ "name": "stripe", "version": "^14.0.0", "type": "OPEN_SOURCE" },
{ "name": "@acme/shared-auth", "version": "2.1.0", "type": "INTERNAL" }
],
"apiEndpoints": [
{ "path": "/payments/charge", "method": "POST", "description": "Initiates a payment" },
{ "path": "/payments/{id}", "method": "GET", "description": "Retrieves payment status" }
],
"risks": [
{
"title": "No circuit breaker on orders-service call",
"description": "If orders-service is slow, payments will queue up and degrade",
"severity": "HIGH"
},
{
"title": "Stripe API key stored in plain-text env var",
"severity": "CRITICAL"
}
]
}
]
}Graph View
The Graph page is the core of Meridian. It renders an interactive visualization of all systems in the workspace and the dependency edges between them, resolved from your inventory uploads. Navigate to Graph in the workspace header to open it.
Toolbar & filters
The toolbar at the top of the graph provides controls to filter and configure what is displayed. All filter states are persisted to the URL as query parameters, making filtered views fully shareable.
| Control | Description |
|---|---|
| Search | Filter nodes by system name in real time as you type |
| Domain | Multi-select dropdown to show only systems belonging to selected domains |
| Dependency type | Multi-select with color-coded swatches to show only specific edge types (HTTP, Kafka, shared database, etc.) |
| Language | Multi-select to filter systems by programming language |
| Isolated | Toggle to show or hide systems that have no dependency connections (eye icon) |
| Flow animation | Toggle particle animations on messaging edges (Kafka, RabbitMQ, SQS). Uses a lightning bolt icon. |
| Layered layout | Switch between free-form layout and a topological 3-layer layout (EDGE → BUSINESS_LOGIC → DATA_INFRA) |
| Cluster | Group nodes visually by business domain. At zoom levels below 0.4, domains automatically collapse into a single node. |
| Reset filters | Clears all active filters (only visible when at least one filter is active) |
A counter below the toolbar shows the number of visible systems and edges vs. the total: e.g., 12 / 24 systems · 8 / 31 dependencies.
Layout modes
Meridian supports three layout modes for the graph:
- Free-form (default) — nodes are positioned automatically by a force-directed algorithm. You can drag nodes anywhere; positions are saved per layout mode in local storage.
- Layered — activates a topological layout that places systems in three horizontal layers based on their declared
layerfield:EDGE(user-facing),BUSINESS_LOGIC(internal services), andDATA_INFRA(databases, queues, infrastructure). Useful for understanding architectural tiers. - Clustered — groups nodes inside domain containers. When you zoom out below 0.4×, individual nodes collapse into a single domain node to reduce visual noise. Click a collapsed domain node to expand it.
Node interactions
Each node in the graph represents a system. Nodes display the system name, domain badge, programming language, and service ports. Service types use abbreviated labels:
| Service type | Badge label |
|---|---|
| API | API |
| WORKER | WKR |
| CRONJOB | CRON |
| BACKGROUND_SERVICE | BG |
Nodes support the following interactions:
- Click — opens the System Detail Panel on the right side of the screen, showing the system metadata, services, databases, integrations, and risks
- Highlight button — click the waypoints icon on a node to activate a highlight session: connected edges are highlighted and all unrelated nodes fade to near- invisible (opacity 0.08)
- Risk badge — if the system has risks, a badge showing the risk count appears on the node
- Drag — grab and move any node to reposition it; the new position is saved automatically
Edge types & colors
Every dependency edge is color-coded based on its type. Messaging edges (Kafka, RabbitMQ, SQS) also display flowing particle animations to indicate data flow direction.
| Type | Color | Animated | Description |
|---|---|---|---|
HTTP_API | Indigo · #4f46e5 | No | REST or HTTP API calls between systems |
KAFKA_TOPIC | Green · #059669 | Yes | Kafka topic relationships (producer → consumer) |
RABBITMQ_QUEUE | Violet · #A855F7 | Yes | RabbitMQ queue relationships |
SQS_QUEUE | Yellow · #EAB308 | Yes | AWS SQS queue relationships |
SHARED_DATABASE | Amber · #d97706 | No | Two systems connecting to the same database (same name + provider) |
CROSS_DATABASE_QUERY | Red · #dc2626 | No | Direct cross-database queries between systems |
SHARED_PACKAGE | Purple · #7c3aed | No | Two systems depending on the same internal package |
GRPC | Cyan · #0891b2 | No | gRPC calls between systems |
FILE_DEPENDENCY | Gray · #6b7280 | No | File system or artifact dependencies |
A legend below the filters shows all currently visible edge types with their corresponding color swatches.
Edge interactions
Edges support two main interactions:
- Click — opens a popup showing the source system, target system, dependency type, and the specific target service slug (e.g., which API service or message topic the edge targets)
- Drag — click and drag any edge to adjust its path offset. Edges follow an orthogonal step path with rounded corners. Dragging adjusts the X offset (shifts the two vertical bends left/right) and Y offset (shifts the middle horizontal segment up/down). Offsets are saved per layout mode in local storage.
Hovering an edge reveals a semi-transparent glow, a midpoint dot, and faint depends on / consumed by labels near the source and target.
Time machine
The time machine slider at the bottom of the graph lets you travel back through the history of your graph as it was after each inventory upload. Drag the slider to a previous upload to see the state of the dependency graph at that point in time.
This is useful for understanding how your architecture evolved, spotting when new dependencies were introduced or removed, and reviewing the impact of past changes.
Command search (⌘K)
Press Cmd+K (macOS) or Ctrl+K (Windows/Linux) to open the command palette. Type any system name to search across all systems in the workspace. Selecting a result focuses the graph on that node and centers it in the viewport.
Highlight navigation
Activating the highlight mode on a node (via the waypoints button) starts a highlight session:
- All edges connected to the highlighted node (inbound and outbound) remain fully visible
- All unrelated nodes and edges fade to near-invisible (opacity 0.08)
- A navigation bar appears at the bottom of the graph with Previous and Next arrow buttons to cycle through the connected systems one by one
- The currently focused connected node is highlighted in blue; the source node is highlighted in green
Click the highlighted node again or press Escape to exit the highlight session and return to the normal graph view.
Systems
The Systems section lets you browse all services, workers, and jobs registered in your workspace. It provides two views: a searchable list of all systems and a detailed page for each individual system.
Systems list
Navigate to Systems in the workspace header. The page shows a table with all systems in the workspace, sorted alphabetically. Each row displays:
- System name — links to the system detail page
- Domain — the business domain the system belongs to
- Language and Framework — the primary tech stack
- Services count — number of services (APIs, workers, cron jobs)
- Databases count — number of registered databases
- Integrations count — number of outbound integrations declared
- Documents count — number of Markdoc documents attached to the system
Click any row to navigate to the system detail page.
System detail tabs
The system detail page (/w/[slug]/systems/[systemSlug]) is divided into four tabs:
Overview
Shows the system metadata extracted from the inventory: programming language, framework and version, domain name, and the repository URL (clickable external link if provided).
Architecture
Displays the full inventory of technical components registered for the system:
| Component | Fields shown |
|---|---|
| Services | Name, type (API / WORKER / CRONJOB / BACKGROUND_SERVICE), port, path |
| Databases | Name, provider, version, ORM |
| Integrations | Target system, integration type, description |
| Message topics | Topic name, broker, role (PRODUCER / CONSUMER / BOTH) |
| Packages | Name, version, scope (INTERNAL / OPEN_SOURCE / TEST) — top 20 shown |
Risks
Lists all risk entries declared in the inventory for this system. Each row shows the risk title, description, and a color-coded severity badge:
- CRITICAL and HIGH — red (destructive)
- MEDIUM — neutral (secondary)
- LOW — outline
Documentation
Lists all Markdoc documents attached to the system, showing the title, author, and last updated date. EDITOR and OWNER members see a New Document button to create a new document inline.
Documentation
Meridian includes a built-in documentation system that lets teams write and maintain technical docs directly alongside their system inventory. Documents are written in Markdoc, a powerful Markdown-based authoring format that supports custom tags and structured content.
Creating documents
To create a new document for a system:
- Navigate to the system detail page (Systems → click a system)
- Click the Documentation tab
- Click New Document (visible to EDITOR and OWNER roles)
- Enter a title and a slug (URL-safe identifier, auto-generated from the title)
- Write the document content using Markdoc syntax in the editor
- Save the document
Viewing documents with TOC
When you open a document, Meridian renders the Markdoc source into a clean reading view. The page includes:
- Rendered content — fully formatted text with headings, tables, code blocks, lists, and callout boxes
- Table of contents sidebar — automatically generated from the document headings (h2 and h3), displayed as a sticky sidebar on the right side of the document. Clicking a TOC entry scrolls to that section.
- Author and date — shows the author name and last updated timestamp at the top of the document
- Edit link — visible to EDITOR and OWNER members, navigates to the editor for that document
If the Markdoc source contains syntax errors, a validation warning is displayed at the top of the rendered view.
Editing documents
The document editor provides a text area with Markdoc syntax. Documents support standard Markdown features plus Meridian-specific custom tags:
| Tag | Description |
|---|---|
{% callout type="note" title="..." %} | Renders a highlighted callout box. Types: note, warning, error, check |
Here is an example of a complete system document written in Markdoc:
# Service Overview
This document describes the **payments-service** architecture and its integration points.
## Dependencies
The service calls the `orders-service` via HTTP to fetch order details before processing payment.
{% callout type="warning" title="Rate limiting" %}
The orders API enforces a 1000 req/min rate limit. Ensure your retry logic uses exponential backoff.
{% /callout %}
## API Endpoints
### POST /payments/charge
Initiates a payment for a given order.
**Request body:**
- `orderId` (string) — the order to charge
- `amount` (number) — amount in cents
- `currency` (string) — ISO 4217 currency code
**Response:** Returns a `paymentId` and initial `status`.
## Events Emitted
| Event | Broker | When |
|-------|--------|------|
| `payment.completed` | Kafka | Payment successfully processed |
| `payment.failed` | Kafka | Payment declined or errored |