Files and templates
New, open, save
The File group in the toolbar holds New, Open, Save and Revisions. Templates lives in the app menu, and the gallery appears by itself on an empty canvas.
| Action | How | Notes |
|---|---|---|
| New | New button | Replaces the document with a single empty page. It is undoable — ⌘/Ctrl Z brings the previous document back. |
| Open | Open button, ⌘/Ctrl O | Opens .drawio (also .xml) and Visio .vsdx. |
| Save | Save button, ⌘/Ctrl S | Writes back in the format the document is already in. |
| Save As | ⇧⌘/Ctrl S | The extension you pick in the dialog decides the format: choose .vsdx and the document saves as Visio from then on. |
A page is named from its tab in the pages bar along the bottom — double-click the tab, type, press Enter. That name is also the suggested filename when you export the page (path-hostile characters are folded to -, an empty name becomes diagram). The window title shows the open file's name, with a dot while there are unsaved changes; until the document has been saved to a file it shows the active page's name instead.
What you can open
.drawio/.xml— full support, all pages. Content the editor does not model (draw.io shapes and attributes it has no concept of) is kept in memory and written back on save, so opening and saving a draw.io file does not throw away the parts Drawbridge does not understand. Opened the other way round — a file you saved here, opened in draw.io — cables arrive as plain lines with no arrowheads, because a cable connects two devices rather than pointing from one to the other; flow arrows keep their heads. draw.io shows the same icons. Every device is saved with its icon travelling inside the file, so a drawing opened over there is the drawing you made — the tile in its family colours, the icon in the accent above it, the name underneath — rather than a row of coloured boxes. A custom icon you set yourself travels the same way. The icon rides along as part of the device, so moving, copying or deleting a tile in draw.io takes it with you; a shape that came from somebody else's draw.io file is left exactly as they drew it..vsdx— Visio drawings, all pages. This is an interchange path, not archival: 2D shapes become devices, 1D connector shapes become links, and page furniture (guides, decorative divider strokes) is dropped. Shape kinds come from the Visio master name matched against the shape catalog; a shape drawn as an embedded picture keeps that picture (it arrives as an image node, and saving embeds it back into the.vsdxas a real Visio picture shape); plain text boxes arrive as text blocks with their size and alignment; anything else arrives as a generic device rather than disappearing. Links are found even when they were never glued in Visio (a line whose end touches a device connects to it) or when they live grouped together with their caption — the caption becomes the link's label, and the line's colour comes along. Nothing "foreign" is preserved from a.vsdx— what you see after opening is what a save writes back.
Files are recognised by extension, and a file that is really a zip (a renamed .vsdx) is still read as Visio.
You can also drag a .drawio or .vsdx straight onto the canvas to open it, instead of going through Open. It asks the same question first if the current drawing has unsaved changes, and it opens the file as a document — it does not paste it into what you already have. One difference from Open: a dropped file gives the app its contents but not permission to write back to it, so Save will ask you where to put it rather than saving over the file you dropped. Dropping an image still adds the image to the drawing, as it always has.
Compressed legacy draw.io pages
Older draw.io versions stored each page's payload deflate-compressed and base64-encoded. Drawbridge decompresses those on open, so a legacy file's pages arrive as ordinary editable pages — nothing marks them as having been compressed. Saving writes them back as plain XML, which is also what a current draw.io writes by default, so the file only gets easier to read.
A payload that cannot be decoded — a damaged file, or compression draw.io never wrote — opens as a read-only page instead: its tab is marked "Unreadable page — read-only", it shows empty, and its original content is preserved verbatim so saving the file does not destroy it. Other pages in the same file open normally. If no page at all can be read, the open fails with a message telling you to re-save the file with a current draw.io and open it again.
Auto-save
Two things happen automatically, both debounced about a second after you stop editing:
- A local snapshot of the whole document (all pages, plus the speed-colour and bundle settings) is kept in local storage and restored the next time you open the app. This always happens, even for an untitled document, and it also runs when you close the window.
- A write to the open file, once the document has one — that is, after you have opened a file or saved once. There is no Save ritual after that; the Save button turns into status text reading
Saving…/Saved.
Auto-save to the file can be turned off under the app menu (Auto-save). An untitled document is never written to disk.
In the browser, write permission for a file handle can lapse. Auto-save then pauses rather than prompting from a background timer, and a sticky toast offers Re-enable — clicking it re-requests permission and resumes. If a write genuinely fails you get an "Auto-save failed" message once, and auto-save pauses until you retry.
If you close a browser tab with unsaved changes, the browser's own "leave site?" prompt appears. The desktop app never blocks the close — the snapshot has already been written and is restored on next launch.
Desktop vs browser
| Desktop app | Browser | |
|---|---|---|
| Dialogs | Native OS open/save dialogs | File System Access API where available (Chromium) |
| Saving | Writes straight to the path | Writes through the file handle |
| No handle available | — | Falls back to a plain download; the document stays marked unsaved because the browser reports no completion, and nothing auto-saves |
| After relaunch | The document reattaches to its file automatically | The binding is lost; the local snapshot still restores the content |
| Opening from the OS | Double-click a .drawio, "Open with", or a path on the command line opens it in the app |
— |
Firefox and other browsers without the File System Access API can still open files (through a file picker) and save (as a download), but have no file binding, so no auto-save to disk.
On relaunch the desktop app reattaches to the last file without reading it — the local snapshot is at least as new — so nothing on disk is overwritten until your next edit. If the file has been moved or deleted, the binding is dropped silently and the document becomes untitled.
Templates
Press Templates… in the app menu, or pick one from the gallery shown on an empty canvas.
Built-in templates are grouped by category: Datacenter, Campus, Branch, SD-WAN and Global — for example "DC — Spine/Leaf", "Campus — Collapsed Core", "Branch — SD-WAN", "SD-WAN — Hub and Spoke", "Global — AMER / EMEA / APAC". Each card shows a generated thumbnail.
Applying a template replaces the current diagram. If the canvas is not empty you are asked to confirm; the change is undoable either way. Built-in templates are drawn with your current default connector type, exactly as if you had drawn the cables yourself.
Generate an SD-WAN topology
The SD-WAN category has a Generate… card. It opens a short wizard — how much detail, regions, whether hubs mesh across regions, hubs per region, branches per region, WAN links per branch and their types (Internet / MPLS / LTE), single or HA branch firewalls, and the branch LAN (none, switch, switch + AP) — with a live preview and a running count of boxes, tunnels and links, and drops the generated topology in as a diagram.
The first question decides how much of the network is drawn:
- Every device draws each box and each cable. Every firewall — including both members of an HA pair — builds its own tunnels to every hub over every WAN link, hub pairs are joined by their two HA cables, and where regions mesh, every hub reaches every hub in the other regions. Nothing is left unwired, which at four branches × two hubs × two transports is a lot of connectors.
- One box per site draws the same network as an overview: an HA pair — at a hub or at a branch — is a single object, and each branch is one site tile with exactly one tunnel to its regional hub. Only the questions that still change the picture are asked; hubs per region, WAN links, branch HA and the branch LAN all disappear, because at this level a site is a site and a transport is a device-level detail.
Saving and sharing your own
- Save current as template… names and describes the current diagram and stores it under My templates on this machine. Your own templates keep the connector types they were saved with.
- Each of your templates has an export button that writes a shareable
.dbtpl.jsonfile, and a delete button. - Import template… reads such a file back into My templates. The file is validated on the way in; a malformed one is refused with the reason.
Custom templates live in local storage on this machine, not in the diagram file.
Importing devices from a list
Import opens a paste box. Paste terminal output or a CSV and press Import — the devices and links land on the current page, laid out automatically, next to whatever is already there, and the view zooms to fit.
There is no format picker: the parser works out what you pasted and tells you what it decided. Recognised formats:
- Cisco CDP neighbours (
show cdp neighbors, and the detail form) - LLDP neighbours, including the FortiOS variant
- Cisco LLDP detail —
show lldp neighbors detailon IOS, IOS-XE, NX-OS and IOS-XR. Richer than the summary table: the management address becomes an asset field, and the icon is read from what the neighbour says it is. Older IOS does not print the local interface at all; those neighbours still arrive, with the cable unlabelled at your end and one line saying so. - Aruba AOS-CX —
show lldp neighbor-infoandshow lldp neighbor-info detail(or a single port). The summary is a table and says nothing about what a neighbour is, so its icons come from the neighbour names; the detail form carries the management address and the capabilities, so it is the one that draws icons from what a device said about itself. - ArubaOS-Switch / ProCurve —
show lldp info remote-device, both the table and the per-port detail, in the same paste if you have both. Chassis ids print as spaced hex bytes and system names may contain spaces; the columns are read from the rule under the header, so neither is torn in half. - FortiSwitch port list —
diagnose switch-controller switch-info lldp neighbors-summary <serial>, run on the FortiGate that manages the switch. This is the one that draws the access layer: it lists what every port of a managed FortiSwitch can hear, so the phones, cameras and third-party access points and switches the FortiLink topology knows nothing about arrive with the cable that reaches them. Ports with nothing plugged in are counted in one line rather than reported one by one, and pasting the output of several switches at once wires them to each other. - FortiGate FortiLink topology —
execute switch-controller get-physical-conn dot <fortilink-interface>, pasted whole, CLI chrome and all. Device roles, serials and models are read from it, and MCLAG peer switches stay side by side on their tier. - Any Graphviz DOT (
digraph { fw1 -> sw1 }) — Drawbridge draws the topology in its own style with its own icons; Graphviz styling attributes are ignored. - CSV of devices, CSV of links, or one file containing both
Where the output says nothing about a device — no show command prints what the box you ran it on is, and a summary table has no capability column — the icon is read from the name, last of all: CORE-SW-01 is a switch, 8325-spine an L3 switch, AP-LOBBY-01 an access point, and a name that says nothing keeps the neutral tile. Anything the output does state wins over it.
CSVs are matched by header name, not column order, so an export from most inventory tools lines up. Recognised device columns include name/hostname/label, kind/type/role, management IP, serial, model/platform, location/site/rack and notes. Link columns include from/source/local, to/target/neighbour, the port/interface on each end, speed and label. Drawbridge's own CSV inventory export uses these names, so it imports straight back in.
DOT files can carry the same data as attributes — kind= (a shape name from the palette), label=, mgmtIp=, serial=, model=, location=, notes= on devices; speed=, label= and taillabel=/headlabel= (or device:port endpoints) on links. They are ordinary DOT attributes, so a file written this way still renders in any Graphviz tool, and one written for Graphviz still imports here.
An import can also arrive as a link: a URL of the form …/app/#import=pako:… opens the app with this paste box pre-filled — same summary, same report, and nothing lands on the page until you press Import. The text travels in the URL fragment, which browsers never send to any server, so the diagram stays between whoever built the link and whoever opens it. scripts/make-import-link.mjs in the repository turns a file, or piped CLI output, into such a link.
An import merges into the devices already on the page. A pasted device whose name matches one that is already drawn — trimmed, and whatever the capitals — is that device: no second tile is created, its cables attach to the tile you already have, and asset fields that are still empty are filled in from the paste. Nothing you already have is overwritten, including the icon you chose and the name as you spelled it, and a cable that is already drawn between the same two devices on the same ports is not drawn again. So pasting the output of a second switch, which names the first one, adds only what is new. The rest of the paste — the genuinely new devices — is laid out and placed below the existing drawing as usual.
The summary line says which it is before you commit: "8 devices — 3 already on this page, 5 new — 12 links (2 already drawn)". If a device really should be a second box, rename one of them before importing. The whole import, new tiles and filled-in fields together, is a single undo.
The dialog shows, before anything is committed:
- what format it read, how many devices and links it found, and how many of them are already on this page;
- every line it could not read, quoted with its line number and a reason (long reports are truncated with a count);
- a count of lines that will be left out.
Good rows are imported and bad ones are reported — real pasted output always contains legends, prompts and footers. Import stays disabled until the paste yields at least one device.
Dropping in images
Drag an image file onto the canvas, or paste one from the clipboard, and it becomes an image node at the drop point.
- Anything larger than 20 MB, or that is not an image, is refused with a message.
- Images are embedded in the document as data URLs — they travel with the file, no linked assets.
- Stored pixels are capped at 1024 px on the longest side. Small PNGs and JPEGs pass through untouched; JPEG sources that need re-encoding stay JPEG, everything else becomes PNG.
- A new image is fitted into a 96 × 80 box (the same footprint as a device tile) and snapped to the grid, never enlarged. A pasted image arrives selected, so resizing it is one drag away.
Inventory
Export → CSV inventory writes every device on every page as <title>-inventory.csv: page, label, kind, and the asset fields — Management IP, Serial, Model, Location, Notes.
Devices with no asset data are listed too — the point is to show what is still undocumented. The file is written with a UTF-8 byte-order mark so Excel reads non-ASCII names correctly, and every cell is guarded so a value beginning with =, +, - or @ cannot be executed as a spreadsheet formula. If the document has no devices at all, nothing is written and you are told so.
When the file changes underneath you
The desktop app watches the file you have open. If something else changes it — an assistant driving the MCP tools, draw.io in another window, a git pull or a branch switch — you do not have to reopen it.
What happens next depends on whether you have unsaved work:
- Nothing unsaved: the drawing reloads on its own and the view fits to it. A short message says why it moved, so a diagram redrawing itself is never a mystery.
- Unsaved edits: nothing is touched. A message stays on screen — it does not fade — telling you the file changed and offering Reload. Your edits are still there until you choose. If you save instead, your version wins and the offer goes away, because by then it is describing a file that no longer exists.
Two things it deliberately does not do. It never reacts to your own saves, so working normally is silent. And it waits for the file to stop changing before reading it — a program part-way through writing a diagram is briefly an empty file, and reloading that would be worse than waiting a moment.
This is the desktop app only. The browser has no way to watch a file it was handed.
Revisions
Revisions in the toolbar's File group saves the drawing as it stands and lets you load it back later. Each saved revision gets an identity of its own: a number that never repeats and a stamp to the minute, so a row reads #4 · 2026-08-04 14:32. Type a note as you save it and the row says what changed. The document's own revision label and your initials ride alongside as context — several snapshots can share those, because the document only gets a new revision when somebody issues one.
They live inside the .drawio file. Send somebody the drawing and its history goes with it — there is no sidecar file to lose and nothing to keep in step. Snapshots are compressed, and the dialog shows what the history costs the file so you can prune it before it matters. Twenty revisions are kept; past that the oldest is dropped and the app says so.
Each row offers three things:
Restore loads that revision back over every page of the drawing. It asks first, and it is undoable — ⌘/Ctrl Z brings back what you had. It does not consume the revision or anything saved after it, so going back to look at something costs you nothing.
Compare shows what changed between that revision and the drawing now. The revision is the baseline, so "added" means present in the drawing now and absent from it.
Compare mode is strictly read-only, and the drawing is read-only with it: while the panel is up, dragging a device, resizing one, pressing F2 or double-clicking a label all do nothing at all — the gesture is refused rather than undone, nothing reaches auto-save, and Exit leaves the drawing exactly as you left it. It never touches the document or the undo stack, and nothing it draws appears in exports. Changes are ringed on the canvas and listed in a panel, each with a glyph (
+,−,~), a word and its own stroke pattern — not colour alone. Node changes are told apart (shape changed, re-labelled, asset data edited, subnet changed, layer changed, grouping changed, moved, resized, restyled) as are link changes (rewired, re-labelled, restyled, rerouted); anything matched by name rather than identity is flagged as a best guess. The revision's counterpart page is matched by page title, falling back to the same position. Exit or Escape leaves.Delete removes it from the file. That one cannot be undone.
Only the .drawio carries the history. A Visio (.vsdx) save or export has nowhere to put it and takes only the current drawing — the app says so when it happens — and every picture export (SVG, PNG, PDF) is of course just the drawing. Opening the file in draw.io works normally; draw.io ignores what it does not recognise, but saving there drops the history, because draw.io rewrites the file from its own model.