Resumeboard
Privacy

There is nowhere for your resume to go.

Resumeboard is a set of static files with no backend behind them. There is no account system, no database, and no operator reading what you type. What follows is not a policy written to be reassuring. Every claim names the file it comes from, and you can open that file and read the line.

Who runs this site

Last updated 4 October 2026. Resumeboard is a one-person operation, and none of the facts below belongs to a company.

FactDetail
ServiceResumeboard, a resume builder that runs in your browser.
Site addresshttps://resumeboard.vercel.app
OperatorUtkarsh, an individual. There is no company behind the site: no registration, no company number, no office, no staff, and no co-founder.
Contact mailboxUtkarsh6624@gmail.com, and it is the only address that exists. There are no role addresses, so put a prefix in the subject line: [Privacy], [Legal], [Security], [Abuse], [Press], or [Bug].
LinkedIn/in/utkarsh-choudhary-116a9736a
Governing lawThe laws of India. A dispute goes to the courts competent where the operator resides.

Every word on this page that says we or the operator means one named person. Where a page has to describe an organisation it uses the service name, Resumeboard, and that name labels this site rather than naming a legal person.

One thing about the host is worth pulling out, because it is the only place on this site where a record of a visit can exist at all. The files are served over HTTPS from a static host, and any host has to handle the network request that fetches a page: an IP address, a user agent, a timestamp, and the address you asked for. Utkarsh does not operate that host, does not read its logs, and cannot see them. None of it is joined to your resume, because your resume is never part of a request.

The rules for using the builder, and the promises this site makes about it, are in the Terms of Service. This page describes what is stored and what leaves your machine. That one describes what you may do with the tool, and what we ask in return.

The short version

  • No cookies. The codebase never writes to document.cookie, for preferences, sessions, or anything else.
  • No analytics, no telemetry, no page-view counters, no error-reporting service, no advertising, and no pixels.
  • No account, no sign-in, and no email address collected.
  • No server. The files your browser downloads are the whole application.
  • Your resume is written to storage inside your own browser and is never transmitted.
  • Exactly one feature is designed to reach another host: PDF import, which downloads a reader from cdnjs.cloudflare.com after you choose it, and shows you both addresses before it starts.

The in-app privacy dialog in the topbar overflow menu says the same three things in three sentences. If the two ever disagree, the source files on this page are the ones that decide which of them is right.

What is stored, and where

When you type, the app saves your resume locally so it is still there when you come back. That save happens in your browser's own storage, keyed to the address you opened the app from. It is written by your browser, readable by your browser, and removable by your browser. The persistence layer is assets/js/core/idb.js, and the code that decides what goes in is assets/js/core/store.js.

IndexedDB: the normal case

IndexedDB is the browser's built-in structured storage. It holds real JavaScript objects rather than text, which is why a full resume, including a photo encoded as a data URL, fits without stuffing a large JSON string into a single key. The app uses exactly one database, with these contents:

  • resumeboard — the database name, at version 1, with a single object store called kv.
  • resume:current — the resume you are editing, as one JSON object.
  • resume:undo — an array of the last 40 states before the current one, so undo survives a closed tab. The app keeps up to 100 in memory during a session and writes the newest 40 to disk.

Those are the literal strings in the source, so you can check them yourself. Open developer tools, go to Application in Chrome and Edge or Storage in Firefox and Safari, find the resumeboard database, and open the kv store. If it is empty, nothing has been saved yet and nothing is being stored.

localStorage: the fallback, and a handful of preferences

Some browsers refuse IndexedDB in private windows, in locked-down configurations, or when a profile is out of room. When that happens the app falls back to localStorage and prefixes every key it writes with rb:. The fallback exists because a resume you cannot save is worse than a resume stored the wrong way, and because losing the whole document to a storage API that threw would be a silent failure.

The trade-off is size. localStorage holds a few megabytes for the entire origin, so a resume with a large photo can hit that ceiling. If the write fails, the app keeps the resume in memory for the life of the tab and tells you so when you press Save now in the command bar. Your work is not lost while the tab is open, and it is not on disk either.

These are all the localStorage keys the app writes, in every mode:

