Skip to content
hitSlopPublic

About

Build & share local mini apps and interactive documents for your Mac with Svelte and your favorite AI coding agent

Topics

Resources

Contributing

Security policy

Stars

9 stars

Watchers

1 watching

Forks

Latest commit

 

History

132 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dotpop

Tiny apps. Big personality.

CI MIT License macOS 15.2+ Apple silicon Discord — show us your pop GitHub stars

Local-first Local use needs no account Tiny apps. Big personality.

Make little apps for your Mac with Svelte & your AI coding agent: a planner that fits your week, a recipe card covered in your notes, a tiny pond to stare at between meetings.

Install dotpop once. Make and share little apps as files. Each .pop carries its interface, saved work and imported files. Send a fresh template or a filled document to anyone with dotpop, without packaging and signing a separate Mac app.

You and your agent work on the same document. Check something off and your agent can read it. Ask your agent to add a row and it appears in your open window. Your documents stay yours to keep, copy and share. The iPhone app on TestFlight brings dotpop to your phone, with a Synced Library through your iCloud account. The Mac app includes the Synced Library.

Download for Mac · Download for iPhone · Explore the website · Make your first pop · Docs

macOS 15.2+ · Apple silicon · Local documents need no account

iPhone (iOS 26+) is in TestFlight; App Store release coming soon. It opens, edits and creates pops, includes the Popular templates, and imports from Files. Availability covers Synced Library and live collaboration. Synced Library uses CloudKit Production on Mac and matches TestFlight/App Store iPhones.

A Mac desktop full of open dotpop: a Winamp-style music player, a desktop pet, a focus timer, flashcards, a doodle board, a koi pond, Wordle, and school planners.
▶ Watch the 30-second tour

On your iPhone

The iPhone app (iOS 26+, TestFlight) opens, edits and creates pops. Start from the Popular templates and keep your library in sync with your Mac through iCloud.

Download for iPhone · iOS 26+ · TestFlight

Little Days, a baby journal pop on iPhone, with Feeding, Diaper, Sleep and Note buttons above today's timeline.    The Templates tab in dotpop on iPhone, listing Popular dotpop such as Invoice, Weekly Planner and Quick Checklist.

Pops can adapt to the phone with responsive layouts and play native haptics for deliberate actions. Make yours work on iPhone.

You and your agent, one document

A pop is a live document with its own small interface. Your agent works on the same document through the pop CLI. Here's a fresh Pop Wins counter:

pop describe "My Wins.pop"
Pop Wins: A little credit for the things you get done.
Version: 000000000000000100000011

Fields
  ["title"]: text (set)
  ["wins"]: counter (increment)

Commands (pop call PATH NAME --args JSON)
  countOne — Give yourself credit for one little win.
    args: {"additionalProperties":false,"properties":{},"type":"object"}

Value (rows retain their $id)
{
  "title": "Pop wins today",
  "wins": 0
}
pop call "My Wins.pop" countOne
pop get "My Wins.pop"
{"title": "Pop wins today", "wins": 1}
pop apply "My Wins.pop" --op '{"type":"increment","path":["wins"],"by":1}'
pop theme set "My Wins.pop" --values '{"accent":"#7050ad"}'

The Pop Wins tutorial below defines countOne. Each app exposes its own actions through describe; apply and batch also let agents edit individual fields directly. With the window open, each increment appears immediately and the theme command turns the accent purple. Edit ▸ Undo can undo agent edits too. Text edits supplied with the version the agent read merge with what you typed since. The agent edits your local document through the pop CLI, including when the file is closed. Sync and live sharing are optional.

Small enough to be yours

Sometimes you just want a packing list for one trip. A timer that looks like a tomato. A recipe card covered in your own notes. Those are good reasons to make software.

dotpop is built for tools with one clear job and a little character. Its templates include planners, music tools, photo and voice notebooks, games, and desktop companions. Or ask your agent for the thing you keep wishing existed. It can feel like a sheet of paper, a pocket calculator, or something you found in an old arcade.

Apps can declare camera and microphone capture and transcribe stored recordings on-device on a supported Mac. Capabilities and permissions explains the APIs, system consent, platform limits and future directions. Contributors should follow the template and app rebuild order so the catalog uses their latest changes.

