Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Graph Explorer Change Log

## Unreleased

- Add defaultStyling.json support for persistent per-type vertex and edge
styling (#1265, #112, #173, #573, #689)
- Add Lucide icon picker to node styling dialog

## Release 3.0.2

This patch release fixes a bug where schema sync did not automatically trigger when switching connections and adds a new configuration option for controlling allowed origins.
Expand Down
2 changes: 2 additions & 0 deletions docs/references/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ Technical reference documentation for Graph Explorer covering configuration, sec
- [Security](./security.md) - HTTPS connections, certificates, and permissions
- [Health Check](./health-check.md) - Proxy server health and readiness endpoint
- [Logging](./logging.md) - Log levels, output, and proxy server logging modules
- [Default Connection](./default-connection.md) - Configure a default connection via environment variables or JSON
- [Default Styling](./default-styling.md) - Configure default vertex and edge styling via a JSON file
165 changes: 165 additions & 0 deletions docs/references/default-styling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Default Styling Configuration

Graph Explorer supports an optional `defaultStyling.json` file that provides
default vertex and edge styling for all users. This is useful for:

- Non-persistent browser environments (e.g., AWS WorkSpaces Web) where IndexedDB
is cleared between sessions
- Pre-configuring a shared visual style for teams
- Providing a consistent starting point for new users

## How It Works

On startup, Graph Explorer fetches `defaultStyling.json` and merges its values
into the user's per-type styling preferences (stored in IndexedDB). Default
values fill in any properties the user hasn't explicitly set — existing user
overrides are preserved.

When no `defaultStyling.json` is mounted, behavior is identical to the default
Graph Explorer experience. When mounted, it populates the per-type styling that
users can then customize. Resetting a vertex or edge style in the UI will revert
to the `defaultStyling.json` values (or the hardcoded application defaults if no
entry exists for that type).

## Setup

### Docker

Mount the file into the container's configuration folder:

```bash
docker run \
-v /path/to/defaultStyling.json:/graph-explorer/packages/graph-explorer/defaultStyling.json \
public.ecr.aws/neptune/graph-explorer
```

### Custom Icons

To serve custom icon files (referenced by URL in the config), mount an icons
directory:

```bash
docker run \
-v /path/to/defaultStyling.json:/graph-explorer/packages/graph-explorer/defaultStyling.json \
-v /path/to/icons:/graph-explorer/packages/graph-explorer/custom-icons \
public.ecr.aws/neptune/graph-explorer
```

Icons in the `custom-icons` directory are served at `/custom-icons/<filename>`.

## JSON Schema

```json
{
"vertices": {
"<VertexTypeLabel>": {
"color": "#hex",
"icon": "lucide-icon-name",
"iconUrl": "url-or-base64",
"iconImageType": "image/svg+xml",
"shape": "ellipse",
"displayLabel": "Custom Label",
"displayNameAttribute": "name",
"longDisplayNameAttribute": "description",
"backgroundOpacity": 0.4,
"borderWidth": 0,
"borderColor": "#hex",
"borderStyle": "solid"
}
},
"edges": {
"<EdgeTypeLabel>": {
"displayLabel": "Custom Label",
"displayNameAttribute": "name",
"labelColor": "#hex",
"labelBackgroundOpacity": 0.7,
"labelBorderColor": "#hex",
"labelBorderStyle": "solid",
"labelBorderWidth": 0,
"lineColor": "#hex",
"lineThickness": 2,
"lineStyle": "solid",
"sourceArrowStyle": "none",
"targetArrowStyle": "triangle"
}
}
}
```

All properties are optional — only specify what you want to override. Type
labels must exactly match the vertex/edge type names in your graph database.

### Icons

There are three ways to set vertex icons:

- **Icon Picker (UI)** — In the Node Style dialog, click **Browse** to search
and select from the full Lucide icon library (~1,900 icons).
- **`icon`** — A [Lucide](https://lucide.dev/icons) icon name in kebab-case
(e.g., `"user"`, `"log-in"`, `"landmark"`). Resolved to an SVG at runtime. No
additional files needed.
- **`iconUrl`** — A URL or base64 data URI for a custom icon. Use this for
non-Lucide icons. If both `icon` and `iconUrl` are specified, `iconUrl` takes
precedence.

### Vertex Shapes

Available shapes: `ellipse`, `rectangle`, `diamond`, `triangle`, `pentagon`,
`hexagon`, `heptagon`, `octagon`, `star`, `barrel`, `vee`, `rhomboid`, `tag`,
`round-rectangle`, `round-triangle`, `round-diamond`, `round-pentagon`,
`round-hexagon`, `round-heptagon`, `round-octagon`, `round-tag`,
`cut-rectangle`, `concave-hexagon`.

### Line Styles

Available for edges and borders: `solid`, `dashed`, `dotted`.

### Arrow Styles

Available for `sourceArrowStyle` and `targetArrowStyle`: `triangle`,
`triangle-tee`, `circle-triangle`, `triangle-cross`, `triangle-backcurve`,
`tee`, `vee`, `square`, `circle`, `diamond`, `none`.

## Common Lucide Icons for Graph Use Cases

| Use Case | Icon Name |
| -------------------- | --------------------------------- |
| Person / User | `user` |
| Account / Bank | `landmark` |
| Email | `mail` |
| Phone | `phone` |
| Login / Auth | `log-in` |
| Device | `monitor`, `laptop`, `smartphone` |
| IP Address / Network | `globe`, `network` |
| Transaction | `arrow-left-right` |
| Location | `map-pin` |
| Organization | `building` |
| Alert | `shield-alert`, `triangle-alert` |
| Document | `file-text` |
| Calendar / Date | `calendar` |
| Lock / Security | `lock`, `shield` |
| Database | `database` |
| Server | `server` |
| Link / Relationship | `link` |

See the full list at [lucide.dev/icons](https://lucide.dev/icons).

## Import / Export / Reset

The Settings page provides styling management:

- **Export Styling** — exports the current per-type styling as a
`defaultStyling.json` file, for sharing or Docker-mounting as team defaults.
- **Import Styling** — imports a `defaultStyling.json` file. This is an
alternative to mounting the file in Docker.
- **Reset All Styling** — resets all styling to defaults. If a
`defaultStyling.json` is mounted, those values are restored; otherwise,
styling reverts to the application defaults.

Per-type reset is also available in the Node/Edge Style dialogs via the "Reset
to Default" button.

## Example

See [`example/defaultStyling.json`](../example/defaultStyling.json) for a
complete example with banking-oriented vertex and edge types.
86 changes: 86 additions & 0 deletions example/defaultStyling.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"vertices": {
"User": {
"color": "#1565C0",
"icon": "user",
"shape": "ellipse"
},
"Account": {
"color": "#2E7D32",
"icon": "landmark",
"shape": "ellipse"
},
"Login": {
"color": "#EF6C00",
"icon": "log-in",
"shape": "ellipse"
},
"EmailAddress": {
"color": "#C62828",
"icon": "mail",
"shape": "ellipse"
},
"PhoneNumber": {
"color": "#6A1B9A",
"icon": "phone",
"shape": "ellipse"
},
"Device": {
"color": "#00838F",
"icon": "monitor",
"shape": "rectangle"
},
"IPAddress": {
"color": "#4E342E",
"icon": "globe",
"shape": "diamond"
},
"Transaction": {
"color": "#1B5E20",
"icon": "arrow-left-right",
"shape": "ellipse"
},
"Location": {
"color": "#E65100",
"icon": "map-pin",
"shape": "ellipse"
},
"Organization": {
"color": "#283593",
"icon": "building",
"shape": "rectangle"
}
},
"edges": {
"OWNS": {
"lineColor": "#2E7D32",
"lineThickness": 2,
"lineStyle": "solid"
},
"TRANSFERRED_TO": {
"lineColor": "#1B5E20",
"lineThickness": 3,
"lineStyle": "solid"
},
"HAS_EMAIL": {
"lineColor": "#9E9E9E",
"lineThickness": 1,
"lineStyle": "dashed"
},
"HAS_PHONE": {
"lineColor": "#9E9E9E",
"lineThickness": 1,
"lineStyle": "dashed"
},
"LOGGED_IN_FROM": {
"lineColor": "#EF6C00",
"lineThickness": 2,
"lineStyle": "solid"
},
"LOCATED_AT": {
"lineColor": "#E65100",
"lineThickness": 1,
"lineStyle": "dotted"
}
}
}
8 changes: 8 additions & 0 deletions packages/graph-explorer-proxy-server/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ export function createApp({
"/defaultConnection",
express.static(path.join(configPath, "defaultConnection.json")),
);
app.use(
"/defaultStyling",
express.static(path.join(configPath, "defaultStyling.json")),
);
app.use(
"/custom-icons",
express.static(path.join(configPath, "custom-icons")),
);

// Host the Graph Explorer UI static files
app.use(staticFilesVirtualPath, express.static(staticFilesPath));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ const useInitCytoscape = ({
}, 100);
cy.on("pan", debouncedPan);

// eslint-disable-next-line react-hooks/set-state-in-effect -- intentional: tracking external Cytoscape instance
setCy(cy);

return () => {
(cy.elements() as any).removeAllListeners();
(cy as any).removeAllListeners();
cy.destroy();
cy.unmount();

setCy(undefined);
};
}
Expand Down
Loading