KeyWhat it holds
rb:resume:currentYour resume, but only in the localStorage fallback. In the normal case this key does not exist.
rb:resume:undoThe same undo history, in the fallback only.
rb:themeWhether you chose light or dark, as the word light or dark. The button at the top of this page, the guides, and the theme command in the builder all write it.
resumeboard:themeThe same light or dark choice, written by the theme switch in the builder's topbar and by the one on the home page.
rb:onboarding.v1A single 1, set once you have dismissed the first-run dialog. Delete it and the dialog comes back.
rb:commands:recentsThe few commands you have run recently, so the command bar can suggest them. Command text only; it is never sent anywhere.
rb.typescaleThe type scale you chose with the control in the builder's toolstrip, stored as a ratio.
rb.typescale.baseThe base point size that ratio is measured against, kept separately so a reset cannot lose it.
rb.typescale.appliedThe size actually in force on the document after that ratio is applied.
rb.doczoomThe zoom on the page preview. Layout only; it changes what you see, not what prints.
resumeboard.rail.collapsedWhether the section rail is collapsed.

One more key is read but never written: rb:site-scale, the text size set by the control in this page's header. It is kept in sessionStorage, with localStorage checked only as a fallback, so on a fresh profile the key is absent.

None of these is a cookie. localStorage is readable only by scripts on this origin, is never attached to a request, and is not sent to a server under any circumstance.

sessionStorage, and why none of it lasts

There is some, and here is all of it. rb:seen-session in reset-guard.js and rb:on-visit in boot.js exist for one job: telling a reload apart from an ordinary visit, so that a reload wipes the document instead of landing you back on it. Neither holds anything about you, and the third key, rb:site-scale in assets/js/motion.js, is the text size described above. The reload guard and the builder's own reset both end with sessionStorage.clear(), and closing the tab discards the lot. None of it is ever attached to a request.

What is inside the stored resume

One object, and it is the same object the JSON export writes out. It holds your name, contact details, summary, every section and entry, your design choices, and a few internal fields: a generated id, creation and update timestamps, the template you are using, and the language tag the app read from your browser.

A photo, if you add one, is stored as a data: URL inside that object, so the image is part of the local record and is covered by everything on this page. It is not uploaded anywhere and it is not cached by the service worker.

The app reads your browser's own locale to pick a date format, a page size, and whether a photo is expected in your region. That comes from Intl in the browser. It never asks a server where you are, and there is no IP-derived region anywhere in the codebase.

The network

The builder has no beacon, no sendBeacon, no XMLHttpRequest, no WebSocket, and no first-party endpoint of any kind. Type is set in a system font stack, so there is no web font to download and no third-party font server in your history. The only image loading in the export path refuses to run unless the source is a data: URL, so a photo can never become a request to someone else's server.

The requests the app does make

  • Your browser fetches the app's own files: the HTML, the stylesheets, and the scripts. That is the application, and it is the same for everyone.
  • Nothing else. The editor lives on its own page, #start, and the marketing front door on index.html. Both are ordinary static files served like any other page, so the page you are reading describes every request the app makes.
  • PDF import, described next.

There is no advertising network, no data broker, no retargeting pixel, no analytics product, no session replay, no A/B testing tool, and no hosted font or icon font on any page of this site.

The one exception: PDF import

Reading a PDF needs a real PDF engine, and this project ships none. So when you choose Import, then PDF, then pick a file, the app injects a <script> tag pointing at a pinned version of pdf.js on cdnjs. The import panel shows you both addresses before anything is fetched, and offers a cancel that works for as long as the download is in flight.

These are the exact URLs, taken from the constants at the top of assets/js/ui/importer.js:

https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js

The version is pinned rather than tracked, so the file you receive today is the file anyone receives today. The script tag is added with crossorigin="anonymous" and referrerpolicy="no-referrer", which means the request carries no cookies and no information about the page you came from. The worker is the second address: it is fetched by the browser when the parser starts working, and it is the only reason there are two URLs.

After it loads, the library runs inside your browser and is given the bytes of the file you picked. Your PDF is not uploaded. Nothing about the file, its size, its name, or the text inside it is sent to cdnjs or to anyone else. cdnjs sees one request for two public JavaScript files, in the same way it sees a request from any other site. If you never use the PDF option, the request is never made.

