Blueprint by Tiny
Return to
Return to Tiny.cloudTry TinyMCE for Free
Search by

How to set up the TinyMCE save plugin

Joe Robinson

July 12th, 2021

Written by

Joe Robinson


How-tos & Tutorials





With TinyDrive, you can save and backup your assets like images, videos, and text files. You can use it with a no-cost Community plan. Once set up and configured, Tiny Drive saves assets for you, and also allows you to connect a storage location like Google Drive and Dropbox. With everything you need backed up, you can then insert images and other rich and dynamic content into your work.

Have you also heard of our Save plugin? It’s one of our Open Source plugins.

The Save plugin allows you to save content you’re working on in the editor – it works through a web API. When it’s running in a web application, the Save plugin needs <form> tags wrapped around it. They’re needed because Save sends the contents of the editor as an HTML form, and broadcasts the form as a POST API request.

You then configure a web application to listen for the POST request, process the HTML form, and write the contents to a database of some kind. Sounds easy? Using mostly plain JavaScript (with some syntax from the express extension), it’s possible to try out the Save plugin in TinyMCE to see how it works.

How to test the Save plugin

This demonstration uses Node to create a light demo app. (Node is a platform for building web applications.) Using a small amount of Express syntax, you can write a demo that connects a Node application to our TinyMCE rich text editor Save plugin.

Node simulates a working web application. For the simulated back end, our “database”, so to speak, in this example is just a file. In production, you wouldn’t be using a single file (loading time, security, and the sheer file size are some of the sensible reasons why databases are for production and delivery to end users).

Node is also a fast way to see the web API in action. On the topic of speed, Node also helps with writing a demo quickly, since you don’t need to switch from a client side language to a server side language. You can write everything in JavaScript, and see how a save plugin works.

It’s even possible to use a save shortcut key, like the save as shortcut key in Microsoft Word. Once the Save Plugin is running, press ctrl+s in Windows or command+s if on a macOS to save the contents of the editor. 

1. Setting up Node 

Install  Node , and then open the command line on your workstation. In the terminal window, create a directory for your demo save plugin project. Change into that directory, and then run the command to install and save the express extension:

> mkdir test-save
> cd test-save
> npm install --save express

2. Making the Node application

Include the additional packages required to get the demo application to listen out for the Save plugin POST request. Start by creating an app.js file:

> touch app.js

Open up the file in a text editor, and include some constants to reference later in the JavaScript:

const http = require("http");
const fs = require("fs").promises;
const qs = require("querystring");

These are the  fs http, and  qs  packages. The fs.promises API provides a way for the Node application to listen for and filter GET and POST requests from the Save plugin.

In production, web applications run from a server. For our demo, the local, computer workstation will represent the server. Include some constants that specify the local host address, and a port for the application to broadcast through:

const HOST = "localhost";
const PORT = 8000;
const SERVE_URL = `http://${HOST}:${PORT}`;

The SERVE_URL constant provides an easier way to reference the application’s address without having to type $HOST and $PORT together.

3. Configure the Node application to listen for changes

Set up another constant to listen for the requests, and to send responses. We’ve named ours, requestListener :

