Documentation Index
Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt
Use this file to discover all available pages before exploring further.
Admin Print Action Extensions
Admin print actions add a “Print” button to an admin resource page that produces a print-ready document for that resource — packing slips, branded invoices, gift receipts, return forms, pick lists, anything that ends in awindow.print() call.
Unlike Admin Actions (which open an interactive
modal), print actions exist for one job: render a printable view and hand
it to the browser’s native print dialog. The host page automatically
opens a new window, drops the rendered HTML into it, and triggers
window.print() as soon as the page paints.
The current build renders printable HTML and uses the browser’s native
print dialog. Headless-Chrome PDF generation, page-size hints, and direct
receipt-printer support are tracked as future work — see
Roadmap.
How it works
The host (TeamInfra admin) opens the response in a new window:- Template mode — the response includes
htmlalready wrapped in a print-ready envelope (with<script>window.print()</script>baked in). The new window writes the HTML, the script fires onload, and the print dialog opens automatically. - Iframe mode — the host points the new window at your
iframeUrl. Your app is responsible for fetching whatever it needs, rendering the printable view, and callingwindow.print()itself.
Two rendering modes
You choose one of these per print action. The choice is dictated by which field you set on the manifest:template (string of Aqua/Liquid)
or appUrl (HTTPS URL).
Template mode
Ship an Aqua/Liquid template string. CustomerLMS renders it
server-side with the resource id in context and returns HTML wrapped
in a print envelope. Zero app-server work at print time.
Iframe mode
Ship a URL. CustomerLMS returns a signed URL the host opens in a new
window. Your app generates the printable view dynamically, fetching
whatever live data it needs.
template and appUrl. The
server checks appUrl first; if both are set it’s used and template is
ignored. Pick one.
Available targets
| Target | Where it renders |
|---|---|
admin.order-details.print.render | Print menu on the order detail page |
Additional
admin.{resource}-details.print.render targets for product,
draft order, gift card, customer, and shipment pages are planned as the
respective admin detail pages get wired in. Track this in the
Roadmap.Extension manifest
Each print action is one entry inextensions.printActions on your
app.json. After install, each entry is persisted as a single schema
file at:
Template-mode manifest
Iframe-mode manifest
Fields
| Field | Required | Description |
|---|---|---|
handle | yes | URL-safe identifier — unique per app. Used as the schema filename and the API handle parameter. |
target | yes | Print slot. See Available targets. |
title | yes | Print menu label shown to the merchant. Also used as the new window’s <title>. |
template | one of | Aqua/Liquid string rendered server-side with the resource context. Pick this or appUrl. |
appUrl | one of | HTTPS URL loaded as the printable page. Must serve a self-printing HTML view. Pick this or template. |
icon | no | URL of an SVG/PNG icon shown next to the menu item. |
name
and title merged for back-compat). Schema mode is detected at print
time by checking appUrl first, then falling back to template.
Rendering endpoint
When the merchant clicks the print menu item, the admin host sends a POST to CustomerLMS to resolve the action:domainSlug, appHandle, handle. resourceId and
resourceType are surfaced to your template and as iframe query params.
The endpoint is CORS-open (Access-Control-Allow-Origin: *) so the
TeamInfra admin can call it cross-origin. Auth-gating happens at the
admin UI layer, not on this endpoint — anyone who knows the manifest
handle can hit it.
Template-mode response
<script>window.print()</script> fires automatically once the
page paints.
Iframe-mode response
iframeUrl in a new window. The query params are appended
automatically — see Iframe-mode details.
Error responses
| HTTP | Body | Cause |
|---|---|---|
| 400 | { error: "Missing required fields: domainSlug, appHandle, handle" } | Caller didn’t pass one of the required fields. |
| 400 | { error: "Print action manifest must declare either \template` or `appUrl`” }` | Manifest is on disk but has neither field set. |
| 404 | { error: "Print action manifest not found: ..." } | The schema file doesn’t exist — install probably never ran. |
| 500 | { error: "Failed to render print template", details: "..." } | Liquid compilation/render error. |
| 500 | { error: "Invalid print action manifest JSON", ... } | The schema file on disk is corrupted. |
Template-mode details
In template mode your Aqua/Liquid template is rendered server-side using the same engine that powers theme rendering. You get the full filter library (money, date, default, escape, etc.) and the full
render / include / for syntax.
The context exposed to the template is intentionally minimal in the
current build:
resourceType is "order" you can write {{ order.id }}; when
it’s "customer" you’d write {{ customer.id }}. The mirror always
maps to the literal resourceType string, so an unknown resource type
will surface as {{ <resourceType>.id }}.
The rendered HTML is wrapped in a minimal envelope:
@media print rule zeroes padding so your content prints
edge-to-edge. Override it in your own <style> block if you need
margins.
Example: packing slip template
Example: minimal invoice template
Iframe-mode details
In iframe mode yourappUrl is opened in a new window with these query
parameters appended:
| Parameter | Description |
|---|---|
resourceId | The id of the resource being printed. |
resourceType | The resource type (order, etc.). |
domainSlug | The merchant’s domain slug. |
handle | The print action handle. |
appUrl already contains a query string, the params are merged.
If appUrl is unparseable as a URL (relative path, missing scheme), it
is returned as-is and the host opens it verbatim.
Your printable page should:
- Read the params. They tell you which resource to render.
- Authenticate. If you need to call your own backend, obtain a session token through App Bridge and include it in your fetch.
- Render the page. Same DOM you’d use for any printable web view.
- Print. Call
window.print()once the DOM is fully painted — typically inside aloadhandler or a shortsetTimeoutso images have time to lay out.
Why use iframe mode
- You need the full resource (line items, addresses, customer fields) that template-mode context doesn’t expose yet.
- The printable view depends on data only your service has (subscription cadence, custom inventory state, multi-warehouse pick paths).
- You want to ship marketing/branded HTML that you control end-to-end without redeploying the merchant’s app.
Why use template mode
- Zero app-server work at print time. CustomerLMS is the only thing online.
- You only need the resource id stamped on a layout (gift receipt with no prices, simple thank-you slip).
- You want offline-friendly behaviour — no need for the merchant to have working internet to your app, only to LaunchMyStore.
Installing print actions
Print actions install through the same/api/apps/install-extensions
endpoint as other extension types. Add a printActions array under
extensions:
_localManifests.js reader picks these up and exposes them under
admin_print_action type to the host. The host’s AdminPrintActionSlot
(in TeamInfra) renders them as menu items inside the merchant’s “Print”
dropdown.
Subsequent installs overwrite existing schema files — there is no
“add to existing” semantics. Always send your full set of print actions
on each install.
Multiple print actions per app
One app can register many print actions for the same target — they all appear in the merchant’s “Print” menu and are sorted byhandle. This
is the typical pattern for warehouse / fulfilment apps that ship a
suite (packing slip + pick list + return form + gift receipt):
Use cases
- Packing slips — pulled at the warehouse, listing what to grab before sealing the box.
- Branded invoices — custom layouts with the merchant’s logo, terms, bank details, tax IDs.
- Gift receipts — recipient-friendly receipts that hide prices.
- Return labels / RMA forms — pre-filled return paperwork the customer service rep can hand to the customer.
- Pick lists — multi-order picking sheets used by fulfilment teams.
- Compliance documents — country-specific export forms, dangerous goods declarations, customs invoices.
Print action vs admin action
| Admin print action | Admin action | |
|---|---|---|
| Output | Printable HTML opened in a new window | Interactive modal iframe |
| Trigger | Click “Print” menu item | Click action button |
| Auto-prints | Yes (window.print() on load) | No |
| Manifest field | extensions.printActions[] | extensions.adminActions[] |
type field | admin_print_action | admin_action |
| Server endpoint | POST /api/apps/print-action | (none — host loads iframe directly) |
| Template mode | Yes — Aqua/Liquid string | No — iframe only |
| Use cases | Packing slips, invoices, labels | Refunds, resync, one-shot edits |
Roadmap & hardware integration
The current build is intentionally minimal — printable HTML + browser print dialog. Several extensions are tracked for future releases:- Headless-Chrome PDF rendering. Optional server-side flag on the
manifest (
renderAs: 'pdf') that returns a PDF buffer instead of HTML, so the merchant can save / email the result without re-rendering client-side. - Resource hydration in template mode. Expose the full order / product / customer object on the Aqua context so templates can render line items, addresses, and totals without iframe mode.
- More targets. Print actions on the product detail page (barcode labels), draft order page (proforma invoice), gift card page (printed gift card), and shipment page (carrier label).
- Receipt-printer / thermal-printer integration. Today the platform uses the browser print dialog only — any printer the OS exposes works (laser, inkjet, label printer, thermal receipt printer). Direct ESC/POS or ZPL output to a USB/network receipt printer (without the browser dialog round-trip) is not wired and will require a native bridge or a WebUSB-based POS-side helper. Track this in the roadmap; for now, point your thermal printer at the OS print queue and pick it in the browser dialog.
- Print presets. Save a merchant’s preferred paper size, orientation, and margins per action so the dialog opens with the right defaults.
- Bulk print. Select N orders in the order list and run a single print action across all of them (useful for end-of-day fulfilment).
See also
- Admin Actions — modal-triggered UI variant.
- Admin Blocks — inline iframe panels.
- Aqua Filters — for use inside
templatestrings. - App Bridge: Session tokens — for authenticating iframe-mode requests to your backend.