The other three import routes — a .docx file, a .json file, and pasted text — are unpacked and parsed locally and make no request at all.

Share links: the one way your resume can travel

The builder can produce a link that contains your entire resume. It is written into the part of the address after the #, and browsers never send a URL fragment in a request. There is no server to log it, no referrer header to leak it, and no analytics script to see it. The resume is decoded from the link by assets/js/share.js, in your browser, and the fragment is then cleared from the address bar.

Two honest caveats. Anyone who has the link can read the resume, so treat it like a document you handed to someone. And the encoding is not encryption: it is deflate plus base64, which is a compression format, not a cipher.

A photo is left out of the link by default, because a base64 image runs to hundreds of kilobytes and a URL that long stops working in some browsers. It is only included if you explicitly ask, and only when it is under 60,000 characters. The reader refuses any payload over one megabyte.

What the service worker caches

sw.js does two things and nothing else. It makes the app's own static files load from a cache when the network is slow or absent, and it lets a deploy be picked up immediately. The worker only registers when the app is served over http or https; opened from a folder on disk there is no service worker, and the app runs the same way without one.

What is precached

Both front doors are precached in full: the marketing page on index.html and the editor on #start. The list lives at the top of sw.js and holds both documents, every stylesheet and script either one loads, the manifest, and the install icons: 67 paths. With no network at all the editor still opens and still edits, which is the point of the list being that long.

Anything outside that list, such as the writing guides or the example pages, is cached the first time you request it rather than up front. A missing precache entry therefore cannot fail the install, and if one ever does go missing the worker names it in the developer console instead of leaving you to discover it somewhere with no signal.

What it deliberately does not cache

  • Your resume. It is never in an HTTP response, so it can never be in a cache. The worker only ever sees requests the browser makes for files, and your document travels through IndexedDB instead.
  • Anything on another origin. The fetch listener returns immediately when the request URL is not on this site's origin, which is why the lazy pdf.js is never stored by the worker. The browser's own HTTP cache may still hold it, as it would for any script on any page; the app does not manage that.
  • Any fetch or XHR. A fetch() has an empty destination, so it falls outside the list of things the worker will answer and goes straight to the network.
  • Range requests and anything marked no-store.
  • Old versions. The cache name is a hash of the worker's own source combined with the revision stamp written beside it, so a change to the worker or to the list inside it names a new cache, and on activation every older cache is deleted. A deploy that changes a cached file without changing the worker is covered by the stamp, which has to be bumped by hand: a browser only reinstalls a worker whose bytes differ, so without it a corrected stylesheet would keep being served out of the cache. Activation is when the new worker takes over, which is after you accept the offered reload, so until then the old cache is still there and nothing is lost if you never accept.

Navigations are the exception to cache-first: a page request goes to the network first, so you get the current version, and falls back to this browser's own copy of that exact page only if the network fails. It never substitutes one page for another, so opening a page offline that you have never opened before says so plainly rather than quietly handing you the landing page instead. A hard reload skips the cache entirely, so holding Shift while you reload always reaches the network and can never be talked into by a stale copy.

How to delete everything

Deleting is not a request you make to us, because there is no us to make it to. You remove the storage directly and it is gone. Export a backup first if you want to keep it.

From inside the app

The overflow menu in the topbar has Start a new resume. It replaces the stored resume with an empty one, which is the right tool for a shared machine. One caveat, stated plainly: the reset is an ordinary edit, so the resume you had is pushed onto the undo stack rather than destroyed, and the app writes that stack to storage. In other words, Start a new resume empties your document, it does not erase it. The previous version stays readable in resume:undo until the stack rolls over, and the console approach below removes it properly.

From the browser

  • Open developer tools with F12, or by right-clicking and choosing Inspect.
  • Go to Application in Chrome and Edge, or Storage in Firefox and Safari.
  • Under Indexed Databases, delete the database named resumeboard.
  • Under Local Storage, remove every key listed in the table above.
  • Under Cache Storage, delete the caches whose names start with rb-static-. These hold the app's files, not your data; deleting them only means the next visit downloads the app again.
  • Or use the browser's own controls. In Chrome and Edge, Settings → Privacy and security → Third-party cookies → See all site data and permissions, then search for the site's address and delete it. In Safari, Settings → Privacy and security → Manage Website Data, then search for the site.

