DEV Community

Faisal Malik
Faisal Malik

Posted on

Build an E-Signature with React, TailwindCSS, and Django Python

Learn how to create a fully functional e-signature application using React for the frontend, TailwindCSS for styling, and Django REST Framework to save signatures as PNG images. Perfect for contracts, forms, or any web application needing digital signatures.

Introduction

Digital signatures are increasingly common in web apps for signing forms, agreements, or contracts online. In this tutorial, we will build an e-signature app where users can draw their signature on a canvas and save it on the server as an image file.

We’ll use:

  • React for the frontend
  • TailwindCSS for styling
  • react-signature-canvas for drawing the signature
  • Django as a backend to receive and save the signature

By the end, you’ll have a full-stack solution ready for integration into any project.

1️⃣ Frontend Setup: React + TailwindCSS
Step 1: Install dependencies

First, make sure you have a React app. If not:

npm install react-signature-canvas
Enter fullscreen mode Exit fullscreen mode

(Optional but recommended)

npm install trim-canvas
Enter fullscreen mode Exit fullscreen mode

Step 2: Create SignaturePad Component

Create a new file: src/pages/SignaturePad.jsx

import { useRef } from "react";
import SignatureCanvas from "react-signature-canvas";
export default function SignaturePage() {
  const sigRef = useRef(null);
  const clearSignature = () => {
    if (!sigRef.current) return;
    sigRef.current.clear();
  };
  const saveSignature = () => {
    if (!sigRef.current || sigRef.current.isEmpty()) {
      alert("Please sign first");
      return;
    }
    const canvas = sigRef.current.getCanvas();
    const dataUrl = canvas.toDataURL("image/png");
    console.log("Signature Base64:", dataUrl);
    // Needs to do: send to backend
  };
  return (

    <div className="min-h-screen flex items-center justify-center">
      <div className=" bg-gray-100 rounded-lg shadow-md p-6 w-full max-w-lg">
        <h1 className="text-2xl font-semibold mb-4 text-center">
          E-Signature
        </h1>
        <div className="bg-white border rounded mb-4">
          <SignatureCanvas
            ref={sigRef}
            penColor="black"
            canvasProps={{
              width: 500,
              height: 200,
              className: "w-full h-auto"
            }}
          />
        </div>
        <div className="flex justify-between">
          <button
            onClick={clearSignature}
            className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
          >
            Clear
          </button>
          <button
            onClick={saveSignature}
            className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
          >
            Save
          </button>
        </div>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

2️⃣ Backend Setup: Django REST Framework
Step 1: Install Django & DRF

pip install django djangorestframework
Enter fullscreen mode Exit fullscreen mode

Create a Django project and app:

django-admin startproject e-sign
cd e-sign
python manage.py startapp api
Enter fullscreen mode Exit fullscreen mode

Add rest_framework and your app to INSTALLED_APPS in settings.py

INSTALLED_APPS = [
    ....,
    'rest_framework',
    'api',
]
Enter fullscreen mode Exit fullscreen mode

Step 2: Create API Endpoint

Create a view to save the signature:

# api/views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import os
import base64
from django.conf import settings

class SaveSignature(APIView):
    def post(self, request):
        data_url = request.data.get("signature")
        if not data_url:
            return Response({"error": "No signature provided"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            header, encoded = data_url.split(",", 1)
            binary_data = base64.b64decode(encoded)
        except Exception:
            return Response({"error": "Invalid signature format"}, status=status.HTTP_400_BAD_REQUEST)

        save_path = os.path.join(settings.BASE_DIR, "signatures")
        os.makedirs(save_path, exist_ok=True)
        # Save with unique filename
        import uuid
        file_name = os.path.join(save_path, f"{uuid.uuid4()}.png")

        with open(file_name, "wb") as f:
            f.write(binary_data)

        return Response({"message": f"Signature saved at {file_name}"}, status=status.HTTP_201_CREATED)
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • data_url.split(",", 1) separates the Base64 header from the actual data.
  • base64.b64decode converts the Base64 string back to binary data.
  • We save the signature in a signatures folder using a UUID filename to avoid collisions.

Step 3: Setup URLs

# api/urls.py
from django.urls import path
from .views import SaveSignature

urlpatterns = [
    path("save-signature/", SaveSignature.as_view(), name="save-signature"),
]
Enter fullscreen mode Exit fullscreen mode

Step 4: Include the app URLs in the project urls.py

# e-sign/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", include("api.urls")),
]
Enter fullscreen mode Exit fullscreen mode

3️⃣ Connecting React to Django

Your saveSignature function in React sends a POST request with the signature in Base64 format. Django receives it, decodes it, and saves it as a PNG.

const saveSignature = async () => {
    if (!sigRef.current || sigRef.current.isEmpty()) {
      alert("Please sign first");
      return;
    }

    const canvas = sigRef.current.getCanvas();
    const dataUrl = canvas.toDataURL("image/png");

    try {
      const res = await fetch("http://127.0.0.1:8000/api/save-signature/", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ signature: dataUrl }),
      });

      const result = await res.json();
      console.log(result);
      alert(result.message);
    } catch (err) {
      console.error(err);
      alert("Failed to save signature");
    }
  };
Enter fullscreen mode Exit fullscreen mode

Now, running both the frontend (npm run dev) and backend (python manage.py runserver) will allow users to draw, clear, and save signatures.

Conclusion

In this tutorial, you learned how to:

  • Create a signature pad using react-signature-canvas
  • Build a Django REST API to save signatures as PNG images
  • Connect frontend and backend for a full-stack e-signature app
  • This setup can be used for contracts, forms, and any web app requiring digital signatures.

Top comments (0)