Build PromptDrive
YESreplaces $5/mosaves $60/yrback to the verdict
A personal prompt library whose hard problems are filling variables without producing a broken prompt, keeping the version of a prompt that used to work, and copying to the clipboard from a browser that will not give you the clipboard API.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the single process that serves the library.
Get it nodejs.org, or your version manager. open ↗
Verify
node --version prints v20 or higher - installfree
Why The whole library is one file, and a synchronous driver keeps the code simple for a single user.
Get it Install a maintained driver as a dependency.
Verify
The database is created on first run and the schema matches - decidefree
Why One-click copying needs a trustworthy origin, and a plain address on your network is not one, which decides whether you need a certificate.
Get it Decide between using it only on the machine itself, or setting up a hostname with a certificate for phone access.
Verify
The copy button either works or shows the fallback with an explanation on every device you use - have readyfree
Why A library built against five invented examples gets the variable handling and the search wrong, because real prompts are long and contain awkward characters.
Get it Paste in the prompts you currently keep in notes, documents or chat history.
Verify
Search, filling and copying all behave with the real ones
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- prompts(id, title, body, notes, folder_id, created_at, updated_at, last_used_at, use_count) - versions(id, prompt_id, ordinal, body, notes, saved_at, label) · the previous body, every time, because editing is destructive - folders(id, name, parent_id, position) - tags(id, name) and prompt_tags(prompt_id, tag_id) · flat tags, because a second hierarchy is a second filing system - variables(prompt_id, name, label, default_value, required, ordinal) · derived from the body on save and editable - The variables table is derived, so renaming a placeholder in the body renames it here without a migration or a stale row.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DATABASE_PATH | required | ./data/prompts.sqlite | The whole library. Copy this file to back it up. |
PORT | required | 4321 | Bound to the loopback address by default, which is also what makes copying work. |
BIND_ADDRESS | required | 127.0.0.1 | Change it to reach the app from a phone, and read the note about the clipboard first. |
EXPORT_DIR | required | ./data/exports | Where JSON and Markdown exports are written. |
The build, in order
A library you can search faster than you can retype
Finding a prompt takes one keystroke to focus and a few to filter.
A setup step is a reason not to open the app.
Files
src/db.jssrc/schema.sqlInstant or it loses to a text file.
Files
src/public/search.jstests/search.test.jsThis tool is used between two other windows.
Files
src/public/keys.js
done when · tick each as it passeswatch out- Reloading the whole result list from the server on every keystroke makes search feel laggy at exactly the moment it needs to feel instant, and the tool loses to a text file. Keep the query snappy with an index, render results without a full page load, and measure the keystroke to update time rather than assuming it.
Variables that fail loudly
A filled prompt never contains a leftover placeholder, and the form matches the body.
One source of truth, so a rename cannot leave a stale field.
Files
src/variables.jstests/variables.test.jsA second pass substitutes the values themselves.
Files
src/fill.jstests/fill.test.jsName the field, because the user is mid-task.
Files
src/public/fill.js
done when · tick each as it passeswatch out- Substituting with a naive replacement pass lets a value that itself contains a placeholder get substituted on the next pass, so a prompt filled with text pasted from another prompt comes out with fragments replaced in ways nobody asked for. Substitute once over the original body in a single scan, never repeatedly until nothing changes.
Copying, including from the phone on the sofa
The copy button works on the machine and over the network, or explains itself.
On an insecure origin the object is not there at all.
Files
src/public/copy.jstests/copy.test.jsThe platform copy gesture always works.
Files
src/public/copy.jsNot in a documentation file the user will not read.
Files
src/templates/prompt.html
done when · tick each as it passeswatch out- Calling the clipboard write directly assumes the object exists, so on a phone loading the app at a local network address the call throws on the missing object rather than rejecting a promise, and a catch written around a rejected promise never runs. Check for the object before calling, provide the selection fallback, and show a message explaining why the button behaves differently there.
The version that used to work
Editing a prompt never loses the wording that was working yesterday.
Cheap now, priceless the day you need it.
Files
src/versions.jstests/versions.test.jsPrompt edits are usually a handful of words.
Files
src/public/diff.jsSo restoring the wrong one is also reversible.
Files
src/versions.js
done when · tick each as it passeswatch out- Overwriting the body on save means the afternoon spent tightening a prompt is gone when the tightened version turns out worse, and the only record of the good wording was in a chat window that has since scrolled away. Keep the previous body on every save, which for a library this size costs nothing.
Out of this app and into the next oneproduct builder
The whole library moves as files, and the backup story is one line.
The history is the part an export usually loses.
Files
src/export.jstests/roundtrip.test.jsOne file per prompt travels anywhere.
Files
src/markdown.jsBetter than a partial import nobody notices.
Files
src/import.js
done when · tick each as it passeswatch out- An export that drops version history looks complete because the prompts are all there, and the loss is discovered months later when somebody wants the wording from before a rewrite. Round-trip the export in a test that compares every table, including versions, rather than eyeballing the file.
That is the whole plan for PromptDrive. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Team sharing, comments and permissions.
- A browser extension for chat tools.
- Running prompts against models.
- Public share links.
- team sharing, comments, and permissions
- the Chrome extension inside ChatGPT, Claude, and Gemini
- running prompts against models from the same workspace with your own API keys
- public share links with unique URLs
- someone else's servers & support
- Typed variables with a select list, which removes most of the remaining filling mistakes
- A duplicate detector over prompt bodies, since libraries accumulate near-identical entries
- A quick-open window bound to a system shortcut, which is the only thing an extension really gave you
Need the files? The project pack on the verdict page hands your agent the whole brief · more ai writing.