Keep the app. Keep the work.

  • Local documents need no account or server. Choose iCloud when creating a pop to keep it in sync with your iPhone through your private iCloud storage, or choose On this Mac and pick a folder. Move an existing local pop with File ▸ Move to iCloud…. The iPhone app includes the Popular templates. Keep active files outside iCloud Drive and other synced folders.
  • A .pop is one SQLite file: the interface, saved data and imported files travel together. Any SQLite tool can open it to look inside; edit it through dotpop or the CLI. Close a document before moving it in Finder.
  • Send a freshly built template so someone can start their own document. They need dotpop; opening the template asks where to save their writable copy. How to share a pop.
  • Export a PNG or PDF to send an invoice, print a recipe, or drop a plan into a message.
  • Use Share a Copy to send a saved copy, with its attachments and colors, while you keep working in the original.
  • Add a widget for a pop with a widget view: on your Mac desktop, or for library pops on the iPhone Home Screen in TestFlight. Tap to open it; iPhone widgets also refresh in the background, when iOS allows.
  • Choose Live collaboration in the Share popover. The owner signs in with Apple; anyone with the link can edit in dotpop on Mac/iPhone or in Chrome at share.dotpop.click. Chrome saves a downloadable browser copy. Stop ends the link and everyone keeps their copy. Live sharing explains how it works.
  • Design for the phone as well as the desktop: pops can switch to a compact layout on iPhone and play native haptics, which stay silent on Mac and in browsers. Make it work on iPhone.
  • Pin a pop Always on Top, or enter fullscreen in apps that enable it, including Checklist and Hourglass.
  • Finder icons can show what's inside, such as a counter's total.
  • Change a document's colors without touching its code, or edit the source to make a different tool.

Make your own with an agent

Use Bun 1.4.2 or newer on macOS or Linux. Install the dotpop Mac app to open windows and pick your registered templates in its catalog; on both platforms the CLI renders template artwork and exports closed documents as PNG/PDF itself.

bunx @hitslop/pop@1.0.0 init weekend-kit
cd weekend-kit
bun install

Setup asks what your pop should do, then offers to launch your agent: Codex, Claude Code, Gemini CLI, OpenCode, or another CLI. The starter already works: it includes a checklist, its icon and export views, your brief, and dotpop's guidance for agents. Try it before changing anything:

bun run dev       # Open the browser preview; preview data resets on refresh

Ask your agent to customize it, or open the folder in your agent yourself and try:

Read AGENTS.md, pop.ts, and the authoring/design skills in .agents/skills first. Turn this starter into "Weekend Kit," a packing list for short trips. Let me add items, group them by bag, check them off, and see how many are left. Make it feel like a pocket field notebook: warm paper, forest-green ink, and comfortable checkboxes. Include a clean printable packing list for PNG/PDF export. Keep it small, use dotpop's document APIs for saved data, and run the project checks when you're done.

Ask for changes as you go ("Make the checkboxes bigger") and see them in the preview. When it feels right, stop the preview, then:

bun run check     # Check types and components
bun run build     # Package it as dist/weekend-kit.pop
bun run register  # Optional: add it to your dotpop templates

Send dist/weekend-kit.pop to someone with dotpop. They can open it and create their own packing list; the template contains no personal document state.

If you registered it, open dotpop, choose Weekend Kit under Templates, and select Create. Existing documents keep the app version they were made with, so make another version whenever you like.

A whole pop, from scratch below builds a complete app with its export view and Finder icon · Full tutorial · Edit a document with your agent

Use the CLI

Run commands with bunx @hitslop/pop@1.0.0, or install it with bun install -g @hitslop/pop@1.0.0 and use pop. Generated projects have their own pinned bun run scripts.

Task Commands
Create and preview an app init SOURCE, then the project's bun run check and bun run dev
Package and install a template bun run build, bun run register
Make a writable document create --from TEMPLATE --output DOCUMENT, then open DOCUMENT
Inspect and edit a writable document schema, get, apply, batch
Discover and run an app's actions describe DOCUMENT, then call DOCUMENT NAME --args JSON
Move data between documents get, then one batch of insert operations
Customize and share colors, manage files theme get/set/reset/export/import, attachments list/import/export
Export a PNG or PDF export DOCUMENT --format FORMAT --output FILE (png or pdf)
Install agent guidance bun install -g @hitslop/pop, then pop skills install; skills update with the global CLI

Document creation and editing run on macOS and Linux. The CLI carries its own engine, which also exports a closed document as PNG/PDF and renders template artwork on both platforms; opening a window needs the Mac app. If you're unsure whether an edit happened, check with get before trying again. CLI workflows has complete examples.

