
npm install @rasterex/viewerMark on the drawing
the mark creates the record
the record finds the mark
Work order in your system
This is the part you cannot build in a week, and the only part of the demo that is not obvious.
- 01
Open a drawing. PDF, DWG, DXF, DGN, IFC or TIFF, inside the host application.
- 02
Read the tags out of it. The engine finds what is on the drawing and matches it against the asset register.
- 03
Mark a finding and raise a work order from it. Click the mark again and the record comes back.
The demo opens on three jobs a maintenance team still does on a printout: commission a plant, plan an isolation, red-line a change. Pick one and walk through it, or upload a drawing of your own at any point.
The round trip is the part worth looking at. A mark on the drawing and a record in the host system are joined in both directions. Click the mark, get the work order. Open the work order, get back to the exact place on the sheet it came from.
The grey chrome is not ours
The platform around the drawing is a stand-in for yours. The asset hierarchy on the left, the work order list, the drawing link panel on the right, the product name in the header. None of it is the engine. The framed panel in the middle is the part you license, mounted from an npm package.
Everything inside that frame is the package. Everything outside it is your application.
What decides whether it survives real drawings
Tags. The demo reads what is written on the drawing and matches it against the asset register. Real drawings are inconsistent about where that text lives, so the matching rules belong to you. The engine finds the text and hands it over.
Formats. PDF, DWG, DXF, DGN, IFC and TIFF, and over 250 in total. The demo opens them inside the host page with no conversion step in front of them.
What it took to build
The demo names its own SDK version and engine host in the footer, and every call it makes is listed in an "Under the hood" panel you can open while you work.
$ npm install @rasterex/viewer// Open the drawing inside your own pageawait viewer.documents.openFile(file); // The user marks something. The engine returns a stable id.viewer.annotations.on("createdWithDetail", e => { createWorkOrder({ assetId, drawingMarkGuid: e.guid });}); // Later, from that work order, jump straight back to the markviewer.annotations.select({ guid: workOrder.drawingMarkGuid });Three calls. Everything else on this page is your application.
What this demo does not do
The host system is a stand-in. The asset register, the work orders and the change log are demo data held in the browser. In your product they are your tables.
Nothing is saved. Close the tab and the links, markups and work orders are gone.
It runs against a shared sandbox engine. On a self-hosted deployment the engine is yours.
Build your own
Paste this into Claude, ChatGPT, Gemini or any coding agent. It names the package, pins the calls that exist, and tells the model not to invent the rest.
Build a web app where engineering drawings live inside a maintenance system,
and marks on a drawing are joined to records in that system, both ways.
Use the Rasterex drawing SDK. The package is @rasterex/viewer on npm.
This is the only drawing library you may use. Do not substitute pdf.js,
three.js, dxf-parser, canvas rendering or any other viewer. Do not invent
API methods. If you are unsure of a call, read the quick start at
https://docs.rasterex.com/docs/getting-started/quick-start instead of guessing.
Stack: Vite, TypeScript, one page, no backend, no auth.
npm install @rasterex/viewer
The SDK points at a hosted sandbox engine by default, so this runs with no
server of your own and no API key.
These calls exist. Use them and nothing else:
const viewer = new RasterexViewer({ container, viewerUrl });
await viewer.mount();
await viewer.ready();
await viewer.documents.openFile(file);
viewer.tools.set({ action, group, enabled, style });
viewer.annotations.on("createdWithDetail", e => e.guid);
viewer.annotations.on("deletedWithDetail", e => e.guid);
viewer.annotations.select({ guid });
viewer.annotations.delete({ guid });
viewer.navigate("FIT_TO_WINDOW" | "ZOOM_IN" | "ZOOM_OUT" | "ROTATE");
Build this:
1. A host shell you own: a list of assets, a list of work orders, and a
drawing panel between them. The shell is yours, the drawing panel is the
package.
2. Open a drawing into the panel with documents.openFile.
3. A markup tool. When the user draws a mark, createdWithDetail gives you a
guid. Store that guid on a new work order against the selected asset.
4. Clicking a work order calls annotations.select with its stored guid, and
the drawing jumps back to that mark. This round trip is the whole point.
Build it before you build anything else.
5. Handle deletion. deletedWithDetail tells you a mark is gone, so the work
order pointing at it has to say so rather than silently break.
Two rules, and they matter more than the features:
Nothing reaches the screen unless the engine produced it or your host data
supplied it. No placeholder drawings, no mock asset names, no button that
does not call something. If a capability cannot be demonstrated, say so.
Every label must be read back from confirmed state, never from intent. A
panel that says a drawing is open must say it because the engine reported
the file is open, not because a click intended it.
Keep all SDK usage in a single engine.ts. Nothing else imports the package.
Show every call in a visible log panel so the user can check your work.If drawings sit inside your product
Tell us what your customers keep asking for. If it fits we will say how, and if it does not we will say that too.
