Skip to main content

Build a print extension

Learn how to build a POS print extension that generates, previews, and prints custom documents.

Anchor to introIntroduction

This tutorial shows you how to create a print extension that lets merchants generate and preview documents before printing.

What you'll achieve:

  • Create a backend service that serves print-ready documents
  • Build a POS extension with preview and print capabilities
  • Implement error handling for a reliable printing experience
  • Test your extension in a development environment

Print Extension in Action

Anchor to requirementsBefore you start

To make the most of this tutorial, you'll need:

  • Complete the Getting started guide
    • Partner account
    • Development store with POS
    • Latest version of Shopify CLI
    • Basic app setup (access scopes only needed if accessing Shopify data)
Access scopes

This tutorial uses simple HTML documents. If you plan to include order, customer or any other Shopify admin data in your prints, you'll need additional access scopes.

Learn more about access scopes

Anchor to backend-setupCreate a route to serve printable documents

First, create a new route file at app/routes/print.js that will serve your printable documents. This example uses Remix, but you can adapt the concepts to your preferred framework.

Need help setting up a Remix server? Check out the Shopify App Remix documentation.

Let's walk through each part of the implementation:

  1. Set up the route and handle authentication with Shopify
  2. Process URL parameters to determine which documents to generate
  3. Generate HTML content with proper styling for each document type
  4. Return a properly formatted response with CORS headers

Here's a complete example that supports multiple document types:

Print document requirements
  • Use only static HTML and CSS - JavaScript won't execute in print documents
  • Include all styles in the section or inline
  • Use @media print CSS rules for print-specific styling
  • Ensure proper CORS headers are set for POS access
Page breaks

When returning multiple documents, use CSS page breaks to ensure proper printing:

@media print {
  .page-break {
    page-break-after: always;
  }
}
Email obfuscation

When using Cloudflare tunnels for development, wrap email addresses in HTML comments to prevent obfuscation:

<!--email_off-->example@email.com<!--/email_off-->

Learn more about email obfuscation

Print Route Implementation

/app/routes/print.js

import {authenticate} from '../shopify.server';

export async function loader({request}) {
// Step 1: Set up the route and handle authentication
const {cors} = await authenticate.admin(request);

// Step 2: Process URL parameters for document configuration
const url = new URL(request.url);
const printTypes = url.searchParams.get('printTypes')?.split(',') || [];

// Step 3: Generate the HTML content
const pages = printTypes.map((type) => createPage(type));
const print = printHTML(pages);

// Step 4: Return properly formatted response with CORS headers
return cors(
new Response(print, {
status: 200,
headers: {
'Content-type': 'text/html',
},
}),
);
}

// Helper function to create document pages based on type
function createPage(type) {
const email = '<!--email_off-->customerhelp@example.com<!--/email_off-->';

// Get document content based on type (invoice, packing slip, etc.)
const getDocumentInfo = () => {
switch (type) {
case 'invoice':
return {
label: 'Receipt / Invoice',
content: `

Anchor to extension-uiBuild the extension UI

Your print extension needs two main components that work together to provide a complete printing experience:

  1. A Tile on the POS smart grid that launches your extension
  2. A Modal that implements the printing workflow:
    • Document selection with a list of available templates
    • Document preview before printing
    • Print button with proper loading and error states

Let's walk through the implementation:

  1. Create a tile component that opens the modal
  2. Set up a Navigator to manage multiple screens
  3. Implement document selection with a List component
  4. Add PrintPreview and execute Print API with button

Here's how to implement both components:

Key components
  • The Tile component uses api.action.presentModal() to open the modal
  • The Navigator component manages the document selection and preview screens
  • The List component with toggle switches for document selection
  • The PrintPreview component shows selected documents before printing
  • Loading states and error handling ensure a smooth user experience

Extension Components

import React from 'react';

import {
Tile,
reactExtension,
useApi,
} from '@shopify/ui-extensions-react/point-of-sale';

const HomeTile = () => {
const api = useApi();
return (
<Tile
title="Print Tutorial"
onPress={() => {
api.action.presentModal('print-tutorial');
}}
enabled
/>
);
};

export default reactExtension('pos.home.tile.render', () => {
return <HomeTile />;
});

Anchor to extension-configConfigure your extension

Configure your extension with the necessary permissions and settings in the shopify.extension.toml file:

Extension Configuration

shopify.extension.toml

api_version = "unstable"

[[extensions]]
type = "ui_extension"
name = "Print Tutorial"
handle = "print-tutorial"
description = "POS UI extension print tutorial"

[[extensions.targeting]]
module = "./src/HomeTile.tsx"
target = "pos.home.tile.render"

[[extensions.targeting]]
module = "./src/HomeModal.tsx"
target = "pos.home.modal.render"


Anchor to testingTesting your extension

To test your print extension:

  1. Navigate to your app directory:

    cd <directory>
    
  2. Start your development server:

    shopify app dev
    
  3. Press p to open the developer console

  4. In the developer console, click on the view mobile button to preview your extension

  5. Click the Print Tutorial tile

  6. Select a template, press next, and then print

Congratulations! You've built a print extension that generates, previews, and prints custom documents.

Testing tip

Use your browser's developer tools to monitor network requests and check for any CORS or authentication issues.

Anchor to deploy-releaseDeploy and release

Refer to Deploy app extensions for more information.

Anchor to troubleshootingSolving common challenges

Here's what might be happening:

  • Your CORS settings might be blocking the preview
  • Authentication could be failing
  • The document URL might be incorrect

Quick fix: Open your browser's developer tools and check the network tab for any failed requests.

Common formatting issues:

  • Print-specific styles might be missing
  • Check if your document format is supported