/how-to-build-replit

How to Build a Insurance claims tool with Replit

Learn how to build a simple, efficient insurance claims tool using Replit. Follow this step-by-step guide to streamline development and boost productivity.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

How to Build a Insurance claims tool with Replit

To build an insurance claims tool on Replit, create a simple Node.js + Express + SQLite app with a React frontend. The backend will handle claim storage and APIs, and the frontend will let users submit claims and review their statuses. Replit handles both client and server in one project easily. You’ll use the “Node.js” template as the base, add a frontend folder for React, store your database safely in a database file, and keep secrets like API keys in Replit’s “Secrets” tab. This step-by-step structure actually works in Replit’s hosted environment and is durable enough for demonstration or small-scale use.

 

Project Setup

 

Create a New Repl: choose “Node.js”. Inside this Repl, you’ll have a default index.js file. That file will run your backend server.

Then, create a folder named client. This will hold your React app. Replit can run both, but the Node server will serve API requests, and React will handle the UI (you can preview through the main URL Replit provides).

 

// In the Shell tab on Replit:
npm init -y
npm install express sqlite3 cors
npx create-react-app client

 

Backend: Setting up Express

 

In your main index.js file (that Replit created automatically):

 

// index.js
const express = require('express')
const sqlite3 = require('sqlite3').verbose()
const cors = require('cors')

const app = express()
app.use(express.json())
app.use(cors())

// Create or open database file
const db = new sqlite3.Database('./database.db')

// Create claims table once
db.run('CREATE TABLE IF NOT EXISTS claims (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, policyNumber TEXT, description TEXT, status TEXT)')

// Endpoint to create new claim
app.post('/api/claims', (req, res) => {
  const { name, policyNumber, description } = req.body
  const status = 'Pending'
  db.run('INSERT INTO claims (name, policyNumber, description, status) VALUES (?, ?, ?, ?)', [name, policyNumber, description, status], function(err) {
    if (err) return res.status(500).json({ error: err.message })
    res.json({ id: this.lastID, name, policyNumber, description, status })
  })
})

// Endpoint to list all claims
app.get('/api/claims', (req, res) => {
  db.all('SELECT * FROM claims', [], (err, rows) => {
    if (err) return res.status(500).json({ error: err.message })
    res.json(rows)
  })
})

// Endpoint to update claim status
app.put('/api/claims/:id', (req, res) => {
  const { status } = req.body
  db.run('UPDATE claims SET status=? WHERE id=?', [status, req.params.id], function(err) {
    if (err) return res.status(500).json({ error: err.message })
    res.json({ changed: this.changes })
  })
})

// Start server
const PORT = process.env.PORT || 3000
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))

 

Make sure your package.json file includes a start command (Replit uses this to run your Repl). Open package.json and add:

 

"scripts": {
  "start": "node index.js"
}

 

Frontend: Building the Client

 

Navigate manually to client/src in your Replit file tree. Replace the contents of App.js with something basic that connects to your backend API.

 

// client/src/App.js
import React, { useState, useEffect } from 'react'

function App() {
  const [claims, setClaims] = useState([])
  const [form, setForm] = useState({ name: '', policyNumber: '', description: '' })

  useEffect(() => {
    fetch('http://localhost:3000/api/claims')
      .then(res => res.json())
      .then(setClaims)
  }, [])

  const handleSubmit = async (e) => {
    e.preventDefault()
    const res = await fetch('http://localhost:3000/api/claims', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(form)
    })
    const newClaim = await res.json()
    setClaims([...claims, newClaim])
  }

  return (
    <div>
      <h2>Insurance Claims Tool</h2>
      <form onSubmit={handleSubmit}>
        <input placeholder="Name" onChange={e => setForm({ ...form, name: e.target.value })} />
        <input placeholder="Policy Number" onChange={e => setForm({ ...form, policyNumber: e.target.value })} />
        <textarea placeholder="Description" onChange={e => setForm({ ...form, description: e.target.value })} />
        <button type="submit">Submit Claim</button>
      </form>

      <h3>Submitted Claims</h3>
      <ul>
        {claims.map(c => (
          <li key={c.id}>{c.name} – {c.policyNumber} – {c.status}</li>
        ))}
      </ul>
    </div>
  )
}

export default App

 

Running Frontend and Backend Together

 

Replit always runs one process by default. So to run both React and your API server, the practical way is to run the backend (so `index.js` keeps live for database route access) and use the React development server only during editing. In the Shell:

 

cd client
npm start

 

You might get a prompt saying the port is already in use because Replit uses port 3000 for the Node server. Change your React app to run on a different port by editing client/package.json and adding this line under scripts:

 

"start": "PORT=3001 react-scripts start"

 

That way, your API stays available at http://localhost:3000/api/claims and your frontend locally at http://localhost:3001. In production or when showing the tool, you can instead build the React app and serve it directly from Express by adding inside index.js (below your existing routes):

 

// Add this only after building your React app with: cd client && npm run build
const path = require('path')
app.use(express.static(path.join(__dirname, 'client/build')))
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'client/build', 'index.html'))
})

 