Roadmap

Here’s where we’re heading:

  • iPhone app. Open, edit and create pops, import from Files, and add Home Screen widgets in TestFlight on iOS 26+.
  • Synced Library. Keep pops in sync between Mac and iPhone through iCloud.
  • Live collaboration. Edit together through a link on Mac, iPhone or Chrome.
  • Release the iPhone app. Bring iPhone to the App Store and qualify sharing on release devices.
  • More platforms. Explore iPadOS, Android, Windows and Linux native apps.
  • Ask from the window. Work with your agent beside your document, see what it changed, and undo its edits.
  • Remix something you love. Make someone else’s pop your own, and keep your saved data as the app evolves.
  • A store for tiny apps. Discover, publish and install community pops through an app-store-style catalog.
  • More native capabilities. Calendars, reminders, notifications, Shortcuts and Siri, “Send to pop,” MIDI, and richer audio and transcription—with permissions for each pop.

See direction for priorities and ideas for the proposals. Remaining directions have no release dates yet.

What would you like to see? Tell us on Discord.

Why Svelte?

A .svelte file looks like a small web page: a <script>, some HTML and a <style>. That's the shape of a pop. You write class, onclick and {doc.current.wins} in ordinary markup, with no JSX or hooks, and the page updates when the document does.

  • Styles are scoped to their component, so a pop can be all personality in plain CSS.
  • Reactivity is part of the language. Read doc.current in markup and Svelte keeps it current, with no dependency arrays to get subtly wrong.
  • Transitions and motion are built in, for the hourglass that tips and the koi that drift.
  • Mistakes are loud: bun run check catches type and template errors before you build.

Svelte is compiled into the .pop with the app, so a document keeps the Svelte it was built with; the Mac app supplies the document engine and native services, not Svelte. Svelte is the supported integration today; other frameworks would need an adapter.

A whole pop, from scratch

Pop Wins is a complete example: a name, a counter, and a button for giving yourself a little credit. Its window, Finder icon, and export all read the same document.

With the same Bun and Mac app setup above, create a fresh starter:

bunx @hitslop/pop@1.0.0 init pop-wins
cd pop-wins
bun install

Replace the following starter files. Keep the generated package.json and tsconfig.json.

1. Say what it remembers

schema.ts defines the saved fields and what a new document starts with. Text is editable; a counter supports increments. It also holds the one action the button and your agent share:

import { defineDocument, s, type Tx } from "@hitslop/pop";

const schema = defineDocument({
  title: s.text(),
  wins: s.counter(),
}, { initial: { title: "Pop wins today" } });
export default schema;

/** Give yourself credit for one little win. */
export const countOne = (tx: Tx<typeof schema>) => tx.fields.wins.increment();

Changing initial later doesn't overwrite saved wins.

2. Give it a name, a window and colors

pop.ts describes the app: its name, its starting window size and the colors people can change. The explicit slug identifies the app.

import { definePop } from "@hitslop/pop";

export default definePop({
  slug: "pop-wins",
  title: "Pop Wins",
  description: "A little credit for the things you get done.",
  author: { name: "You" },
  categories: ["personal"],
  window: { kind: "standard", width: 360, height: 360, fullscreenable: true },
  theme: {
    surface: "#fff7e6",
    ink: "#382d24",
    accent: "#28634b",
  },
});

Theme colors are CSS variables shared by the window, icon, and export. Change them through the theme panel or CLI, or share them as a theme file, without rebuilding. Changes stay with that document; the template keeps its defaults.

fullscreenable: true enables the Mac window's fullscreen control and View ▸ Enter Full Screen. See window behavior for other window types.

3. Give the button and CLI the same action

Replace the starter's commands.ts with:

import { defineCommands } from "@hitslop/pop/commands";
import schema, { countOne } from "./schema";

export default defineCommands(schema, {
  countOne: {
    description: "Give yourself credit for one little win.",
    args: {},
    run: ({ tx }) => countOne(tx),
  },
});

The button runs countOne with doc.change(countOne); an agent discovers the command with pop describe and runs it with pop call. Both apply the same action atomically, as one undo step. Commands are for agents, and their arguments are flat s.* scalars. Ordinary field handles remain useful for typing and other direct edits.

4. Build the app, icon, and export together

