Syncing to your own backend
Build a backend API and connect it to Pindrop with a custom adapter
Pindrop stores comments in localStorage by default. To sync them across devices and users, point it at your own API using an adapter.
You need two things: a backend that stores and returns comments, and an adapter that connects Pindrop to it.
What your API needs
Two endpoints are enough:
| Method | Path | Description |
|---|---|---|
GET | /api/comments | Return all comments as a JSON array |
POST | /api/comments | Replace the stored comments with the request body |
Pindrop passes the full comment array on every save, so you don't need separate create/update/delete endpoints.
Example: Next.js API route
// app/api/comments/route.ts
import { NextResponse } from 'next/server'
let comments: unknown[] = [] // replace with your database
export async function GET() {
return NextResponse.json(comments)
}
export async function POST(req: Request) {
comments = await req.json()
return NextResponse.json({ ok: true })
}Replace the in-memory comments array with a real database write — Postgres, SQLite, MongoDB, whatever you use.
Wire the adapter
import { Pindrop } from 'pindrop.js'
Pindrop.init({
storageKey: 'my-app',
adapter: {
load: async () => {
const res = await fetch('/api/comments')
return res.json()
},
save: async (comments) => {
await fetch('/api/comments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(comments),
})
},
},
})That's all the adapter needs. Pindrop handles unread state, merging, and UI — you just store and return the array.
Live sync for multiple users
If multiple users share the same page, you can poll your API to pick up comments left by others without a page reload:
const pindrop = Pindrop.init({ storageKey: 'my-app', adapter })
setInterval(async () => {
const remote = await fetch('/api/comments').then(r => r.json())
pindrop.applyRemoteComments(remote)
}, 5000)applyRemoteComments merges remote comments into the local store — new ones appear as unread, existing ones preserve the current user's read state.
Scoping comments to a URL
If your backend serves multiple pages, store comments per URL:
const url = encodeURIComponent(location.pathname)
const adapter = {
load: async () => {
const res = await fetch(`/api/comments?url=${url}`)
return res.json()
},
save: async (comments) => {
await fetch(`/api/comments?url=${url}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(comments),
})
},
}Then filter by url in your API handler.
Last updated March 29, 2026