If you opened the app from a folder on disk

Pages opened from file:// sit on a storage origin of their own and browsers handle that inconsistently. The reliable method is the console. Open the app, press F12, choose the Console, and run:

indexedDB.deleteDatabase('resumeboard') Object.keys(localStorage).filter(k => k.startsWith('rb:')).forEach(k => localStorage.removeItem(k))

Then reload the page. You will get an empty resume, which is the correct result. That is what deleting means.

Things that delete it without asking

  • Clearing browsing data, or site data, in your browser settings.
  • Using a private or incognito window. Anything stored there is discarded when the window closes.
  • Browser eviction under storage pressure. Browsers may reclaim site data when a device is low on space, and there is no notice and no copy kept anywhere else.
  • Opening the app in a different browser, a different profile, or at a different address. Each of those is a separate storage bucket, so each starts empty.
  • Uninstalling the browser, wiping the profile, or changing the folder the files live in.

That is the cost of a local-only app, without hedging: a deletion is complete, because there is no copy on any server, and an accident is not recoverable by anyone.

How to export a backup

A backup is a single JSON file containing the same object the app saves locally, including your design settings. It is plain text you can read in any editor, and it is small enough to email to yourself.

  • Open the builder and use the export button in the topbar, choosing the JSON format. The file is named after your name — alex-morgan.json if your name is Alex Morgan, or resume.json if you have not set one.
  • The file is built in the page as a blob and handed to your browser's own download mechanism. It is not posted anywhere, and there is no upload step to wait for.
  • Keep it somewhere you control: a folder, a cloud drive you chose, an email to yourself. The app has no opinion and keeps no copy.
  • To restore, open the builder on any device and use Import to load the file. It restores your content and your design settings, and it does not restore the undo history.

The example resumes can be downloaded the same way, so you can read the exact shape of the file before writing your own. Start with the software engineer example or the product designer example; both have a Download JSON button.

The exported file is a snapshot. It does not update itself and it is not synced. If you keep editing, export again.

Eviction, and what the app does to reduce it

The resume is written about 400 milliseconds after you stop typing, not on every keystroke, and the app writes once more when the tab is closed or navigated away from, so the last edit before you leave is not the one that gets lost. It also asks the browser, once at start-up, to mark this site's storage as persistent, which is the standard request that stops a browser reclaiming an origin's data when a device runs low on space.

All of that is a local write. There is no automatic export file, no second copy in a folder you did not choose, and no mirror on a server. If the browser evicts the data anyway — and a browser is free to, because the request can be refused — the only version that survives is the one you exported. The example resumes are a good place to see what a finished file looks like before you trust the process with your own.

If you are on a shared computer

The storage belongs to a browser profile at an address, not to you. Anyone who opens the builder in that same profile sees the resume you left there, including your email, phone number, and address. This is the most common way a local-only app leaks, and it has nothing to do with us.

  • Export the JSON first. Do this before anything else, because after a reset the file is the only copy.
  • Use a private or incognito window for anything you would not leave on screen. Nothing in it survives the window closing.
  • When you are done, use Start a new resume in the overflow menu, and if the machine is not yours, delete the database as well. The reset is an ordinary edit: the previous resume moves into the stored undo history, which is written to disk like everything else.
  • Do not leave a share link in the address bar. The link is a complete copy of the resume, and it is readable by anyone who has the string.

Third parties

One, and only on a path you choose. Resumeboard has no advertising network, no data broker, no analytics vendor, no session-replay tool, no customer support platform, no error-reporting service, and no subprocessor, because there is no processor and no data to process. cdnjs, the content delivery network that serves pdf.js, is the single external host the codebase can reach, and it is reached only when you ask for PDF import.

Everything this site serves is a file in the same directory tree, from favicon.svg to sw.js. There is no build step, no bundler, no package downloaded at runtime, and no web font.

The one transfer, and who receives it

Exactly one outbound dependency in this entire application reaches a server belonging to somebody else, and that is the pinned pdf.js download described in the network. Nothing you type reaches it. The two addresses are requested by your browser, for two public JavaScript files, with the version pinned so the bytes you receive are the bytes everyone receives.

