ttscoff

Marked Share

A log of Marked Share development.

Wiki links inside a folder

Wiki links inside a folder

A wiki link is a note’s name in double brackets. On the share page, that name becomes a link to the matching document in the same folder.

See [[Meeting notes]] for the recap.
The short version is in [[Meeting notes|the notes]].
Jump to [[Meeting notes#Decisions]].

The brackets stay in the Markdown you save. The page rewrites them when it renders, so a renamed note or a newly shared sibling shows up the next time someone opens it. You do not republish to refresh the links.

Same folder only

[[Meeting notes]] matches the document whose name in that folder is “Meeting notes”. A note with the same name in another folder is a different note. Matching is case-insensitive when there is only one candidate. If two notes differ only by case, the exact spelling wins.

An alias after | is the visible text. A #heading jumps to that heading on the target page.

A private note is linked for its owner. Everyone else still sees the brackets. ![[embeds]] are left alone, and so are wiki links inside code.

A missing note, if it is yours

When you are signed in and reading your own document, a wiki link with no match turns red. Click it and Share creates a private note in the same folder and opens the editor with that title filled in.

[[Follow up|later]] still creates a note titled “Follow up”. The alias is only what the link says. Other readers keep seeing [[Follow up|later]] as text. Once the note exists, the red link becomes a normal share link.

A list when you type [[

In the editor, type [[ and a list of the other documents in the current folder pops up. Keep typing and it narrows. The list follows the folder selected on the document, including a new folder you have not saved yet. Switch folders and the suggestions change with it.

Editor shortcuts, tabs, and reference ids

Editor shortcuts, tabs, and reference ids

A few editor habits that should have worked like a normal Mac text field now do.

Move and indent without leaving the page

Control-Command-Up and Control-Command-Down move the current line. Control-Command-Left and Control-Command-Right indent it. On Windows and Linux those are Ctrl-Alt with the same arrows.

Command-[ and Command-] outdent and indent too. They used to step through browser history, because the browser treats those chords as back and forward. In the editor they stay on the line you are editing.

Tab inserts a real tab, lined up on a 4-column stop, instead of two spaces.

Refresh after someone else saved

If the note was updated elsewhere, the status bar says to refresh. That reload used to get stuck behind unsaved changes in the tab you were looking at. Refresh now drops that stale buffer and loads the newer copy, so you can keep going.

Complete a reference id

Reference-style links can be filled in from the document itself.

With the cursor inside the id of a link, [the spec][|], the list is every [id]: url definition in the note. The same list opens for an image, ![diagram][|]. Typing narrows it.

The other direction is the definition you have not written yet. A [ within three spaces of the start of a line lists ids used in the text that still need a URL. That includes [label][id], image references, and a collapsed link like [CommonMark][], whose id is the link text. Ids that already have a definition stay off that list. Fenced code is ignored.

See [the spec][spec] and [CommonMark][].

[spec]: https://example.com/spec

Drop [some claim][src] in a paragraph, then later type [ at the start of a line and pick src when you are ready to paste the URL.

Two-way folder sync

Two-way folder sync

A folder on Share can stay in step with a folder of Markdown on disk. New notes, edits, renames, and moves go both ways. Deletes only happen if you ask.

The index

Sync does not download every note to find out what changed. One request is the snapshot:

GET /api/v1/documents?view=index&folder=Work

You get each note’s id, path, and content hash, plus tombstones for notes that were deleted. Only a tombstone means deleted. An id you knew about that is missing from both lists was moved to another folder. It is still on Share.

New local files go up in batches, up to 200 at a time. Edits use PATCH with If-Match and the last hash you saw. If the note changed on Share since then, you get a 409 instead of a silent overwrite. Notes that are new or changed on Share come down with GET /documents/:id.

Imports store the Markdown immediately and render HTML in the background. Open a note before that job runs and it renders on the spot.

The example client

script/share_sync in the Marked Share repo is a single Ruby file, standard library only, that does the whole loop:

  • Push new and edited local files
  • Pull edits and new notes from Share
  • Follow renames and moves
  • Keep the Share version when both sides changed, and upload your local edits as a new note titled “(conflicted)”
  • Delete in either direction only with --delete, and never throw away local edits that have not synced yet
export MARKED_SHARE_TOKEN="your-token"
export MARKED_SHARE_DEVICE_KEY="your-device-key"

./script/share_sync sync ~/Notes/Work --folder "Work" --dry-run --verbose
./script/share_sync sync ~/Notes/Work --folder "Work"

Point it at a locked folder if the notes are personal. Create the folder, lock it, then sync into it. A locked folder rejects a public upload, including one from a sync client.

Limits for now: 200 notes per import request, 500 KB per note, and 5,000 notes in one synced folder. Past that, split them across folders. Empty folders are not synced. If a move leaves an empty directory on disk, remove it yourself.

The API docs have the endpoints. The script is the walkthrough.

Locked folders stay private

Locked folders stay private

A folder can be locked. Everything in it, including subfolders, is forced private until you unlock it.

The padlock

Select a folder in the sidebar and click the padlock. The dialog tells you that documents in that folder and its subfolders cannot be shared. If any of them are already public or sitting on a public collection, Share tells you how many will become private, and removes them from your profile and public collections when you confirm.

A locked folder shows a padlock in the tree. A subfolder of a locked folder shows a dimmer one: the lock belongs to the parent, and you unlock it there.

What the lock actually stops

Moving a note into a locked folder makes it private. A bulk visibility change skips locked documents. Publishing to Micro.blog is refused. The API reports the lock, and a client that tries to set a locked note to public does not win.

Unlocking does not blast everything back to public. Documents stay private until you share them on purpose.

This is a guardrail, not a vault. Share still has to read your Markdown to render and search it. A lock is the thing that stops “oops, I shared the journal.”

Callouts that nest, and tables that look like tables

Callouts that nest, and tables that look like tables

GitHub-style callouts were already rendering. Real documents asked for more: a callout inside a callout, a table inside that, a task list inside the inner one, and a fold you can actually see.

Fold, nest, and keep going

A + after the callout type starts it open. A - starts it closed. The summary is the first line, and a chevron on the summary turns when you open it.

> [!info]+ Project status
> Here is where things stand.
>
> > [!warning]- Blockers
> > - [ ] Waiting on review
> > - [x] Assets delivered

Nested callouts keep their own type and their own fold. Tables and task lists inside them stay inside them. The reading-position shortcuts stop on a callout as its own block, including one nested in a list or inside another callout, so j/k does not skip the whole thing.

Tables

Tables in the document body pick up the reading styles now: borders, spacing, and a header row that looks like a header. A table inside a callout uses the same treatment, so a status table does not fall back to raw browser defaults in the middle of a note.

Working in a bigger library

Working in a bigger library

Folders made the library useful. The tools around them are what make a few hundred notes tolerable.

Search this folder

When a folder is selected, search can stay inside it. Check Current folder only under the search field and results come from that folder and its subfolders. The choice sticks, so you can leave it on if you mostly work in one place.

Titles in a nested folder show the path relative to where you are, so you can tell Client A/Meeting notes from the other Meeting notes without leaving the list.

Rename a folder

Double-click a folder name in the sidebar. It becomes a text field. Enter saves the new name, Escape backs out. Documents and subfolders come along. The paths update. You do not refile everything by hand.

Move a selection

Select a few documents and choose Move to folder. The picker is the same tree as the sidebar. One action files the whole selection.

Visibility changes in the list too, without opening each note. A selection can also be added to a collection from the library.

Big batches

Large libraries page instead of loading every row at once. Changes that touch a lot of documents, a bulk visibility change or a big move, run in the background and the library catches up when they finish. You are not staring at a spinner for the whole job.

Folders in the library

Folders in the library

The library is no longer one long list. Documents live in folders, folders can nest, and an empty folder can exist before you put anything in it.

A tree, not a pile

The sidebar is a folder tree. Pick a folder and the list shows that folder and everything under it. Drag a document onto a folder to file it. Drag a folder onto another folder to nest it, or drop it at the root to pull it back out.

You can add a folder without publishing a dummy note into it, and you can delete a folder. Deleting asks what to do with the documents inside: move them up, or remove them with the folder.

Where a note sits

A document still has a title. The folder is just the place it lives. File “Meeting notes” in Work/Client A and the stored path is:

Work/Client A/Meeting notes

A slash in a title becomes -, because a slash is how nesting works. Two notes with the same title in the same folder become Meeting notes and Meeting notes 2. The title you see stays the same.

Leave the folder blank and the note sits at the library root. That is not a fake folder named Library. The path is just the title.

Collections are unchanged. A note can live in Work/Client A and also appear on a public collection. A folder is where you keep it. A collection is how you share a set of posts.

Picking a folder when you publish

The editor has a folder menu instead of a path you type by hand. Choose an existing folder, or add a new one. The note’s name in that folder comes from the title.

On the API, folders are their own records, so an app can list them and create Inbox without uploading a file first. Identity is the path string. Work/Client A creates Work on the way if it is missing.

Made for sharing

This is an example of what a post can look like when shared on social media. Thanks to the new Open Graph generator, links get a nice “card” preview with the headline of the post in the image, and a summary in the description.

Marked Share is meant for, well, sharing. So making your documents look as inviting as possible is an important part of that. Hopefully these new features will make both of us look good!

Development log: rich media, Apex fixes, and highlight cards

A short tour of what just landed on Marked Share — with live examples in this post so you can see the plumbing instead of only reading about it.

Apex 1.0.20

Share renders with Apex. 1.0.20 fixes two bugs that showed up on real documents:

  1. Mermaid fences with edge labels like A -->|Yes| B no longer get a fake table separator injected into the diagram source.
  2. Definition lists next to fences and callouts keep their order — prose after a DL stays before the diagram, not after it.

Older shares that were stored with broken HTML can heal on open via on-read refresh.

Definition lists

MultiMarkdown / Kramdown-style definition lists work as styled <dl> blocks again:

Term
The thing you are defining.
Mermaid
Diagrams from fenced mermaid blocks, drawn in the browser.
SVG
Inline vector markup that survives sanitization.
Math
TeX hooks from Apex ($…$ / $$…$$), typeset when MathJax is enabled on the page.
Another term
A second definition to show stacking.
Yes, multiple definitions per term are fine.

Mermaid

Labeled edges used to corrupt the fence. This graph should render cleanly:

graph TD
  Publish[Publish Markdown] --> Apex[Apex HTML]
  Apex -->|Yes| Mermaid[Client Mermaid]
  Apex -->|No| Plain[Plain pre block]
  Mermaid --> Share[Share page]

SVG

Inline SVG is allowed through sanitization (with dangerous bits scrubbed). A simple mark:

MS

Math

Apex emits math hooks for inline and display TeX. With MathJax on the document page, these typeset; without it you still see the TeX source rather than nothing.

Inline: the identity \(e^{i\pi} + 1 = 0\) still hits.

Display:

\[ \int_{-\infty}^{\infty} e^{-x^{2}}\,dx = \sqrt{\pi} \]

Fenced math blocks are supported the same way Mermaid is (source in a math fence until the client runtime picks them up):

\sum_{n=1}^{\infty} \frac{1}{n^{2}} = \frac{\pi^{2}}{6}

Callouts

GitHub-style callouts are enabled in the renderer:

note

Front matter (YAML / MMD / Pandoc) is stripped from the HTML view only. Raw download and TextBundle still include your source.

tip

A paragraph that starts with Note: under an H1 is not MultiMarkdown metadata anymore — it stays on the page.

Front matter and the Word: bug

Two related fixes:

  • Leading YAML no longer appears as a thematic break and key/value soup on the share page.
  • Undelimited MultiMarkdown metadata stripping only treats conventional keys (Title, Author, …) as metadata. Prose like Note: … or First span: … under a heading stays visible. Existing shares that lost an H1 + colon paragraph can refresh on read.

Highlight share cards

Click a text highlight → share icon on the floating bar → live PNG preview with Download and Copy image.

The card is square (1080×1080): document title, gradient quote (coral → purple), attribution. Handy for pasting into Slack, Notes, or social without screenshot gymnastics. Open Graph images for ?hl= links are still a follow-up.

What else

  • Mermaid and callout/SVG styles on document and blog surfaces
  • On-read HTML refresh when stored bodies are missing rich media or were corrupted by older Apex
  • rubyzip bump for a known CVE

If something still looks wrong on an old link, open it once (refresh heals many cases) or republish. Bugs with a Raw vs rendered diff are especially helpful on support.

The Marked Share API

The Marked Share API

Marked Share is built API-first. The same HTTP endpoints powering the Marked desktop app and the web frontend are available for your own scripts, Raycast extensions, Alfred workflows, and automated publishing pipelines.

Authentication and Endpoints

The API is located at https://share.markedapp.com/api/v1.

Requests require an API Token and write operations require an X-Device-Key header:

Authorization: Bearer <your_api_token>
X-Device-Key: <your_device_key>

Tokens and device keys can be created in your account settings.

Core Capabilities

1. Document Management

  • List & Search: GET /documents?q=query&limit=25 supports full-text ranked search and pagination headers (X-Total-Count, Link).
  • Create Documents: POST /documents accepts either raw JSON with body_markdown, title, visibility, and collection_slug, or multipart TextPack archives (.textpack / .zip).
  • Update Documents: PATCH /documents/:id updates content safely with If-Match: <content_hash> optimistic concurrency locking.
  • Export TextPacks: GET /documents/:id/textpack downloads the complete document bundle with images and metadata.

2. Highlight Sets and Reviews

  • Retrieve Annotations: GET /documents/:id/highlight_sets lists all reader highlight sets on your documents.
  • Import Highlights: POST /documents/:id/highlight_sets/:set_id/import merges a reviewer’s feedback into your personal highlight set.

3. Collections

  • List Collections: GET /collections returns all collections, their display modes, and custom domains.
  • Inspect Collection: GET /collections/:id?include=documents lists collection metadata and member posts.

4. Cross-Publishing

  • Micro.blog: POST /documents/:id/microblog triggers immediate Micropub syndication with format: "full" or format: "excerpt".

Automating Your Workflow

Because Marked Share accepts standard Markdown over a clean REST API, you can easily integrate it into your existing tools:

curl -X POST https://share.markedapp.com/api/v1/documents \
  -H "Authorization: Bearer $MARKED_API_TOKEN" \
  -H "X-Device-Key: $MARKED_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "document": {
      "title": "My Post",
      "body_markdown": "# Hello World\nPublished via curl.",
      "visibility": "public",
      "collection_slug": "marked-share"
    }
  }'

With simple API primitives, you can publish from anywhere, script backups, and build custom workflows tailored to your writing habits.

Integrating with Micro.blog

Integrating with Micro.blog

For many writers, publishing on the web means participating in the open web and IndieWeb ecosystems. Marked Share includes native integration with Micro.blog, letting you cross-post documents directly from your library.

Connecting Your Micro.blog Account

Connecting Micro.blog takes just a few seconds:

  1. Navigate to Settings → Micro.blog on Marked Share.
  2. Paste in your Micro.blog App Token (generated from your Micro.blog Account settings).
  3. Choose your default publishing format:
    • Full Text: Posts the entire document body as a standard blog entry.
    • Excerpt: Posts the title, a generated summary, and a direct link back to your canonical Marked Share document.
  4. Save your token. Marked Share verifies the token and links your @username.

Publishing from Marked Share

Once connected, publishing to Micro.blog is available directly from the document toolbar and share dialog:

  • Click Publish to Micro.blog on any document you own.
  • Choose whether this specific post should be sent as Full Text or Excerpt.
  • Submit the form. Marked Share formats the post, issues the Micropub request, and stores the resulting Micro.blog post URL.

Automatic Feeds and Discovery

Once published, your document displays a direct badge link to the Micro.blog post. If you are running a public Marked Share collection as a blog, changes also ping relevant endpoints to ensure feed readers and subscribers receive updates immediately.

Cross-posting long-form drafts or short notes to your personal Micro.blog timeline has never been easier.

Integrating with Marked

Integrating with Marked

Marked Share was built to be the ideal cloud companion to Marked for macOS. Instead of having to copy and paste text or manage file uploads through a web browser, Marked can communicate directly with your Marked Share account.

One-Click Account Connection

Connecting Marked to your Marked Share account requires no manual API key generation or copy-pasting:

  1. In Marked, trigger the Share workflow. Marked opens the authorization URL in your default web browser (share.markedapp.com/auth/marked).
  2. Log in (or sign up) and click Connect Marked.
  3. Marked Share mints an account API Token and a machine-specific Device Key, then triggers a deep link: x-marked-3://login?api_token=...&device_key=....
  4. Marked catches the link, securely stores the credentials in your macOS Keychain, and marks your machine as connected.

Publishing from the macOS Desktop

Once connected, sharing a document from Marked is seamless:

  • Packaging: Marked bundles your active document into a TextPack with all local referenced images and custom reading styles.
  • Upload: The bundle is transmitted via the Marked Share API in a single HTTP request.
  • Instant Link: Marked receives the published share URL (markedb.in/...) immediately, ready to copy to your clipboard or open in your browser.

Concurrency and Conflict Avoidance

When you edit a document in your local editor and preview it in Marked, sharing it again updates the existing remote document rather than creating duplicates.

To prevent accidental data loss:

  • Each version on the server has a unique content_hash.
  • Marked sends an If-Match header with the last known hash.
  • If the document was modified elsewhere (in the web editor or on another Mac), Marked Share returns a 409 Conflict, naming the specific device that made the newer change.

Syncing Reviews Back to Mac

When readers leave highlights and comments on your shared document, you can pull those reviews back into Marked. Marked imports the reader’s highlights.json and displays their feedback directly over your local preview.

TextPack Import/Export

TextPack Import/Export

Portable file formats are essential for avoiding vendor lock-in. Marked Share embraces the open TextBundle and TextPack standards to keep your content self-contained and universally readable.

What is a TextPack?

A TextBundle is an open format that groups Markdown text and all associated assets into a single bundle folder. A TextPack is simply a compressed (zipped) TextBundle file with a .textpack extension.

Inside a Marked Share TextPack archive, you will find:

  • text.md (or text.markdown): The complete, raw Markdown source.
  • assets/: Embedded images referenced throughout the text (PNGs, JPEGs, GIFs, WebPs).
  • info.json: Metadata specifying the Markdown dialect and published reading style preferences.
  • highlights.json: Any highlights, notes, and signatures attached to the document.

Importing Documents

You can import documents into your Marked Share library at any time:

  • Drag and Drop: Drag a .textpack, .zip, or .md file directly into your Library or upload area.
  • Capture Web Pages: Use the Capture URL tool to convert an external web article into clean Markdown and assets automatically.
  • Asset Handling: Local image paths are automatically parsed, uploaded to secure cloud storage, and updated to point to resilient hosted URLs.

Exporting and Round-Tripping

Every document published on Marked Share can be exported immediately:

  • Click the TextBundle link in the document toolbar or share dialog.
  • Download raw Markdown via /d/<id>.md.
  • Download the complete asset-backed archive via /d/<id>.textpack.

Because Marked Share exports follow the standard TextBundle specification, you can open exported TextPacks in Marked, Ulysses, Bear, or any compatible editor with all images and reading styles completely intact.

Highlighting and Sharing

Highlighting and Sharing

Most publishing tools treat readers as passive consumers. Marked Share turns every shared document into a collaborative review surface with built-in highlighting and margin notes.

Highlighting for Everyone

Anyone with permission to view a document can annotate it—no account or login required.

There are two easy ways to highlight:

  1. Selection Menu: Select any string of text. A floating toolbar appears with options to Highlight or Comment.
  2. Keyboard Shortcuts: Press h to toggle a highlight on the currently active block, or press c to attach a comment.

If you are doing a deep proofread, turn on Highlight as I select in the Highlights menu. Every selection you drag across will instantly become an active highlight without extra clicks.

Notes and the Comments Sidebar

When you attach comments to highlights:

  • A speech-bubble indicator appears in the margin next to the annotated passage.
  • The Comments Sidebar displays all notes in chronological order alongside the document.
  • Clicking any note smoothly scrolls to its exact passage in the text.
  • Notes and highlights save automatically in real time—no save buttons required.

Isolated Highlight Sets

Your annotations never overwrite anyone else’s. Every reader creates their own distinct Highlight Set.

When you share your annotations, Marked Share generates an annotated link with a ?hl=<id> query parameter. Anyone following that link sees the document with your specific highlights and comments overlaid.

The Reviews Panel for Authors

If you are the author of a document, you have access to the Reviews panel.

Here you can:

  • See all highlight sets submitted by readers and editors.
  • Inspect reader signatures and feedback in one consolidated view.
  • Import selected review highlights directly into your own master highlight set.
  • Export annotations to take them back into local tools.

Previewing Documents

Previewing Documents

Reading Markdown on the web should feel as deliberate and polished as reading a well-typeset book. Marked Share brings the previewing sensibilities of Marked right into the browser.

Guided Reading and Block Navigation

When viewing a document, Marked Share includes keyboard navigation and reading position tracking:

  • Block Cursor: A subtle indicator tracks your active block as you read.
  • Reading Band: Navigation automatically keeps your current reading position roughly one-third of the way down the screen, preventing fatigue from awkward scrolling.
  • Persistent Location: Your exact reading place is saved locally in your browser. Reopening the document restores your place immediately.

Press ? on any document page to view the navigation shortcuts:

  • j / k or ↓ / ↑: Move to the next or previous block.
  • gg / t: Jump to the top of the document.
  • G / b: Jump to the bottom of the document.
  • Page Down / Page Up (or Ctrl-d / Ctrl-u): Page down or up while maintaining reading focus.
  • e: Instantly jump into the editor (if you have permission).

Five Reading Styles

Typography can make or break long-form prose. Marked Share includes five distinct reading styles, each available in independent Light and Dark modes:

  1. Editorial: Classic serif typography designed for long essays, articles, and documentation.
  2. Manuscript: Traditional book-style formatting with generous margins and classic serif type.
  3. Swiss: Clean, crisp grotesque sans-serif inspired by mid-century modern graphic design.
  4. Contrast: High-contrast, sharp geometric type for maximum clarity and focus.
  5. Typewriter: Monospaced aesthetic crafted for technical drafts, logs, and code-heavy notes.

The Typography Hierarchy

As an author, you can set a Published Style in the Share dialog to give your document an intended aesthetic.

However, readers always remain in control:

  1. Reader’s per-document choice (selected in the Aa menu).
  2. Reader’s global default (saved in settings or browser preference).
  3. Author’s published style.
  4. Default fallback (Editorial).

This balance ensures authors can suggest a tone while readers can always choose the typography that works best for their eyes.