App.svelte is the whole interface. Import the definition from schema.ts and acquire the document with getDocument(schema) while the component initializes. Read doc.current, write through doc.fields, and let dotpop handle saving. See document access for child components and helpers.

<script lang="ts">
  import { bindText, getDocument } from "@hitslop/pop/svelte";
  import schema, { countOne } from "./schema";
  import "./styles.css";
  const doc = getDocument(schema);
</script>
<main class="wins-card">
  <input aria-label="Counter title" use:bindText={doc.fields.title} />
  <p class="wins-number" aria-live="polite">{doc.current.wins}</p>
  <button onclick={() => doc.change(countOne)}>A little win +1</button>
</main>

Preview.svelte reads its saved snapshot prop. Capture props also supply image URLs and the view's mode:

<script lang="ts">
  import type { CaptureMode, CaptureProps } from "@hitslop/pop/svelte";
  import type schema from "./schema";
  let { snapshot }: CaptureProps<typeof schema> & { mode: CaptureMode } = $props();
</script>
<article class="wins-card">
  <h1>{snapshot.title}</h1>
  <p class="wins-number">{snapshot.wins}</p>
  <p>Little things add up.</p>
</article>

For this small counter, optional Export.svelte can reuse the complete preview:

<script lang="ts">
  import type { CaptureMode, CaptureProps } from "@hitslop/pop/svelte";
  import type schema from "./schema";
  import Preview from "./Preview.svelte";
  let props: CaptureProps<typeof schema> & { mode: CaptureMode } = $props();
</script>
<Preview {...props} />

Icon.svelte:

<script lang="ts">
  import type { CaptureMode, CaptureProps } from "@hitslop/pop/svelte";
  import type schema from "./schema";
  let { snapshot }: CaptureProps<typeof schema> & { mode: CaptureMode } = $props();
</script>
<div class="wins-icon">{snapshot.wins}</div>

App.svelte is the editor. Separate components supply saved-state captures:

  • Required Preview.svelte supplies a compact overview for Quick Look and in-app previews.
  • Optional Export.svelte supplies complete PNG/PDF output. Use normal document flow so long content can expand. Without it, export actions are hidden.
  • Required Icon.svelte supplies the document's dynamic Finder icon, centered on a transparent 512 × 512 canvas. Missing or failed artwork can still fall back to the preview or generic document icon.
  • Widget.svelte supplies small, medium and large widget images from saved data for Mac and for library pops on iPhone in TestFlight. The phone renders its own images, including in the background when iOS allows. Saves, watched file changes and startup freshness checks refresh them while dotpop runs; WidgetKit controls when the new image appears.

dotpop refreshes the Finder preview and icon when you close the document. On macOS and Linux, build and register render the template's initial artwork from starting values.

Capture views use Takumi: restricted rendering on Mac and Linux, and in-process rendering on iPhone. Mac and Linux support selectable vector PDF. Capture components must be synchronous. Quick Look reads the saved artwork.

See icons, previews, and exports for capture details and size limits.

Style the views in styles.css:

* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: var(--pop-ink); }
.wins-card {
  padding: 28px;
  text-align: center;
  overflow-wrap: anywhere;
  background: var(--pop-surface);
}
main.wins-card { min-height: 100%; }
.wins-card input {
  width: 100%; padding: 10px; border: 0; border-radius: 8px;
  font: inherit; color: inherit; background: transparent; text-align: center;
}
.wins-card h1 { margin: 0; font-size: 24px; }
.wins-number { margin: 20px 0; font-size: 72px; font-weight: 800; }
.wins-card button {
  min-height: 44px; padding: 12px 20px; border: 0; border-radius: 12px;
  font: inherit; color: var(--pop-surface); background: var(--pop-accent);
  cursor: pointer;
}
.wins-card :focus-visible { outline: 3px solid var(--pop-accent); outline-offset: 4px; }
.wins-icon {
  width: 440px; height: 440px; border-radius: 100px;
  display: grid; place-items: center; font-size: 150px; font-weight: 800;
  color: var(--pop-accent); background: var(--pop-surface);
}

The builder finds each part by its filename: pop.ts, schema.ts and App.svelte, plus required Preview.svelte and Icon.svelte, optional Export.svelte and commands.ts. Stylesheets are imported from components, as App.svelte does above. See the runtime reference for the app interface.

5. Take it for a spin

bun run check     # Check the types and Svelte component
bun run dev       # Try it in the browser; preview data resets on refresh

The preview reloads as you edit. Stop it before continuing.

