Custom Vue SPA Apps

Updated Jun 19, 2026
DataMagik Application Designer

Custom Vue SPA Apps

When the visual designer is not enough, build a custom SPA app — a real Vue 3 + Vite single-page application that you author locally and publish as a versioned bundle. It is the “infinite customization” end of the spectrum: your code, your components, your UX — still permission-gated and available on the web, inside Plex, and on mobile.

How it works (in 60 seconds)

Your built Vite bundle is published as an app version and served into a sandboxed iframe with an opaque origin. Your code never holds a session or token and cannot reach the network directly (connect-src 'none'). Every platform call goes through the @datamagik/app-sdk bridge, which the trusted host page proxies to app-scoped APIs with server-side authorization on every request. You declare up front which lookup tables, ODBC queries, scripts, serial series, and printers your app uses — undeclared resources are refused (not_declared).

Quickstart

# 1. Create the SPA app shell (Builder permission required)
#    apps_create { "app_name": "Receiving", "app_type": "spa" }

# 2. Scaffold a starter (prompts for "simple" or "showcase")
npx @datamagik/cli init my-app
cd my-app && npm install

# 3. Set "appId" in dm.config.json, then log in
dm login --url https://data-magik.com   # paste an API key (dcp_...)

# 4. Run it now — hot reload against real data
dm dev --context order=42 --context line=L1

# 5. Declare your resources, regenerate types
dm add
dm typegen

# 6. Publish a version (vite build -> zip dist/ -> upload)
dm publish --message "first SPA version"

The showcase starter ships a platform-styled app with a working example of every SDK area; simple is a minimal connect-and-query app. Full command details are in Installing & Using the CLI.

Rules of the sandbox

  • No direct network. fetch/XHR/WebSocket are blocked by CSP — use the SDK.
  • No cookies or platform-origin storage. The frame is opaque-origin.
  • Relative asset paths only. The CLI forces Vite base: './' — keep it.
  • Declared resources only. Add the resource to dm.config.json, re-run dm typegen, and republish.
  • Bundle caps: zip ≤ 30 MiB, ≤ 100 MiB uncompressed, ≤ 1,000 files.

Writing app code

import { dm } from './dm.generated';

await dm.init();                                  // resolves platform context
const rows = await dm.data.query('parts');         // typed rows, alias autocompletes
const sn   = await dm.serials.generate('lotSerial', { PART: part });
await dm.print.submit('line1Zebra', { format: 'zpl', data: label });
dm.emitOutput('completed', { received: rows.length });

See every method in The App SDK Reference.

Not yet supported (v1)

Writing rows (dm.data.writeRow) and capture (dm.capture.*) are not part of the v1 SPA SDK surface — those flows currently authorize through editable components in a layout app. Reading lookup data, running scripts, generating serials, and printing are fully supported.

Was this page helpful?