Database and Secrets on Replit

 

SQLite works well for small tools because it stores all data in database.db. Replit persists that file between runs. If you ever add external APIs (SMS, email, etc.), use Replit’s Secrets panel on the left sidebar — never store tokens directly in code, always reference them with process.env.MY_SECRET_KEY.

 

Deploying

 

In Replit, click the Deploy button on top right → choose “Static” if you only need frontend, or “Always On” if you need backend running continuously. Always test by opening the web preview tab and submitting a new claim to verify that the form talks to your API correctly.

 

This approach is the most practical way to build and demo a small insurance claims tool using Replit — it keeps the structure simple, uses features Replit naturally supports, and avoids common pitfalls like conflicting ports, lost database files, or exposing secrets.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Contact Us

How to Handle Insurance Claim Submissions with Express and Replit



import express from "express";
import multer from "multer";
import { v4 as uuidv4 } from "uuid";
import Database from "@replit/database";

const db = new Database();
const app = express();
const upload = multer({ dest: "uploads/" });

app.use(express.json());

app.post("/api/claims", upload.single("evidence"), async (req, res) => {
  try {
    const { policyId, claimantName, claimType, description, amount } = req.body;

    if (!policyId || !claimantName || !claimType || !amount) {
      return res.status(400).json({ error: "Missing required fields" });
    }

    const claimId = uuidv4();
    const claimData = {
      claimId,
      policyId,
      claimantName,
      claimType,
      description: description || "",
      amount: parseFloat(amount),
      filePath: req.file ? req.file.path : null,
      status: "pending",
      createdAt: new Date().toISOString()
    };

    await db.set(`claim:${claimId}`, claimData);
    res.status(201).json({ message: "Claim submitted successfully", claimId });
  } catch (err) {
    console.error("Error saving claim:", err);
    res.status(500).json({ error: "Server error while submitting claim" });
  }
});

app.get("/api/claims/:id", async (req, res) => {
  const claim = await db.get(`claim:${req.params.id}`);
  if (!claim) return res.status(404).json({ error: "Claim not found" });
  res.json(claim);
});

app.listen(3000, () => {
  console.log("Insurance claim service running on port 3000");
});

How to Handle Insurance Claim Webhooks Securely with Replit



import express from "express";
import crypto from "crypto";
import Database from "@replit/database";

const app = express();
const db = new Database();

app.use(express.json());

// Verify webhook signatures from external insurance API
function verifySignature(req, secret) {
  const signature = req.headers["x-insurance-signature"];
  const payload = JSON.stringify(req.body);
  const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
  return signature === expected;
}

// This route listens for external claim status updates (fraud detection, auto-adjustment, etc.)
app.post("/webhook/claim-status", async (req, res) => {
  const secret = process.env.INSURANCE_WEBHOOK_SECRET;
  if (!verifySignature(req, secret)) return res.status(403).json({ error: "Invalid signature" });

  const { claimId, newStatus, reason } = req.body;
  if (!claimId || !newStatus) return res.status(400).json({ error: "Invalid payload" });

  const claimKey = `claim:${claimId}`;
  const claim = await db.get(claimKey);
  if (!claim) return res.status(404).json({ error: "Claim not found" });

  claim.status = newStatus;
  claim.statusReason = reason || null;
  claim.updatedAt = new Date().toISOString();

  await db.set(claimKey, claim);
  res.json({ message: "Claim status updated", claimId, newStatus });
});

app.listen(3001, () => {
  console.log("Webhook listener active on port 3001");
});

How to Automate Fraud Checks for Insurance Claims with Replit



import fetch from "node-fetch";
import Database from "@replit/database";

const db = new Database();

