Getting Started
This guide walks you through setting up Templatical Cloud in your application.
Prerequisites
- A Templatical Cloud account with an active plan
- A project and tenant configured in the Cloud dashboard
- The
@templatical/editorpackage installed in your project
Installation
If you haven't already installed the editor, add it along with the cloud dependencies:
npm install @templatical/editor @templatical/media-library pusher-js@templatical/media-library provides the built-in media browser and pusher-js enables real-time collaboration. Both are optional peer dependencies — only needed when using initCloud().
Shadow DOM
initCloud() inherits all shadow-DOM behavior from the editor — mounted inside a Shadow DOM by default for host-CSS isolation. The media browser, AI panels, comments, and version-history UI all teleport into the editor's shadow-aware popover root, so no special handling is needed. Pass shadowDom: false to opt out. See the Shadow DOM guide.
Authentication Endpoint
Cloud features require an authentication endpoint on your server that issues access tokens. The SDK calls this endpoint automatically to obtain and refresh tokens.
Laravel Example
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
Route::post('/api/templatical/token', function (Request $request) {
$response = Http::post('https://templatical.com/api/v1/auth/token', [
'client_id' => config('templatical.client_id'),
'client_secret' => config('templatical.client_secret'),
'tenant' => $request->user()->tenant_id,
]);
return $response->json();
});Node.js Example
app.post('/api/templatical/token', async (req, res) => {
const response = await fetch('https://templatical.com/api/v1/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: process.env.TEMPLATICAL_CLIENT_ID,
client_secret: process.env.TEMPLATICAL_CLIENT_SECRET,
tenant: req.user.tenantId,
}),
});
res.json(await response.json());
});Initialize the Cloud Editor
Replace init() with initCloud() and provide your auth endpoint:
import { initCloud } from '@templatical/editor';
const editor = await initCloud({
container: '#editor',
auth: {
url: '/api/templatical/token',
requestOptions: {
method: 'POST',
credentials: 'same-origin',
},
},
});The auth.url should point to the token endpoint you created above. The SDK handles token refresh automatically.
initCloud() is init() with Cloud's adapters
It authenticates, fetches your plan, builds Cloud's templates / render / versionHistory / savedBlocks / testEmail providers, and then calls init() with them. There is one editor component, one editor core and one header behind both entry points, and the two return the same type — which is what makes "Cloud implements the same interfaces you would" checkable rather than just claimed.
One consequence: the bootstrap runs before the editor mounts, so a failed handshake rejects initCloud() instead of mounting an editor showing an error overlay. Handle it like any other rejected promise. A session that dies later — a token refresh that cannot renew — still surfaces as an overlay, because by then there is an editor to cover.
Configuration Options
initCloud() accepts all the same options as init() (theme, locale, merge tags, custom blocks, etc.) plus Cloud-specific options:
const editor = await initCloud({
container: '#editor',
auth: {
url: '/api/templatical/token',
},
// Cloud features (all optional)
ai: {}, // Enable all AI features
collaboration: { // Enable real-time collaboration
enabled: true,
},
savedBlocks: true, // Cloud-backed (default); false to disable,
// or pass a SavedBlocksProvider to use your own store
// Callbacks
onChange: (content) => { /* template changed */ },
onError: (error) => { /* handle errors */ },
templates: {
onSaved: (template, { trigger }) => { /* trigger: manual | autosave | rename | restore | api */ },
onCreated: (template) => { /* create() resolved — template.id is new */ },
onLoaded: (template) => { /* load() resolved */ },
},
comments: { // omit for Cloud's default; false to disable entirely
onCreated: (comment, { origin }) => { /* origin: local | remote */ },
},
versionHistory: { // omit for Cloud's default; no boolean to disable
onRestored: (template) => { /* restore() resolved */ },
},
onUnmount: () => { /* the editor has been torn down */ },
});Each Cloud-backed capability has its own page: Templates, Rendering, Saved Blocks, Comments, Version History and Test Emails.
Working with Templates
Create a New Template
const template = await editor.create();
// template.id is now available for saving, sharing, etc.
// Optionally seed it:
await editor.create({ name: 'Spring campaign', content });create() takes the same { name?, content? } input init() does.
Load an Existing Template
const template = await editor.load('template-id-here');Save Changes
const template = await editor.save();save() resolves to the stored Template. Rendering is its own provider, so it is separately callable and a save does not pay for a server render on every autosave tick.
Autosave, the unsaved-changes guard and the automatic version every save records are covered in Templates.
Export
const mjml = await editor.toMjml();
const html = await editor.toHtml();Both render server-side, from the saved template — so each call saves first, and a session that has never created a template gets a clear rejection rather than an export of nothing. initCloud() does not take a render provider: see Rendering for what Cloud's output adds over the browser's, and why the key is refused.
Cleanup
When the user navigates away, unmount the editor to clean up WebSocket connections and event listeners:
editor.unmount();Health Check
Verify your Cloud connection is working:
import { performHealthCheck } from '@templatical/core/cloud';
const result = await performHealthCheck({
baseUrl: 'https://templatical.com',
});
console.log(result.overall); // true if all services are reachable
console.log(result.api); // { ok: true, latency: 42 }
console.log(result.websocket); // { ok: true }
console.log(result.auth); // { ok: true }Next Steps
- Authentication — Advanced auth configuration
- AI Assistant — Generate and rewrite content with AI
- Collaboration — Set up real-time co-editing