What the other end sees is what any web server sees when a browser asks for a file: the network address the connection came from, a user agent string, a timestamp, and the file that was requested. The IP address is not something the app sends. It is a property of your connection, and there is no way to fetch a script without it. The app adds crossorigin="anonymous" and referrerpolicy="no-referrer" to the script tag, so no cookie and no referring page travel with it, and no identifier of yours is attached. Your resume, your name, the file you picked, its size and its contents are all absent, because none of them is ever in a request.

cdnjs is a free CDN run by Cloudflare, and cdnjs publishes no privacy policy of its own: the address it links to from its own footer is Cloudflare's privacy policy. That is the document to read if you want to know what the receiving end does with a request. The cdnjs about page names Cloudflare as the party providing the network. We do not know how long Cloudflare keeps network records, and we have no way to ask it to delete one on your behalf, because we are not the account holder of the request.

Not using it is a complete answer. The other three import routes — a .docx file, a .json file, and pasted text — make no request at all, and so does everything else in the app.

Your rights

Most of what a privacy notice offers is something you can already do here by yourself in about a minute, because your resume is in your browser and nowhere else. That is worth stating plainly rather than hiding behind a process that does not exist. Each right below says what it means here and how you actually exercise it.

Access

Use the export button in the builder and choose JSON. It writes the exact object the app stores, unredacted, with nothing held back, as described in how to export a backup. If you would rather read it where it lives, open developer tools, go to Application in Chrome and Edge or Storage in Firefox and Safari, and open resume:current in the kv store of the resumeboard database.

Correction

Edit it in the app. The document is the editing surface, so every field is changed where you see it. If you want a written record of a correction rather than a silent fix, email the mailbox with [Privacy] in the subject and say what should read differently; Utkarsh will confirm the change in writing. The honest limit is that a record cannot be corrected where none exists: if you have already deleted the stored copy, the correction applies to the file you exported, in your hands, on your device.

Erasure

Delete the storage yourself, using how to delete everything. It takes effect the moment you do it, because there is no copy on a server that would need clearing afterwards, and no queue to wait in. Two things cannot be reached from here. A file you exported to your own drive or your own inbox is yours, and a share link you sent to someone else is a document you handed over. Neither is erased by anything this site does or does not do.

Portability

The JSON export is the portable format. It is plain text, readable in any editor, and it loads back into the builder on any device with Import, carrying your content and your design settings with it. It is a plain JSON file, not a proprietary container, and nothing about it is tied to this site or to an account. The PDF and plain-text exports are for reading and printing; if the goal is to move the data, use the JSON.

Objection

There is nothing to opt out of, because there is no processing to opt out of. The app does its work with the network switched off, and it keeps working that way. The single thing you can decline is the pdf.js download described in the one transfer, and declining it costs you exactly one feature: PDF import. If you want that refusal written down, say so in an email with [Privacy] in the subject and it will be acknowledged.

Three limits that follow from the architecture, stated so they are not discovered later. We hold no register of visitors, so there is no file to amend, no account to close and nothing to deactivate. With no account there is also no way to verify who you are before acting on a request, so please do not send anything sensitive expecting it to be checked against a record. And with no server there is nothing to retrieve, restore or confirm, because nothing was ever received. Where a request needs a record we do not hold, you will be told so plainly and given the instruction to do it yourself instead.

Complaints, grievances, and how they get answered

Send it to Utkarsh6624@gmail.com, with [Privacy] in the subject for anything on this page and [Legal] for anything about the terms. That mailbox reaches Utkarsh, the operator, directly. There is no ticket system in front of it, no shared inbox, and no queue: one person reads what arrives.

Utkarsh replies within seven days, usually sooner. Seven days is what one person can commit to without it quietly becoming untrue. If it passes, a nudge in the same thread is fair, and it will be picked up.

What is worth putting in the message:

  • What you expected to happen, and what happened instead.
  • The page and the section, quoted rather than described.
  • Your browser and roughly when it happened.
  • What you want to happen now. A correction, an explanation, or a deletion of something on this site.