async function runFraudCheck() {
  const allClaims = await db.list("claim:");
  for (const key of allClaims) {
    const claim = await db.get(key);
    if (claim.status === "pending") {
      try {
        const response = await fetch("https://external-fraud-api.example.com/check", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${process.env.FRAUD_API_KEY}`
          },
          body: JSON.stringify({ claimId: claim.claimId, amount: claim.amount, claimant: claim.claimantName })
        });
        const result = await response.json();
        if (result.flagged) {
          claim.status = "review";
          claim.statusReason = "Potential fraud detected";
        } else {
          claim.status = "approved";
        }
        claim.updatedAt = new Date().toISOString();
        await db.set(key, claim);
      } catch (err) {
        console.error("Fraud check failed for claim:", claim.claimId, err);
      }
    }
  }
}

runFraudCheck();

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Contact Us
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Best Practices for Building a Insurance claims tool with Replit

The best practice for building an insurance claims tool on Replit is to structure your project clearly — separate backend and frontend code, handle secrets properly using Replit’s Secrets tab, and use persistent storage like Replit’s built-in Database or an external one via environment variables. Build your backend (for example, using Node.js + Express or Python + Flask/FastAPI) in a file such as server.js or main.py, build your frontend (React, or a simple HTML/CSS/JS interface) in a separate folder, and connect them through defined APIs. Replit supports deployments, so you can use its “Deployments” feature for persistent uptime and easier sharing.

 

Project Structure

 

Use a clear folder structure to stay organized:

  • backend/ — for all your server and logic files (for claim handling, validations, database).
  • frontend/ — for user interface (claim submission form, claim status page).
  • replit.nix — auto-managed by Replit to install necessary dependencies.
  • .env (automatically managed) — use Replit's “Secrets” tab instead of manually creating this file.

 

Basic Backend Setup (Node + Express)

 

Create a file named backend/server.js inside your project. This is where your API logic lives.

// backend/server.js

import express from "express"
import cors from "cors"
import bodyParser from "body-parser"

const app = express()
app.use(cors())
app.use(bodyParser.json())

// Example endpoint: claim submission
app.post("/api/claims", (req, res) => {
  const { policyNumber, incidentDescription, claimAmount } = req.body
  if (!policyNumber || !claimAmount) {
    return res.status(400).json({ message: "Missing required fields" })
  }

  // In real projects, you'd save this to a persistent database
  console.log("Received claim:", req.body)
  res.status(201).json({ success: true, message: "Claim submitted successfully" })
})

// Example endpoint: list all claims
app.get("/api/claims", (req, res) => {
  // Replace with database fetch
  res.json([{ policyNumber: "ABC123", status: "processing" }])
})

app.listen(3000, () => {
  console.log("Server running on port 3000")
})

Where to put it: Inside backend/server.js. Replit will run it as the main entry point if you set the Run command to node backend/server.js in the “Shell” or “Run” settings.

 

Frontend Setup

 

If you want a simple frontend for submitting claims, create frontend/index.html with a basic form that hits your backend API.

<!-- frontend/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>Insurance Claim Form</title>
  </head>
  <body>
    <h2>Submit Your Claim</h2>
    <form id="claimForm">
      <input type="text" name="policyNumber" placeholder="Policy Number" required />
      <input type="text" name="incidentDescription" placeholder="Describe incident" required />
      <input type="number" name="claimAmount" placeholder="Claim Amount" required />
      <button type="submit">Submit</button>
    </form>

    <p id="response"></p>

    <script>
      const form = document.getElementById("claimForm")
      form.addEventListener("submit", async (e) => {
        e.preventDefault()

        const data = {
          policyNumber: form.policyNumber.value,
          incidentDescription: form.incidentDescription.value,
          claimAmount: form.claimAmount.value,
        }

        // Replit's backend runs on localhost:3000 while previewing
        const res = await fetch("/api/claims", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(data)
        })

        const result = await res.json()
        document.getElementById("response").innerText = result.message
      })
    </script>
  </body>
</html>

Where to put it: Inside frontend/index.html. When you preview your app in Replit, open this file or configure Replit to serve frontend via static middleware if you want to combine the two layers.

 

Serve Frontend from Backend (Optional for Simplicity)

 

If you prefer a single app (no separate frontend develop command), serve the HTML file right from Express. Add this inside your server.js before your app.listen line:

// Serve static files
import path from "path"
import { fileURLToPath } from "url"
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

app.use(express.static(path.join(__dirname, "../frontend")))

Now, visiting the Replit preview URL will show your form served by the same backend.

 

Using Secrets Safely

 

Never hardcode keys or database credentials. Go to Replit’s sidebar → click the 🔒 Secrets icon → add items like DB_URI, ADMIN_TOKEN. Access them in Node like this:

const dbUri = process.env.DB_URI

This ensures sensitive information isn’t visible in your code or public Repls.

 

Connecting a Database

 

For production-level claims data, you can connect to MongoDB Atlas (which has a free tier). You’ll store your database link as a secret and use Mongoose:

import mongoose from "mongoose"

mongoose.connect(process.env.DB_URI)
  .then(() => console.log("Database connected"))
  .catch(err => console.error(err))

// Example model
const Claim = mongoose.model("Claim", new mongoose.Schema({
  policyNumber: String,
  incidentDescription: String,
  claimAmount: Number,
  status: { type: String, default: "submitted" }
}))

// Inside POST endpoint, replace console.log with save:
const claim = new Claim(req.body)
await claim.save()
res.status(201).json({ success: true })

 

Deploying in Replit

 

Once things run correctly, open the Deployments tab on the left sidebar in Replit, select Always On or Static deployment (depending on your plan). This keeps your insurance tool live, so users can submit claims even when you’re not online.

 

Common Pitfalls (and Fixes)

 

  • Not using Secrets properly: Never store credentials in code – always use Replit Secrets.
  • Forgetting port binding: Replit exposes your app automatically, so always listen on process.env.PORT || 3000 if hosting externally.
  • Trying to use local file writes: Filesystem changes reset when Replit restarts. Use DB instead for persistent storage.
  • Relying only on Preview for routing: Preview rewrites paths; test endpoints directly or deploy to see real routing behavior.

 

By structuring your Replit project this way — clear separation, secure secrets, and stable endpoints — you create a maintainable, deployable, and realistic insurance claims tool that behaves predictably even beyond demo level.

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022