Skip to main content

How to implement a server to host snapshots

The library allows users to take chart snapshots via buttons located on the top toolbar.

Take snapshot menu

Snapshots taken through Copy link, Open in new tab, and Tweet image options are stored on your servers. This guide shows how to implement a Node.js server to host snapshots generated by the library.

By the end of this guide, you'll have a server that:

  • Sends a POST request with a snapshot.
  • Saves the snapshot to a local folder.
  • Returns a URL you can use to access the snapshot later.

You can use tools like curl, Postman, or a frontend form to upload the snapshot.

Before you start

Consider taking the following steps before proceeding with the guide:

  1. Set up the Widget Constructor and run the library. For more information, refer to the First run tutorial.

  2. Make sure you have installed Node.js and npm (comes with Node.js).

  3. Create a new folder and run the following commands.

    npm init -y
    npm install express multer cors
  4. Create a JavaScript file that will contain the server code. In this example, assume it's snapshotserver.js.

Create a server

1. Import required modules

snapshotserver.js
// Import Express framework for creating the server
const express = require('express');

// Enable Cross-Origin Resource Sharing (CORS)
// It allows your server to accept requests from the library
const cors = require('cors');

// Middleware for handling file uploads
const multer = require('multer');

// Modules for working with the file system
const path = require('path');
const fs = require('fs');

2. Initialize app and create uploads folder

snapshotserver.js
const app = express();
const port = 3001;

// `cors()` allows your app to accept requests from anywhere
app.use(cors());

// Check if `uploads/` exists
// If not, it creates the folder
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}

3. Configure Multer

snapshotserver.js
// Configure Multer storage: set destination folder and filename format
const storage = multer.diskStorage({
// Set the destination directory for uploaded files
destination: (req, file, cb) => cb(null, uploadDir),

// Add a timestamp to the original filename to prevent name collisions
filename: (req, file, cb) => {
const timestamp = Date.now();
cb(null, `${timestamp}-${file.originalname}.png`);
},
});

// Accept only image files based on the MIME type
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) cb(null, true);
else cb(new Error('Only image files are allowed'), false);
};

// Create the upload middleware with custom storage and file filter
const upload = multer({ storage, fileFilter });

4. Serve uploaded files

snapshotserver.js
// Serve static files from the uploads directory at the `/uploads` URL path
app.use('/uploads', express.static(uploadDir));

This allows users to access uploaded snapshots via a URL like http://localhost:3001/uploads/<filename>.

5. Handle upload endpoint

snapshotserver.js
// Handle image upload at the `/snapshot` endpoint
app.post('/snapshot', upload.single('preparedImage'), (req, res) => {
// Return an error if no file was uploaded
if (!req.file) {
return res.status(400).send('No image uploaded.');
}

// Create the public URL for the uploaded snapshot
const imageUrl = `${req.protocol}://${req.get('host')}/uploads/${req.file.filename}`;
console.log(`Received image: ${req.file.originalname}`);

// Respond with the snapshot URL where snapshot can be accessed
res.status(200).send(imageUrl);
});

6. Start the server

snapshotserver.js
app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`);
});

How to use the server

Use the following node command:

node snapshotserver.js

This command outputs the following:

Listening at http://localhost:3001

How to test the server

Use curl to test the server:

curl -i -X POST http://localhost:3001/snapshot \
-F preparedImage=@/path/to/your/image.png

Generated output should be:

http://localhost:3001/uploads/1716379138459-image.png

At this point, you can open this link in a browser and see the image.

How to connect the server to the library

Once your server is deployed and accessible from the internet, pass its /snapshot endpoint to the snapshot_url property in your Widget Constructor. This allows the library to send chart snapshots to your server and receive public image URLs in return.

main.js
const datafeed = new Datafeeds.UDFCompatibleDatafeed("https://demo-feed-data.tradingview.com");
new TradingView.widget({
container: "chartContainer",
locale: "en",
library_path: "charting_library/",
datafeed: datafeed,
symbol: "AAPL",
interval: "1D",
snapshot_url: "https://myserver.com/snapshot",
})

Complete code

At this stage, you have implemented a functional server.

Expand to view the complete code for the snapshot server in snapshotserver.js.

// Import required modules
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();
const port = 3001;

// Use CORS to allow requests from the frontend
app.use(cors());

// Ensure the uploads directory exists
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}

// Multer storage config
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, uploadDir),
filename: (req, file, cb) => {
const timestamp = Date.now();
cb(null, `${timestamp}-${file.originalname}.png`);
},
});

// Accept only image files
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) cb(null, true);
else cb(new Error('Only image files are allowed'), false);
};

const upload = multer({ storage, fileFilter });

// Serve static files from the uploads directory
app.use('/uploads', express.static(uploadDir));

// Endpoint to receive `preparedImage`
app.post('/snapshot', upload.single('preparedImage'), (req, res) => {
if (!req.file) {
return res.status(400).send('No image uploaded.');
}

const imageUrl = `${req.protocol}://${req.get('host')}/uploads/${req.file.filename}`;
console.log(`Received image: ${req.file.originalname}`);
res.status(200).send(imageUrl); // Respond with the image URL
});

// Endpoint to receive `image`
app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`);
});