What comes back depends on what is actually true. A page that states something the code contradicts gets corrected, and the last-updated date at the top of this page changes. A claim you disagree with gets argued with, not quietly removed. A request about data you think is held here cannot be fulfilled, because none is, and the answer will say so instead of pretending otherwise. A critical review of this site is not a grievance and will not be taken down to settle one.

If a reply does not resolve it, reply to that thread and say what is still open. Beyond that, escalation is available to you: under the laws of India a dispute goes to the courts competent where the operator resides. It is worth being straight about the shape of that, though. Resumeboard holds no resume and processes no personal data, so there is no processing here for a data-protection oversight body to adjudicate. What remains is a disagreement about a page on this site or about something you sent in, and the honest description of that route is the courts, not a regulator. Both this site and the operator's professional profile are public, and saying something in public is also a route.

Children

The builder is not directed at anyone under 16, and it collects nothing about anyone: not a child, not a parent, not an adult. There is no account, no form, no analytics and no server, so there is no collection for a parent to consent to and no record for anyone to hold. A consent mechanism would be theatre: there is nothing behind it to consent to.

What does exist is the arrangement described in if you are on a shared computer: a resume typed into the app sits in that browser profile until it is deleted. That is a property of local storage on a shared machine, not a disclosure to us, and the same four precautions apply to a child as to anybody else. Export the backup, use a private window, do not leave a share link in the address bar, and delete the database when you are done.

If you are under 16, ask a parent or a guardian before putting personal details into a resume you plan to send to anyone.

If you are a parent or a guardian with a question about a child using this site, write to Utkarsh6624@gmail.com with [Privacy] in the subject, say who you are and what you are asking about, and the answer will usually be that we hold nothing about your child, because we hold nothing about anyone. No identification will be asked for, because there are no records to search and no account to match against.

Changes to this page

This page is a plain file in the same tree as the application, which is also why it can be checked. Every claim above names the source file it comes from, and the app is plain HTML, CSS, and JavaScript that you can read in full. If a claim here and a line of code ever disagree, the code is the truth and the claim is the bug.

The date at the top of this page changes when the page does. A revision that corrects a factual claim will say so in the section it corrects, and a revision that changes how data is handled will also change the Terms of Service, because the two pages describe the same arrangement from opposite ends. There is no changelog file because there is no need for one: the file's own history is the record.

Questions people ask

Is my resume uploaded anywhere?

No. The builder writes your resume into your own browser, in a database called resumeboard, and it never opens a connection that carries it. The one feature that is designed to reach the network is PDF import, which downloads a PDF reader from cdnjs.cloudflare.com after you ask for it and shows you the two exact addresses first. The file you pick is read in your browser and is not uploaded.

Can the browser delete my resume without asking me?

Yes, and this is the one real cost of a local-only app. Browsers may reclaim site data when a device is low on space, clearing your browsing data removes it, and a private window throws it away when it closes. At start-up the app asks the browser to mark its storage as persistent, which lowers the risk but does not remove it. If you want a copy that no browser can take from you, export the JSON file and keep it somewhere you control.

What happens if I use a shared or work computer?

The resume is tied to that browser profile and that address, so the next person to open the builder on the same profile sees what you typed. Do the export first, then use Start a new resume in the overflow menu, and if the machine is not yours delete the database as well, because that reset is an ordinary edit and the previous resume moves into the stored undo history. A private window is the cleaner option, because everything in it is discarded on close.

Does a share link send my resume to a server?

No. A share link puts the whole resume in the part of the address after the #, which browsers never put in a request. The resume is decoded from the link in your browser. What is true is that anyone holding the link can read the resume, so treat it like a document you handed over. Your photo is left out of links unless you deliberately ask to include it, and only if it is under 60,000 characters.

Where do I send a privacy question?

To Utkarsh6624@gmail.com, with [Privacy] in the subject line. It is one real mailbox and it reaches Utkarsh, the operator of this site, directly. There is no ticketing system in front of it and no support desk: one person reads what arrives, and replies, normally within seven days.

Having no server is a fact about the architecture, not about who to ask. Every claim above names the source file it comes from, so reading the line it points at often answers the question first. If it does not, the mailbox gets a real reply. If you would rather read about the design decisions behind all of this, the about page covers the trade-offs, and the guides cover the writing.