const requestListener = function (req, res) {
  if (req.method === "POST") {
    if (req.url === "/") {
      const chunks = []; /* turn the chunks variable into an empty array, which will immediately be populated by the information broadcast by the Save plugin once it runs */

This tells the application to listen for any POST requests from the “/” address (you’ll set this up when configuring the Save plugin). The chunks function converts the data into an array. The POST request needs to be in a format that Node can understand and interpret:

   .on("data", (data) => chunks.push(data)) /* append data to the chunks variable */
    .on("end", () => {
       const buf = Buffer.concat(chunks); /* The buffer class transforms data into a binary stream. We then want to connect the parts together with a concatenate function.*/
       const decoded = decodeURIComponent(buf); /* get the decoded version of the buffered integers */
      const parsed = qs.parse(decoded); /* This is the querystream working - it decodes the buffer stream */

       fs.writeFile(__dirname + "/saved-content.html", parsed.content)
             .then(() => {
            res.writeHead(301, {
             "Content-Type": "text/html",
            Location: SERVE_URL,

The essential steps the Node application follows is: push the chunked data into a variable, and then end the POST request process. Next, concatenate, decode, parse, and write the content to the file specified (“/saved-content.html”). Then finish with a redirection code sent back to the “server” (the localhost on the workstation), and end the response.

Handling the Save plugin is one thing, but setting up the Node application to actually open and run an html rich text editor requires some more JavaScript.

These steps tell the Node application to listen for a GET request, and if one is detected, open the index.html file, send a 200 code to the “server”, and then end the process:

if (req.method === "GET") { /* Load the homepage from the file system. */
   if (req.url === "/") {
      fs.readFile(__dirname + "/index.html")
        .then((contents) => {
          res.writeHead(200, {
            "Content-Type": "text/html",

4. Add in some error handling

Because Save plugin app must work as closely to a real, production case as possible, include some error handling statements:

/* directly after the “res.end(""); })” line */
.catch((error) => {
             res.writeHead(500, {
                "Content-Type": "text/html",

Error handling in our demo application catches any problems or faults. Add in error handling for the GET request:


/* directly after the second “res.end(""); })” line for the GET req.method */
.catch((error) => console.error(error));
    } else {
      // Provide not found errors for all other pages.
      res.end("Not Found");

And then directly after this line, one more error handling statement will provide some feedback in case of a 404 error:

if (req.method !== "GET" && req.method !== "POST") {
  res.end("Not Found");

Finally, add the JavaScript that creates a server for our Node application to run from - in this case, on your workstation:

const server = http.createServer(requestListener);

server.listen(PORT, HOST, () => {
  console.log(`Server is running on ${SERVE_URL}`);

5. Include the TinyMCE rich text editor

The index file that your Node application uses to load TinyMCE needs to be saved in the same directory as the app.js file. Create an index.html file next to the app.js file. 

> touch index.html

Open it the file in a text editor, and enter in the TinyMCE reference (with your API key) and the TinyMCE initialisation script:

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <script src="" referrerpolicy="origin"></script>
    <script type="text/javascript">
          selector: "textarea",
          plugins: [
            "lists checklist link image print preview",
            "code fullscreen",
            "insertdatetime media paste save"
          toolbar: "save | preview | insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | checklist",

Wrap the div tag that contains the TinyMCE rich text editor class in a form tag. Modify the form tag to broadcast a POST action with a method, and include a “/” with an action:

<form method="POST" action="/">
    <textarea name="content"></textarea>

Save and close the file.

6. Set up a file for saving your content

Without a place to save your content, the Node application will either become stuck, or return a “not found” error. Create the “saved-content.html” file in your demo application directory. Ensure the file name spelling matches the file name spelling in the app.js file:

> touch saved-content.html

7. Launch the application, and try out the Save plugin

To launch your application:

  1. Run ‘node app.js’ from the command line. You should receive a message: Server is running on http://localhost:8000
  2. Click on the URL, or highlight it, copy, and then paste it into a browser. 
  3. Press the enter key to load the Node application. TinyMCE should then appear. Type into the text editor to start creating content.
  4. When you’re ready, click the save button along the menu bar. The page will refresh.

Your content is now saved in the saved-content.html file. You can open the file in a browser to view it. You can also try out the save shortcut key. After writing content into your editor, use the command key + s or control key + s. The page reloads, and your file saves to the “database”.

A complete copy of the app.js file is  available as a code pen  if you get stuck on any of the steps. 

For more information about saving with TinyDrive, you can  visit our documentation , or talk to our Sales team  for support.

byJoe Robinson

Technical and creative writer, editor, and a TinyMCE advocate. An enthusiast for teamwork, open source software projects, and baking. Can often be found puzzling over obscure history, cryptic words, and lucid writing.

Related Articles

  • How-tos & Tutorials

    Migrating from Quill to TinyMCE

    by Joe Robinson in How-tos & Tutorials
Subscribe for the latest insights served straight to your inbox every month.

Deploy TinyMCE in just 6 lines of code

Built to scale. Developed in open source. Designed to innovate.

Begin with your FREE API Key
Tiny Editor
Tiny logo
Privacy Policy - Terms of Use© 2021 Tiny Technologies Inc.TinyMCE® and Tiny® are registered trademarks of Tiny Technologies, Inc.


  • TinyMCE
  • Tiny Drive
  • Customer Stories
  • Pricing