Docket
Self-Hosted Agentic Support CenterVisit DocketFAQ
Docket is a complete support centre you run yourself: bug reports, feature requests, a public roadmap, a changelog, an FAQ and testimonials, all on your own domain under your own brand. Underneath it is a folder of Markdown files in your own GitHub repository and a static website built from them. There is no database, no server to maintain and no account with us. You buy it once and the code is yours.
Those are hosted services you pay for monthly, where your customers' feedback lives on their servers and the price rises with seats or tracked users. Docket is a one-time purchase of the source code. It runs on your hosting, your data sits in your own repository, and there is no monthly bill, no seat count and no per-board pricing. The trade is that you host it and you own the upkeep, which for a static site is close to nothing.
Free gives you the whole board: bugs, features, voting, roadmap, changelog, testimonials, FAQ, your own domain and the full design system, on unlimited products. You reply by hand and it carries a small "Powered by Docket" badge. Pro at $99 adds the work being done for you: AI first replies, email notifications, the digest, Slack and Discord alerts, the feedback widget, automatic update pull requests, and badge removal. Studio at $249 adds everything Pro has plus client deployments, a view across all your clients, and replies signed per teammate.
The free edition is a complete working support centre with every board section, your own domain and the full design system, on unlimited products. It is genuinely usable rather than a trial. There are also interactive demos of all three editions on our website, where you can click through a realistic board rather than reading about one. If you outgrow the free edition, the paid ones add the automation rather than unlocking the basics.
You need a free GitHub account, a hosting account (Vercel, Netlify, Cloudflare and Deno Deploy all work, and free plans are fine), and ideally a domain you already own so the board can live on a subdomain like support.yourcompany.com. For the paid editions you also want a coding agent you already use, such as Claude Code, Codex or Cursor. Optional extras are an AI key and an email provider key, both on your own accounts.
For the paid editions, no. You open the repository with your coding agent, paste one line, and it does the setup while answering your questions. The free edition installs by hand following INSTALL.md, which is five steps of editing two files and clicking deploy. Either way you will click buttons in GitHub and your hosting provider, and you will need to paste a couple of keys into settings pages. Nobody needs to write code.
Node 22 or newer, and git. That is the whole list, because Docket has no dependencies to install: there is no npm install step and no build tools to set up. If you are letting a coding agent do the setup it will check this for you. You can even do most of the work in GitHub's web interface and your host's dashboard without touching a terminal, though having Node locally makes checking your work much easier.
Payment is handled by Polar, who are the seller. You connect your GitHub account through Polar and are invited as a read-only collaborator on the repository for the edition you bought. Accept the invitation, then use GitHub's "use this template" flow to create your own copy under your own account in one click. That copy is entirely yours, with no git connection back to ours, which matters because your customers' reports become files in it.
Open your new repository with your coding agent and say "Set up Docket by following SETUP.md." It asks you a handful of questions: your company name, your support email address, the address the board will live at, and which products you support. It fills in config.js and products.json while you get on with something else. The parts only you can do are pasting keys into GitHub and your host, and pointing your domain. Fifteen minutes is realistic.
Docket is a static site plus two small endpoints, so it runs anywhere that serves both. We document Vercel, Netlify, Cloudflare Pages and Deno Deploy in docs/hosting.md, and each needs no changes to the code. Netlify and Cloudflare are the easiest free options. Vercel's Hobby plan does not permit commercial use, so if you are a business on Vercel you will need one of their paid plans. Moving hosts later is a matter of repointing the domain.
Docket needs its own subdomain, something like support.yourcompany.com or feedback.yourcompany.com. It cannot live in a folder of an existing site, because it serves its own pages from the root. Point that subdomain at your host following their instructions, and HTTPS is issued automatically by all four hosts we document. If you do not own a domain yet you can start on the free address your host gives you and move later, and nothing breaks when you do.
Two files carry almost everything. products.json lists what you support, one entry each, with a short id that becomes part of the web address, so choose those carefully as changing one later breaks links. config.js holds your company name, your support address, your accent colour and which sections each product shows. Start with the sections you will actually use: a board full of empty sections makes a new support centre look abandoned, and adding one later is a one-line change.
Example content lives in data.example/ and is never used once your own products.json exists, so there is nothing to delete and no risk of a stranger's demo items reaching your live site. If you would rather see a populated board first to get a feel for it, copy the examples across with cp -R data.example data, have a look, then remove it with rm -rf data before you go live. Your own first real report creates the folder properly.
Docket runs the same both ways. Most people choose private, because the repository holds your customers' submissions including their encrypted email addresses, and there is no reason for that to be browsable. Your published board is a separate thing and stays public either way. If you hold a paid edition, keep it private: the licence allows you to run and change the code but not to publish the source.
Run npm run build and open dist/index.html in your browser. That is the exact site your host will serve, so what you see is what customers get. The one thing that will not work locally is submitting the form, since that needs the endpoints your host provides. Netlify, Vercel and Cloudflare also build a preview for every pull request, which is the easiest way to check a change before it reaches your live board.
npm run check walks through your setup and tells you in plain English what is still missing, naming each thing rather than showing an error code. When it says everything is set up, it is. After that, open your live board and file a test bug through the form the way a customer would. It should appear on the board within a few seconds. Delete it afterwards by removing the file from data/ and committing.
Buy the edition you want, accept the invitation and create your copy from the new template, then move your data/ folder, config.js and products.json across. Those are the files that hold everything you have written, and they are unchanged between editions. Your coding agent can do this in a few minutes. Nothing about your board's addresses or content changes, so links you have already shared keep working.
We do not ship an importer for Canny, UserJot or Featurebase. Your data in Docket is plain Markdown with a short block of fields at the top, in a git repository, so the practical route is to export from your current tool and ask your coding agent to convert it. That is exactly the kind of repetitive job agents are good at, and docs/data-schema.md describes the format it needs to produce.
The paid editions ship a setup guide and an operating guide written for an agent to follow, plus three skills for triaging support, posting a changelog and updating the FAQ. Anything that can read a repository and follow instructions inside it will work: Claude Code, Codex, Cursor and Gemini among them. There is nothing to install and no plugin. The free edition does not need an agent at all, since it installs by hand.
People can report a bug, request a feature, leave a testimonial and comment on existing items. Feature requests and bugs can be voted on, once per person, without anyone signing up for anything. Every item gets its own page with a permanent address you can link to. Testimonials are held until you approve them, so nothing appears on your site under that heading without your say-so.
There is no account, no password and nothing to forget. Someone fills in a short form and their report is on the board. An email address is optional, and the only thing it is ever used for is telling that person their issue was answered or their request shipped. Voting works the same way, once per person, with no sign-up. Removing that barrier is a large part of why boards like this get used at all.
Every bug and feature carries a status, and each status is a real page with its own address, so you can link somebody straight to everything you have planned. The board shows all items with a status on each row, and you can filter to one status at a time. Declined only appears when you have actually declined something, so a new board never shows an empty tab. The roadmap draws from the same items.
Statuses are defined in the code rather than in a setting, so adding one means editing several places that list them, including the labels, the colours and the board columns. It is a job for your coding agent rather than a line in config.js, and it takes a few minutes rather than an afternoon. Because those are files Docket owns, copy the change somewhere durable or expect a future update's pull request to flag it.
Every report, request, testimonial, comment and vote is a Markdown file in the data/ folder of your own repository, with a short block of fields at the top. There is no database. That means you can read everything in a text editor, search it with ordinary tools, back it up by cloning, and edit or delete anything by changing a file and committing. It also means your coding agent can already see all of it, without any integration.
Docket ships two small endpoints, one to submit and one to vote. When somebody submits, the endpoint writes a new Markdown file into your repository using a token you supply. Your host sees the commit and rebuilds the site, which usually takes under a minute. Nothing sits in a queue and nothing passes through us. If two people submit in the same second, both are kept.
On the paid editions, a scheduled job runs every fifteen minutes, reads new bugs and feature requests, and writes a short first reply in the voice you set in config.js. It posts the reply to the board and emails it to whoever submitted, if they left an address. The point is that nobody waits a day to hear something, and you still decide what actually happens to the item.
You bring your own API key and the cost lands on your own bill, not ours. A first reply reads a handful of small files and writes a short answer, which comes to well under a penny each with the default model. It is the only running cost Docket has. There is also a hard ceiling: ai.maxRepliesPerDay defaults to 50, counted against replies already posted, so an unusual day cannot produce an unusual bill.
Leave the AI key unset and no first replies are written. Nothing else changes: submissions still arrive, emails still send, the board still works, and the scheduled job ends quietly having found nothing to do. You can also lower ai.maxRepliesPerDay to throttle it rather than switching it off, or delete the workflow file entirely if you would rather it never ran.
On the paid editions there are four. A short receipt confirming a submission landed. The first reply, when it is written. Any official reply you add to an item, sent on to whoever raised it. And a notice to everyone who voted for a feature, on the day it ships. All four are optional in the sense that they need an email provider key; without one, replies still appear on your board and simply do not reach an inbox.
Twenty alerts in a morning is a thing people mute, and a muted alert is worse than none. Set digest.when to "daily" or "hourly" in config.js, with digest.timezone set to your real timezone and digest.hour to the hour you want it. You then get one email describing everything that happened on your board, grouped by product. Quiet days send nothing at all, so a slow week costs you no email.
The paid editions post to Slack or Discord the moment anything arrives. Create an incoming webhook in whichever you use, and add the URL as a WEBHOOK_URL secret in your repository settings. Docket works out which service it is from the URL. This is separate from email, so you can have alerts in a channel and no inbox notifications, or both.
On the paid editions, one script tag on your own site puts a small button in the corner of your product. People can report a bug, request a feature, leave a testimonial, browse your roadmap and search your answers without leaving what they were doing. It reads a small file your build produces, so its search and roadmap stay current automatically. docs/api.md covers the attributes and the one setting it needs.
The page carrying the widget is a different site from your support centre, so the browser will not let it post until you say that page is allowed. Add its address to widget.allowedOrigins in config.js and redeploy. This is granted to that one site by name rather than to everybody, which is what stops anyone else posting to your board. It is the single most common thing to miss when adding the widget.
The paid editions include two more pieces in kit/. The callout card is a small card you paste onto any page of your own site, linking through to your board, with four things to change inside it and no script involved. The quick menu is one link anywhere on your site that opens a short menu straight onto any section: report a bug, request a feature, the roadmap, your answers. A support centre nobody can find is a support centre nobody uses.
Add an entry to products.json for each one. There is no limit on any edition, because charging per board is charging you for shipping more. Each product gets its own sections, its own accent colour and its own addresses, and the home page lists them all. You can also give each product a different set of sections, so a small tool might show only bugs and a changelog while your flagship shows everything.
Add an entry with its id, name, accent colour and the sections you want it to show, then commit. It appears on your home page with its own board and its own addresses. There is no limit on any edition. Choose the id carefully, because it becomes part of every web address for that product and changing it later breaks any link you have already shared.
The quickest lever is theme.accent in config.js, which is a single colour that flows through the whole design, including a frame tint that adapts so a vivid brand colour sits as calmly as a muted one. Beyond that, the stylesheet, the page templates, the copy, the statuses and what happens when something arrives are all ordinary files you can change. Ask your agent for what you want in plain English.
The whole board is designed for small screens, not just shrunk to fit. On a phone every section sits in a row above the board so moving between bugs, features and the roadmap is a single tap, the roadmap columns stack rather than scrolling sideways, and the filters show which way they scroll. Since most people reach a support centre from a link in an app or an email, that is where a lot of your traffic will be.
Open the item's file in data/, add your reply under the ## Replies heading, and commit. That is the whole thing. On the paid editions, that reply is then emailed on to whoever raised the item automatically. You can also ask your coding agent to do it, which is what the support skill is for: it reads the board, drafts replies for you to approve, and posts the ones you accept.
Anyone with write access to your repository can reply, change statuses and publish changelog entries, because all of that is editing files and committing. There is no separate user system, no seats and no per-person cost, on any edition. On Studio, replies can be signed by each teammate individually rather than all appearing under one name, so customers see who they are talking to.
Every section has search, covering bugs, features, the roadmap, the changelog, testimonials and your FAQ. It runs in the browser over the content the page already carries, so there is nothing to index, nothing to pay for and nothing that can fall out of step with your data. It works on hundreds of items comfortably. The widget carries its own smaller search over your answers and roadmap.
Docket builds static pages, so all your text, headings and structured data are in the page source rather than assembled by a script afterwards. That is what search engines and AI crawlers need. The paid editions add a sitemap, an llms.txt, crawler rules and IndexNow, which pushes changed pages to Bing, Yandex and DuckDuckGo as soon as you publish. In practice a well-used board becomes a genuine source of search traffic.
The free edition carries a small badge in the sidebar footer. It is an ordinary link that loads nothing and reports nothing. Pro and Studio ship with no badge at all, so there is nothing to remove and nothing of ours on a page your customers think belongs to you. This is the only cosmetic difference between the editions.
Boards are public and there is no privacy setting to turn on. A post is a commit, so it appears as soon as it is made, and there is no moderation queue for bugs or features. Testimonials are the exception: those are held until you approve them. You can delete or edit anything at any time, and because it is your repository that is an ordinary change rather than a request to us. You hold the code, so putting a board behind your own gate is a change you can make and keep.
Submissions are text only. In practice the fields ask for enough detail that most reports are actionable, and people often paste a link to an image they have hosted elsewhere. If file uploads matter to you, that is a feature you can build on top rather than one you have to wait for us to ship, since you hold the code and the endpoints are yours to extend.
There are two endpoints, one to submit and one to vote, both locked to your own pages rather than open to other sites. There is no read API and no MCP server, and that is on purpose rather than pending: your data is Markdown in the repository your agent already has open, so there is nothing for a server to serve. Reading your board means opening a file.
The free edition is $0 forever. Pro is $99 and Studio is $249, both one-time payments. There is no subscription, no renewal, no seat pricing and no per-board pricing. The price is the same whether ten people or ten thousand use your board, and the same as your team grows. The only ongoing cost is your own AI usage if you turn that on, which is well under a penny per reply on your own account.
You buy a copy of the source. Use it, change it, and run it on as many of your own products as you like, forever. Updates are included with no time limit and no renewal. There is no licence key, no activation and nothing that expires. The two things you may not do are sell the code on or publish the source. That is the whole of it.
That single line separates them. If you are shipping your own products, however many, Pro is the right one. If you set up, run or maintain a support centre for somebody else as part of your service, that is a client deployment and it needs Studio. Studio has no limit on how many clients, each can have their own install on their own domain, and it adds a view across all of them plus replies signed by individual teammates.
You are not stuck and you do not start again. Email support@theodorehq.com and we move your access to Studio for the difference between the two prices. There is no change fee and no time limit on doing it. Your existing install carries on exactly as it is; you simply gain the right to run them for clients, and the Studio features arrive with your next update.
There is no limit on installs, boards, products, items, or the number of people who use them. Pro covers everything you ship yourself. Studio covers that plus everything you run for clients. Contractors you engage may work on your install without needing their own copy. What the licence stops is selling the code on or publishing the source, not the number of places you run it.
Before you accept the invitation to the repository, email support@theodorehq.com and we refund you in full, straightforwardly. After you accept it you are holding the source code, which cannot be handed back, so we do not refund at that point. Your statutory rights under the Consumer Rights Act 2015 are unaffected either way. Refunds are issued by Polar, who are the seller of record for the purchase.
It is one payment. The code is already in your repository, it does not call home and there is no licence to check, so it keeps running whatever happens next, including whatever happens to us. There is no expiry, no degraded mode and no feature that switches off. The honest reason there is no licence check is that there is nothing for one to enforce.
On the paid editions a job checks once a day and, when there is a new version, opens a pull request against your repository written in plain English about what changed. Nothing on your site changes until you click Merge. Updates are included for as long as Docket exists, with no renewal. The free edition has no updater, so you take new versions by hand when you want them.
config.js, products.json, data/ and assets/ are yours and no update touches them. Files that belong to Docket are replaced, and if you have edited one the pull request names it and says plainly that your changes to that file will be lost, before you merge. If you want Docket itself to behave differently, the durable route is to say so on our support board, because the change then belongs to everyone and survives every update.
The site is yours, the code is yours and it builds from your own repository, so it keeps running whether or not we do. There is no service to shut down, no server of ours in the path and no licence to expire. The daily update check would simply find nothing and carry on quietly. You would keep every feature you have on the day it happened, indefinitely.
Your domain, your company name, your colour and your typography. The paid editions carry no badge, no attribution and no link to us anywhere on the page. Replies are signed with whatever you set as your official author name, defaulting to something like "Support Team". The free edition carries one small "Powered by Docket" link in the sidebar footer, and nothing else.
This is the first thing to try for almost any problem. It walks your whole setup and reports in plain English what is present and what is not, naming each missing key or setting and what turns on when you add it. It separates things that must be fixed before customers see the board from optional extras you can leave. If it says everything is set up, the problem is somewhere else and worth emailing us about.
A successful build is not always a deploy. Open your host's dashboard and compare the newest deployment's time against your last push. If the deployment is older, nothing was triggered, which usually means the project was created from the command line and has no git connection. Reconnect the project to the repository in your host's settings and push again. Until that is linked, pushing publishes nothing.
It tells you exactly what is wrong with a data file in plain English, naming the file and the problem rather than showing a stack trace. The usual causes are a missing field in the block at the top of the file, or a date in the wrong format. npm run build deliberately refuses to publish a malformed file rather than shipping a broken page, so a failed build has protected your live site rather than broken it.
Submissions are written to your repository with the token you supplied, so the usual cause is that the token has expired. Fine-grained GitHub tokens have an expiry date, and when it passes, submissions stop being saved. Check the commits in your repository: if the file is there but the page is not, the site simply has not rebuilt yet, which takes about a minute. If there is no commit, regenerate the token and update it in your host's settings.
Docket builds static pages, which is what makes it fast, free to serve and readable by search engines. The cost of that is a short delay between a submission being written and the page showing it, usually well under a minute. The person submitting sees a confirmation immediately and gets their receipt email straight away, so the delay is invisible to them.
Three things cause almost all of it. The provider key needs to be in your repository's Actions secrets, not only in your host's settings, because the jobs that send email run in GitHub rather than on your site. EMAIL_ENCRYPTION_KEY must be set or addresses cannot be read back to send to. And your sending domain needs verifying with your provider, with SPF and DKIM records added, or mail is accepted and then quietly discarded. npm run check names whichever is missing.
Mailgun runs separate European and United States infrastructure, and sending to the wrong one fails with an error that reads exactly like a bad key. If your Mailgun account is European, set MAILGUN_REGION to eu. Mailgun also needs MAILGUN_DOMAIN alongside its key, because its endpoint is per sending domain and there is nothing sensible to guess. Those two together resolve nearly every Mailgun setup.
The job that writes replies runs on GitHub Actions, not on your website, so its key belongs in your repository under Settings, Secrets and variables, Actions. A key in your host's environment variables will not reach it. Check the key matches the provider named in ai.provider, and check ai.maxRepliesPerDay has not already been reached for the day. Open the Actions tab to see whether the job ran and what it reported.
Scheduled runs are queued rather than guaranteed, and under load GitHub delays them, sometimes by several minutes. On a repository with no activity for sixty days it stops running them until you push again. Every job also has a "Run workflow" button in the Actions tab, so you never have to wait for a schedule to test something. GitHub's clock is UTC and does not follow daylight saving, which is worth remembering if a job looks an hour out for half the year.
Add the subdomain in your host's dashboard first, then create the record it asks for at your domain registrar. All four hosts we document issue the HTTPS certificate automatically once the record resolves to them, which can take anywhere from a few minutes to a few hours. A certificate warning almost always means the record is not yet pointing where the host expects, rather than a problem with the certificate.
Every submission, reply and change is a commit, so nothing is ever really gone. Open the file's history on GitHub and you can see every version and restore the one you want, or ask your coding agent to recover it. This is one of the quiet advantages of storing everything as files: an accidental deletion is an ordinary thing to undo rather than a support request to somebody else.
Cloning your repository gives you every submission, every reply, your settings and your entire history in one folder. There is no database to dump and no export format to worry about, because the files you would export are the files it already runs on. GitHub is holding a copy already, so a clone on your own machine or a scheduled mirror is belt and braces rather than the only line of defence.
Anything a visitor triggers, such as a submission or a vote, is in your host's function logs. Anything scheduled, such as first replies, the digest or the update check, is in the Actions tab of your GitHub repository, with a full log per run. Between those two you can see every step. The scheduled jobs also report clearly when they have nothing to do rather than failing, so a green run with no output is usually correct.
The pull request lists any file Docket owns that you have edited, and says plainly that merging replaces your version. Nothing changes until you merge, so you can close it, reapply your change afterwards, or keep your version and skip that update. For a change you want permanently, the durable pattern is to copy the file to a new name and use your copy, since a file you create is never touched by an update.
Docket is a static site plus two endpoints, and adapters for Vercel, Netlify, Cloudflare and Deno Deploy all ship in the box. Moving means connecting the new host to the same repository, copying your environment variables across, and repointing your domain. Your repository, your content and your addresses are untouched. docs/hosting.md covers what each host needs.
Email us at support@theodorehq.com and we answer within one working day. Docket has its own support centre where you can file a bug or request a feature publicly, which is often faster because other people can see it and vote. Whatever route you use, send the output of npm run check, your hosting provider, and the log from the failing run if there is one. That is usually enough to answer without a second exchange.
Every submission is a file in your GitHub repository, on your hosting, under your control. It never reaches us, because there is no path for it to travel: Docket has no server of ours in it and no account with us. Who can read it is whoever you have given access to that repository, and nobody else. If you make the repository private, only your collaborators can see the raw files, while the published board shows what you choose to publish.
The form asks for what they are reporting, their name as they wish to give it, and optionally an email address. Nothing else is taken: no account, no device fingerprint, no tracking identifier and no hidden fields beyond the one that catches bots. The email address is used for one purpose, telling that person what happened to their item, and nothing else. Leaving it blank works fine and they can still post and vote.
Addresses are encrypted with a key only you hold, before anything is written to your repository, and none of them appear on any page. This matters because a git repository's history is permanent, so a readable address written into it could never truly be deleted. Encrypted, honouring a deletion request is an ordinary edit. Keep EMAIL_ENCRYPTION_KEY somewhere safe: losing it makes every stored address permanently unreadable.
GitHub stores your repository. Your hosting provider serves the site. Beyond that, everything is optional and yours: an AI provider if you want first replies written, an email provider if you want mail sent, Slack or Discord if you want alerts. Each is your own account with your own agreement with them, and none of them is required for the board itself to work. We are not in that list, because nothing routes through us.
When a first reply is written, the item's title and description are sent to whichever provider you configured, along with your voice settings, so it can write a relevant answer. No email addresses are included. Whether that text is used for training is governed by your own agreement with that provider, not by us, and the major providers do not train on API traffic by default. If you would rather send nothing at all, leave the AI key unset.
A Docket board sets no cookies, loads no third-party scripts and carries no analytics or advertising of any kind out of the box. There is nothing to put a cookie banner on, because there is nothing to consent to. If you want analytics you can add your own by setting analytics.scriptUrl and analytics.websiteId in config.js, in which case the choice of provider and the consent obligations that come with it are yours.
The free edition makes no request to us for any reason, ever, because it has no updater in it. The paid editions ask once a day whether a newer version exists. That request carries no licence key, no repository name, no domain, no account and no unique identifier, so there is nothing in it that distinguishes your install from anybody else's. It runs inside GitHub rather than on your server. Delete the update workflow and even that stops.
Because your customers' data lives in your repository and never reaches us, you are the data controller for it and we are not a processor of it. That is unusually simple compared with a hosted tool, where you would need a processing agreement. What you do need is a privacy notice on your own board explaining what you collect and why. Docket ships no legal templates, and LEGAL-CHECKLIST.md sets out what running a public board commits you to.
Find their item in data/, delete the file or remove the personal parts, and commit. The board rebuilds without it. Because addresses are encrypted rather than stored in the clear, an address in your git history is not readable to anyone without your key, so a normal deletion genuinely resolves the request rather than leaving a copy behind in history. You can do this yourself in a minute, without asking anyone.
Keys live in your host's environment variables and in your repository's Actions secrets, never in a file in the repository. .env is already ignored by git so a local copy cannot be committed by accident. Use fine-grained GitHub tokens scoped to the one repository with Contents read and write and nothing else, set an expiry, and put a reminder in your calendar. If a key is ever exposed, revoke it at the provider and issue a new one.
A hidden field catches bots that fill in every field they find. An origin check turns away scripts that never loaded your page. And there is a rate limit per visitor: five submissions and twenty votes per ten minutes. On top of that, AI replies are capped per day, so even an unusual night cannot produce an unusual bill. Anything that does get through is a file you delete and commit.