Pinafore: A Fast Mastodon Web Client That Is No Longer Maintained
Alternative web client for Mastodon (UNMAINTAINED)
At a glance
- What is it?
- Pinafore is an alternative web client for Mastodon built for speed and small page weight, with offline read-only support, progressive web app features and multi-instance support. The README now carries a no maintenance intended badge and a link to the author's retirement post, while the last release is from January 2023.
- Who is it for?
- Pinafore fits someone who wants a Mastodon client that loads quickly on a modest device, and who is willing to run a service that nobody upstream is patching, because the application itself still runs and the AGPL-3.0 source is complete.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 180 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Client Built for Speed, Then Retired
Pinafore is an alternative web client for Mastodon, focused on speed and simplicity, and it is available at pinafore.social with beta releases at dev.pinafore.social.
The first line of the README is the important one. It carries a No Maintenance Intended badge and the note that Pinafore is unmaintained, with a link to the author's post about retiring the project, and the original documentation follows after it.
So this is a specific kind of article. The software is complete, the source is available, the code runs, and nobody is working on it. The interesting questions for a reader are therefore about the design decisions that were made while it was alive, and about what it means to run something in that state.
The project itself is a JavaScript application built on Sapper, and the repository layout shows the parts: src/ for the application, static/ for assets, webpack/ for the build configuration, a bin/ directory of build scripts, server.js for the production server, and a tests/ directory with an end-to-end suite.
The releases tell the timeline. v2.6.0 is from 2023-01-09, with v2.5.1 and v2.5.0 from December 2022, and the last push to the repository was on 2026-04-26, which is well after the retirement announcement.
The Goals List, and Everything Deliberately Left Out
The README states its goals as a list, and the non-goals list beside it is the more informative half.
The goals are to support the most common use cases, to keep the page weight small, to stay fast even on low-end devices, to be accessible, to work offline in read-only mode, to have progressive web app features, to support multiple instances, to support the latest versions of Chrome, Edge, Firefox and Safari, to support non-Mastodon instances such as Pleroma as well as possible, and to be internationalised. There is a secondary list of possible future goals, which are to serve as an alternative frontend tied to a particular instance and to support offline search.
The non-goals are where the real design shows. There is no support for old browsers, proxy browsers or text-based browsers. There is no React Native, NativeScript or hybrid-native version, and no Android or iOS apps using Cordova or similar. There is no full functionality with JavaScript disabled, no emoji support beyond the built-in system emoji, and no multi-column support. There is no admin or moderation panel, and no offline support in read-write mode, which the README says would require sophisticated sync logic.
That last one is the most telling exclusion. A read-only offline mode is straightforward, because reading needs no conflict resolution. A read-write one needs a sync model, and the author decided the client was not the place to build it.
Self-Hosting With Docker or Yarn
Building and running is documented in three ways, and the Docker route is the shortest.
The requirements are Node.js and Yarn. For a production build you install the dependencies and build:
yarn --production --pure-lockfile
yarn buildand then you run the server:
PORT=4002 node server.jsThe Docker route builds an image and runs it on the same port:
docker build .
docker run -d -p 4002:4002 [your-image]and the compose file does the same thing, with a restart policy of unless-stopped and the port mapping 4002 to 4002. The Dockerfile uses the node:16-alpine base image, and the comments in it explain two choices, that Alpine is used to keep the images smaller and that the run command uses an explicit node command rather than yarn or npm to use less memory. The build step also deletes the source, docs, tests and bin directories from the final image.
Updating an existing checkout is a single command that picks the highest version tag:
git checkout $(git tag -l | sort -Vr | head -n 1)The browser support position is narrow by choice. Pinafore supports the latest versions of Chrome, Edge, Firefox and Safari, and the README says compatible versions of each, such as Opera, Brave and Samsung browsers, should be fine.
Do Not Serve the Static Export Directly
The export section is the part of the README that saves a self-hoster a security problem.
Pinafore is a static site, and when you run yarn build the static files are written to __sapper__/export. It is explicitly not recommended to expose those files directly when self-hosting, and you should use node server.js instead, with an nginx or Apache proxy in front.
The reason given is that the server adds several things you do not get from the raw static files. The first is CSP headers, marked important for security. The second is certain dynamic routes, which the README describes as less important because the Service Worker manages routing, but where certain things could break if Service Workers are disabled in the user's browser.
So the static export is a build artefact for inspection and deployment to a static host, not a complete production deployment for your own instance. The node server is the deliverable, and the proxy in front of it is where your TLS and your headers go.
The README also notes that an nginx config generator is currently an open issue, which tells you the deployment story is not fully automated and that a self-hoster is expected to write the proxy configuration.
Multi-Instance Support and the Admin Guide
Two features shape how Pinafore is used in practice, and both are about talking to a Mastodon server.
The first is multi-instance support, listed among the goals. A single Pinafore deployment can serve users of several instances, which matters for a shared deployment, and it pairs with the related secondary goal of serving as an alternative frontend tied to a particular instance.
The second is the admin guide, and the README tells you when you need it: if Pinafore cannot connect to your instance. That is the failure mode that matters for a self-hoster, since the client is a front end for a server you do not control, and the connection is where version differences, instance configuration and API quirks show up. The user guide covers the basic usage, and the admin guide exists for the case where the basic usage does not work.
The repository also carries a set of scripts for working with a Mastodon instance for development, with a clone-mastodon script, an install-mastodon script and a run-mastodon script, which is how the test suite gets a server to talk to.
For updates and support, the README points to the account at [email protected], and the changelog lives in the GitHub releases, with a separate BREAKING_CHANGES.md file listing the breaking changes.
The Test Suite Runs Against a Real Mastodon
The testing setup is the most instructive part of the repository, because it shows how the project checked that a client still worked against a server it did not control.
The test script runs testcafe with the BROWSER environment variable set to chrome:headless, and the browser test script runs three things in parallel with a race between them: starting a Mastodon instance, building and starting Pinafore, and then the testcafe run itself. A separate script waits for Mastodon to start and waits for the Mastodon data to be ready before the tests begin, and there is a per-suite script for the first suite, which is how the tests are split up.
The .testcaferc.json file holds the testcafe configuration, and the workflow is orchestrated with npm-run-all, with run-p for the parallel steps and run-s for the sequential ones.
So the answer to the question a self-hoster actually has, which is whether the client still works with a current server, was answered by running the real thing in CI rather than by mocking the API. That is a heavier approach than most front end projects take, and it is consistent with a project that lists fast even on low-end devices and support for non-Mastodon instances as goals.
The linting is in the same spirit. The lint script runs standard over the JavaScript and then standard again with the html plugin over the route templates, so the markup is linted with the same tool as the code.
What Retiring Means for an Instance You Run
The practical consequence of the retirement is that a self-hosted Pinafore will not receive fixes, and the dependencies will age.
The engine field in the package manifest lists the Node versions the project was built against, from 12.20 and 14.13.1 up through 16, 18, 20 and 22, and the Docker image is built on node:16-alpine, which is itself well past its support window. So an instance that still runs today is running on a Node runtime that no longer receives security updates, and the container base is the same story.
That is the part to weigh. The application code is fine, the AGPL-3.0 licence lets you read it and change it, and the architecture is still a reasonable model for a small fast client. What you do not get is a maintained dependency tree, a maintained client for new Mastodon API changes, or security patches in the runtime you are serving it from.
The README is honest about the state of the project, which is the right way to leave it, and the linked retirement post from the author is the place to read the reasoning. If you want a similar client that is still worked on, you will have to look at other projects in the space.
Pinafore is named after the Gilbert and Sullivan play, and the README notes that the soundtrack is very good, which is a better ending to the project than most retirements get.
Editorial conclusion
Pinafore fits someone who wants a Mastodon client that loads quickly on a modest device, and who is willing to run a service that nobody upstream is patching, because the application itself still runs and the AGPL-3.0 source is complete. It is a poor fit for a new deployment, since the newest release is v2.6.0 from 2023-01-09 and the project has been retired, and a poor fit if you need features the non-goals list excludes, such as an admin panel, native mobile apps or offline read-write support. Before you rely on an instance you run yourself, read the admin guide, because connecting to an instance is the part most likely to need attention, and note that the static export must not be served directly, since the server adds the CSP headers and the dynamic routes. The project is AGPL-3.0 licensed and the last push was on 2026-04-26.
Frequently asked questions
Is Pinafore still maintained?
No. The README carries a No Maintenance Intended badge and states that Pinafore is unmaintained, with a link to the author's post about retiring the project. The newest release is v2.6.0 from 2023-01-09, and the last push to the repository was on 2026-04-26.
How do I self-host Pinafore with Docker?
Create a docker-compose.yml using the configuration in the repository, which builds the image from the Dockerfile and maps port 4002, then run `docker-compose up --build -d`. The image is based on node:16-alpine, exposes port 4002 and starts with PORT=4002 node server.js.
Why should I not serve the static export directly?
The README says it is not recommended to expose the files in __sapper__/export directly, and to use node server.js with an nginx or Apache proxy in front. The server adds CSP headers, which are important for security, and certain dynamic routes that would break if Service Workers were disabled.
What features does Pinafore deliberately not support?
The non-goals list excludes old, proxy and text-based browsers, React Native or hybrid-native versions, Android or iOS apps, full functionality with JavaScript disabled, emoji beyond the built-in system emoji, multi-column support, an admin or moderation panel, and offline support in read-write mode, which would require sophisticated sync logic.
How does the Pinafore test suite work?
The test script runs testcafe with BROWSER set to chrome:headless, and the browser test script starts a Mastodon instance and builds and starts Pinafore in parallel before running the tests, with separate wait steps for the instance to start and its data to be ready. The scripts for cloning, installing and running Mastodon are in the bin/ directory.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nolanlawson-pinafore)Was this useful?