bun run build     # Create dist/pop-wins.pop (works on Linux too)
bun run register  # Render its preview and icon, then add Pop Wins to your catalog

In dotpop, choose Pop Wins → Create, then save your document as My Wins.pop. Change its title, add some wins, export a PNG/PDF, and close and reopen it to see the saved values. Check its refreshed icon in Finder, too.

Try the commands from You and your agent, one document on your saved document. pop theme reset "My Wins.pop" restores the template's colors.

How it's built

Rust Swift Svelte 5 TypeScript SQLite Bun dotpop on npm

A pop is a SQLite file holding a Svelte app and a Loro document. Loro's CRDTs (conflict-free replicated data types) merge edits to text, lists and counters. One Rust core owns the document, the file and every edit, so the Mac app and the CLI change a pop the same way.

Layer Built with Role
Document engine Rust, Loro Merging text, lists and counters; atomic edits; the single owner of the document
File SQLite The .pop: app, assets, artwork and saved state in one database
Mac app Swift, SwiftUI, AppKit, WebKit Windows, catalog, Quick Look and PNG/PDF export; a thin native layer over the Rust core via UniFFI
Pop interface Svelte 5, TypeScript The authored app, rendered from document snapshots; the page holds no CRDT
Author SDK and CLI @hitslop/pop, Bun Schemas, pop dev (Vite with a native Rust owner), build, edit and export
Contracts Rust serde, ts-rs, UniFFI Rust owns internal wires and app acceptance; generated TypeScript and typed Swift
page (WebKit) ──▶ Swift façade ──▶ Rust owner ──▶ .pop
pop CLI ───────────────────────▶ Rust owner      (the open window's, or the closed file's lock)
  • App and agent edits take one path, so an open window updates live and a closed file is edited without starting WebKit.
  • Text merges character by character.
  • A failed save keeps the document open and shows a retry.

Inside a .pop

app          markers, catalog columns, definition_json               one immutable declaration
assets       key, media_type, encoding, size, bytes                    ui.js, ui.css, commands.js, media
artwork      name (preview | icon), png                                 Quick Look preview and Finder icon
-- populated when you create and edit a document
document     uuid                                                       the document's identity
history      seq, bytes                                                 saved Loro state: a snapshot, then the edits saved since
share        room, endpoint                                             room and endpoint for live sharing; empty when unshared
attachments  id (SHA-256), media_type, bytes                           files you import

Any SQLite tool shows these tables. history holds Loro bytes rather than rows, so change a pop's data through dotpop or the CLI, not SQL. All seven tables exist in templates and documents. A template has app assets, optional artwork and a seed Loro snapshot; creating a document copies it and adds its own identity. The file's SQLite application_id and user_version mark its format, so a newer file is refused rather than rewritten.

Architecture · Engineering contract · Compatibility

Work on dotpop

Use the Bun version pinned in package.json, Xcode, and XcodeGen on macOS:

bun install --frozen-lockfile
bun install --cwd apps/landing --frozen-lockfile
bun run build
bun run verify --all --native
bun pop dev pop/quick-checklist

Development covers setup and adding templates, and the documentation index covers how the platform works.

Show us your pop

Made something wonderfully specific? Show us your pop. Share a screenshot, swap ideas, or help someone make their first pop app.

Join dotpop on Discord Follow dotpop on X

Little things add up

dotpop repository activity and contributor insights

Star history

dotpop GitHub star history chart

Related projects

Other projects exploring personal software and interactive documents:

Older inspirations: HyperCard and Smalltalk put making your own tools within reach. Winamp's skin system was a major inspiration for dotpop's look and feel.

Privacy

Release builds of the Mac app enable Firebase Analytics and Crashlytics. They send launch, open, create (source), duplicate and export (format) events; operation breadcrumbs; failure records with fixed operation, classification, reason and format fields; crash reports; and Firebase's standard app and device data.

Our custom event, breadcrumb and failure fields do not include document contents or file paths. Automatic crash reports contain diagnostic information collected by the Firebase SDK. Collection is enabled in release builds with no in-app toggle; Debug builds and tests do not upload telemetry.

See Privacy for the public disclosure.

License

MIT © 2026 dotpop contributors. See LICENSE and third-party notices.

About

Build & share local mini apps and interactive documents for your Mac with Svelte and your favorite AI coding agent

Topics

Resources

Contributing

Security policy

Stars

9 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages