Butterfly: freehand drawing and typed notes on one endless canvas
🎨 Powerful, minimalistic, cross-platform, opensource note-taking app
At a glance
- What is it?
- Butterfly is a Flutter-based note-taking app that puts handwriting, Markdown, images, and PDFs together on an unbounded workspace. It runs on Android, Windows, Linux, and the web, stores files locally by default, and labels real-time collaboration experimental.
- Who is it for?
- Butterfly suits solo users who want freehand annotation, Markdown text, and PDF import in one file, stored locally without a subscription. It covers Android, Windows, Linux, and Chromium-based web in one app.
- 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 2 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An unbounded workspace for notes, drawings, and imported documents
Butterfly is a note-taking app built for work that does not fit a linear document. Rather than a scrolling page, it provides an endless canvas where you can place notes, sketches, shapes, and documents at any position in two-dimensional space. A diagram can sit next to the text that explains it, a math proof next to its supporting graph, or meeting notes alongside images without any forced vertical order.
Input methods include stylus, touch, and mouse for freehand drawing, along with keyboard entry for typed text and Markdown. PDFs, SVGs, and image files can be imported directly onto the canvas and annotated with a pen in the same file. Export goes out as PDF, SVG, images, or the app's own portable format.
Butterfly runs on Android, Windows, and Linux as native apps. A web build lives at web.butterfly.linwood.dev, where Chromium-based browsers are recommended, and neither Firefox nor Safari is mentioned as supported.
How Flutter and WebAssembly produce the cross-platform build
All deployment targets share one Dart codebase written in Flutter. Web deployment compiles to WebAssembly rather than JavaScript. The Dockerfile shows how that process works: it reads the Flutter version pinned in app/pubspec.yaml using `yq '.environment.flutter'`, clones that exact version from GitHub, and then runs the production build:
flutter build web --wasm --release --no-web-resources-cdn --dart-define=flavor="$BUILD_FLAVOR"Passing `--no-web-resources-cdn` bundles all web resources into the build output, so a self-hosted instance does not fetch anything from a CDN at runtime. BUILD_FLAVOR accepts "production", "nightly", "development", and "dev" as values. When the flavor is nightly, development, or dev, the Dockerfile copies the contents of web_nightly/ over web/ before compilation, giving those builds different assets than the production build.
A separate build step follows the main Flutter compilation:
dart run ../tools/build_web_service_worker.dartThis generates a custom service worker specific to Butterfly, not part of the standard Flutter toolchain.
Repository entries include an api/ directory alongside app/. Neither the project documentation nor the Dockerfile explains what that component does or whether it is required for a self-hosted deployment to function.
Self-hosting via Docker: the port mapping in docker-compose.yml is commented out by default
For a self-hosted web instance, the repository includes a Dockerfile and a docker-compose.yml. A multi-stage build compiles the Flutter web app and copies it into an nginx container configured to serve on port 80 inside the container. Starting the container with the default configuration produces no errors, but nothing on the host machine can reach it. The docker-compose.yml ships with its port mapping disabled:
services:
butterfly:
build:
context: .
container_name: butterfly
#ports:
# - "3000:80"
restart: alwaysUncommenting those two lines maps port 3000 on the host to port 80 in the container. The Dockerfile has an `EXPOSE 80` directive, which documents the container's intent but does not itself open any host port. This is the detail a quick read of the Dockerfile alone would miss, because the EXPOSE instruction looks sufficient until you check what the compose file actually forwards.
Building from source requires outbound internet access during the Docker build, since the Dockerfile clones Flutter from GitHub. Users who do not want to build from source can download platform packages from butterfly.linwood.dev/downloads or try the hosted web app at web.butterfly.linwood.dev without running anything locally.
Pen parameters: smoothing, thinning, pressure behavior, and shape detection
Drawing is the feature that separates Butterfly from plain text and Markdown editors. Five parameters are configurable per pen: smoothing, thinning, pressure behavior, zoom-dependent strokes, and shape detection.
Smoothing reduces jitter from a stylus or mouse, and thinning narrows the stroke at lower pressure. Pressure behavior controls how much the pen width responds to force, which matters on stylus input where pressure varies continuously. Zoom-dependent strokes scale the drawn line with the current zoom level, so a stroke drawn while zoomed out does not turn into an unwanted thick band when you zoom in for close work.
Shape detection converts a rough hand-drawn shape into a clean geometric version. No documentation specifies which shapes it recognizes, at what confidence threshold it converts, or how to disable it per pen. For notes where freehand character is intentional, knowing whether accidental shape conversions are easy to undo would be worth testing before building a workflow around that pen setting.
Templates store a full pen configuration alongside palettes, stamps, text styles, and page layout, so a setup tuned for one kind of work can be saved and reloaded without reconfiguring manually. Mixed-content elements on the canvas also include rulers, grids, textures, and laser pointer notes, alongside Markdown text and handwriting.
Local-first files, WebDAV sync, and what no required account means in practice
Files are stored on the device by default. No account creation is needed to start using Butterfly, and no subscription or proprietary cloud connection is required. The consequence is that backup and sync responsibility falls on the user from the start.
Cross-device sync works through WebDAV or Nextcloud, both of which you configure yourself. If local files are lost without a sync setup in place, there is no documented recovery option. Desktop users can choose a different data directory, which lets you store notes inside a folder already managed by a separate sync tool. Whether that directory change is reversible is not addressed.
Organization within a document goes through multiple pages, page folders, layers, named areas, and waypoints. That structure is managed inside a single Butterfly file rather than through a folder tree, so the external file manager view of a notebook is a single file regardless of how many pages are inside it.
Community translation comes through Crowdin. Which languages are currently complete and how far translation progress has gone for any locale are not stated in the project documentation.
Experimental collaboration relies on Swamp or a self-hosted WebSocket relay
Collaboration is labeled Experimental in the feature list. Sessions use end-to-end encryption. Two relay options are named: Swamp, and a self-hosted WebSocket server.
Swamp is not explained anywhere in the project documentation, and its operator, availability, usage limits, and terms are not mentioned. For the self-hosted WebSocket option, no configuration instructions appear, and end-to-end encryption is cited without naming the protocol or describing how session keys are exchanged.
For team use, the experimental label is a substantive warning. A feature in this state may change behavior or stop working between releases without notice. The alternatives are sharing files manually through WebDAV or Nextcloud, or treating a Butterfly file as a shared asset in an existing version-control or file-sync system. Both of those routes work without any relay and carry no experimental caveats.
What the project documentation leaves without explanation: API directory and presentation mode
Several parts of the repository have no explanation in the project documentation. The api/ directory at the repository root is one example: its purpose is undocumented, and nothing indicates whether a self-hosted deployment needs it running alongside the web app.
Presentation tools and laser pointer notes appear in the mixed-content feature list but are not described further. Whether a presentation mode exists as a distinct screen layout, how the laser pointer is activated, or whether it works in the web app are open questions.
The always-editable design is explicit: most elements on the canvas can be moved, resized, recolored, and reordered after placement. A note put in the wrong position is not a permanent mistake, though no list of elements that cannot be moved or resized is documented.
Butterfly is distributed under AGPL-3.0; v2.6.0 was published on 2026-09-28 and the last push to the develop branch was on 2026-10-06.
Editorial conclusion
Butterfly suits solo users who want freehand annotation, Markdown text, and PDF import in one file, stored locally without a subscription. It covers Android, Windows, Linux, and Chromium-based web in one app. Avoid it if your team requires reliable shared editing today: the collaboration feature is labeled experimental, and neither Swamp nor the self-hosted WebSocket option is documented in enough detail to evaluate. Before self-hosting, uncomment the port lines in docker-compose.yml to expose the app on port 3000, and test which of your storage paths appear in the Storage view before committing to it.
Frequently asked questions
What platforms does Butterfly run on?
Butterfly runs on Android, Windows, and Linux as native apps. A web build is hosted at web.butterfly.linwood.dev, and Chromium-based browsers are recommended for the web version.
Does Butterfly require an account or subscription?
No account, subscription, or proprietary cloud connection is required. Files are stored on the device by default, and sync through WebDAV or Nextcloud is optional.
How do I self-host Butterfly?
The repository includes a Dockerfile and docker-compose.yml that build the app and package it in an nginx container. The default docker-compose.yml ships with the port mapping commented out, so you must uncomment the ports section to reach the app at localhost:3000.
What file formats can Butterfly export?
Export formats are PDF, SVG, images, and portable Butterfly files. Import supports PDFs, SVGs, and image files.
Is Butterfly's collaboration feature stable enough for team use?
Collaboration is labeled Experimental. Two relay options are named, Swamp and a self-hosted WebSocket server, but neither is documented in detail. End-to-end encryption is mentioned without naming the protocol.
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/linwooddev-butterfly)