Do not use LocalObjectStoragePipeline in production.
Use a custom API-backed pipeline and register it through a CKEditor plugin.
Step 1: create a custom storage pipeline
import type { GruntObjectStoragePipeline } from "@grunt/ckeditor5-grunt/grunt";
export class CustomStoragePipeline implements GruntObjectStoragePipeline {
async saveCommit(key: string, commit: string): Promise<void> {
await fetch(`/api/grunt/${key}/commit`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ commit })
});
}
async saveSvg(key: string, svg: string): Promise<void> {
await fetch(`/api/grunt/${key}/svg`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ svg })
});
}
async getCommit(key: string): Promise<string> {
const response = await fetch(`/api/grunt/${key}/commit`);
if (!response.ok) throw new Error("Failed to load commit");
const data = await response.json();
return data.commit;
}
async getSvg(key: string): Promise<string | null> {
const response = await fetch(`/api/grunt/${key}/svg`);
if (response.status === 404) return null;
if (!response.ok) throw new Error("Failed to load svg");
const data = await response.json();
return data.svg ?? null;
}
}
You can add:
- Authentication headers
- JWT handling
- Versioning
- Multi-tenant routing
- Signed URLs
- Retry logic
Step 2: register the pipeline in a plugin
import { Plugin } from "ckeditor5";
import Grunt from "@grunt/ckeditor5-grunt/grunt";
import { CustomStoragePipeline } from "./CustomStoragePipeline";
class CustomGruntPipelinePlugin extends Plugin {
static get pluginName() {
return "CustomGruntPipelinePlugin";
}
static get requires() {
return [Grunt];
}
init() {
const editor = this.editor;
editor.plugins.get("Grunt").setPipeline(new CustomStoragePipeline(editor));
}
}
Step 3: include the plugin in your editor config
ClassicEditor.create(document.querySelector("#editor"), {
plugins: [
Essentials,
Paragraph,
Bold,
Italic,
Grunt,
CustomGruntPipelinePlugin
]
});
Grunt now uses your API for object persistence.
Next: runtime assets
Serve grunt.js and _framework/* correctly.