DeploymentSelf-Hosted Mode
Standalone Mode
Integrate SeatSquirrel as a full-page app with direct JavaScript API
Overview
In Standalone mode, SeatSquirrel runs as a full-page application. There is no iFrame and no SDK file — you
configure the Designer or Picker by editing the HTML file directly and setting a window.SeatSquirrelConfig object.
After the app initialises, a global window.SeatSquirrel object exposes the API.
Designer
Quick Start
Open designer.html and edit the <script> block that sets window.SeatSquirrelConfig:
<script>
window.SeatSquirrelConfig = {
// Wait for the designer to be ready to receive commands including load layout data
onReady: function () {
console.log('Designer ready!');
// Load an existing layout from your API
// fetch('/api/layouts/123')
// .then(r => r.json())
// .then(data => SeatSquirrel.designer.loadLayout(data));
},
onLayoutChanged: function (data) {
// Layout was changed
console.log('Has unsaved changes:', data.hasChanges);
},
onPricingCategoriesChanged: function (data) {
// Handle in-Designer pricing changes — call getPricingCategories() for the data
const { pricingCategories } = SeatSquirrel.designer.getPricingCategories();
console.log('Pricing changed:', pricingCategories);
},
onError: function (error) {
// Handle error
console.error('Error:', error.message);
},
onSave: function (data) {
// Save the layout to your backend
console.log('Save layout data:', data.layout);
}
};
</script>Designer Complete Example
<!DOCTYPE html>
<html>
<head>
<title>Venue Layout Designer</title>
</head>
<body>
<div id="seatsquirrel-designer-root"></div>
<script>
window.SeatSquirrelConfig = {
onReady: function () {
console.log('Designer ready');
},
onSave: async function (data) {
await fetch('/api/layouts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data.layout),
});
SeatSquirrel.designer.showToast({
title: 'Layout saved',
type: 'success',
});
},
onLayoutChanged: function (data) {
document.title = data.hasChanges
? '* Venue Layout Designer'
: 'Venue Layout Designer';
},
onError: function (error) {
console.error(error);
},
};
</script>
<!-- Bundled app script (do not modify) -->
<script type="module" src="/assets/standalone-designer.js"></script>
</body>
</html>For the full list of constructor options, methods, and callbacks see the Designer API Reference.
Picker
Quick Start
Open picker.html and edit the <script> block that sets window.SeatSquirrelConfig:
<script>
window.SeatSquirrelConfig = {
onReady: function () {
console.log('Picker ready!');
// Load your layout and set availability
// fetch('/api/layouts/123')
// .then(r => r.json())
// .then(data => {
// SeatSquirrel.picker.loadLayout(data);
// SeatSquirrel.picker.setAvailability({ mode: 'by-slug', ...availabilityData });
// });
},
onSelectionChanged: function (data) {
console.log('Selected:', data.totals.count, 'items');
console.log('Total:', data.totals.amount, 'cents');
},
onComplete: function (data) {
// Handle checkout
console.log('Checkout:', data.selections);
},
onError: function (error) {
console.error('Error:', error.message);
},
};
</script>Picker Complete Example
<!DOCTYPE html>
<html>
<head>
<title>Select Your Seats</title>
</head>
<body>
<div id="seatsquirrel-picker-root"></div>
<script>
window.SeatSquirrelConfig = {
onReady: async function () {
const layout = await fetch('/api/layouts/123').then(r => r.json());
SeatSquirrel.picker.loadLayout(layout);
const availability = await fetch('/api/availability/123').then(r =>
r.json(),
);
SeatSquirrel.picker.setAvailability({ mode: 'by-slug', ...availability });
},
onSelectionChanged: function (data) {
document.getElementById('cart-count').textContent =
data.totals.count;
document.getElementById('cart-total').textContent =
'$' + (data.totals.amount / 100).toFixed(2);
},
onComplete: async function (data) {
const response = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
selections: data.selections,
total: data.totals.amount,
}),
});
if (response.ok) {
window.location.href = '/checkout/success';
}
},
onError: function (error) {
console.error(error);
},
};
</script>
<!-- Bundled app script (do not modify) -->
<script type="module" src="/assets/standalone-picker.js"></script>
</body>
</html>For the full list of constructor options, methods, and callbacks see the Picker API Reference.
Best Practices
- Wait for
onReady— never call API methods beforeonReadyfires. - Load layout before setting availability —
setAvailability()requires a loaded layout. - Use slugs — slug-based modes (
setAvailability({ mode: 'by-slug' }),setPricingCategories({ mode: 'update-by-slug' })) are recommended over label-based alternatives since slugs are stable, human-readable identifiers you control. You may also use ID-based identifiers which are globally unique ids set by the Designer during layout creation. - Track unsaved changes — in the Designer use
onLayoutChangedto warn users before navigating away. - Handle errors — always provide an
onErrorcallback to surface issues.