Images and files in your notes

You can drop images and files straight into a journal entry or page. Images show up inline as you write; other files (a PDF, a spreadsheet, a zip) become a tidy link you can click to open or download. EtherPK calls any of these an asset.

Adding an asset

There are three ways, and they do the same thing:

Whichever way, an image starts showing inline immediately, and a non-image file becomes a clickable link.

How an asset looks in your markdown

Your notes stay plain markdown, so an asset is just an ordinary markdown image or link that points into your graph's assets/ folder:

![Quarterly chart](../assets/example-quarterly-chart.png)

[Q3 report](../assets/example-q3-report.pdf)

You don't type these by hand - EtherPK writes them for you - but they are yours to edit, and nothing is hidden behind the scenes.

An image address from the web works too: ![A photo](https://example.org/photo.png) renders inline just like an uploaded one. Bear in mind that it is fetched from that site each time the note is shown, so the site can see that somebody at your address viewed it and when. If that matters, or if you want the picture to be yours whatever happens to the site, upload it instead.

Controlling an image's display size

An image without a hint renders at its natural display size (never wider than the editor). To cap it, add a display-size hint to the image's description - the text between ![ and ] - after a |:

![A diagram|300](../assets/a-diagram.a1b2c3d4.png)

The hint is a maximum: a larger image scales down to fit (keeping its proportions), and a smaller image is left at its natural size - it is never enlarged.

The display-size hint is just part of the description text, so it travels with your notes and works in any markdown editor. Remove it to go back to the natural size.

A default maximum display size for every upload

Images you upload arrive with a hint already applied - |800 unless you say otherwise - so a large photo or screenshot never swamps the page. To pick your own limit, click the cog next to a graph (on the Graphs page, or in the workspace toolbar) to open its settings, and fill in Default maximum image display size on upload - a width like 300, or width×height like 300x200. From then on, images you upload into that graph arrive with that limit instead (you can still change or remove it on any individual image). As with a hand-typed hint, it only ever scales images down - smaller images keep their natural size. Enter 0 to upload without any hint; leave the field blank to go back to the 800 default.

Tip: the editor shows the rendered image while your cursor is elsewhere, and reveals the raw ![...] markdown the moment you click onto that line - so you can tweak the display-size hint, then click away to see the result.

Copying, downloading, opening and deleting

Every asset in a note carries the same three actions, wherever it sits, and a picture carries one more:

Where you find them depends on what you're looking at:

Clicking a file link itself still downloads it, as it always has. To put your cursor inside the link text and edit it, hold Ctrl ( on a Mac) as you click.

Deleting a file

The bin icon does two things at once, and only when it's safe to: it takes the picture or link out of the note and deletes the file itself.

That second part is permanent, so EtherPK checks first whether anything else is using the file:

A synced graph has one extra check. Another device might have added a reference you haven't received yet, so before deleting anything EtherPK confirms it's online and fully caught up with the server. If it isn't, it says so and offers to remove the reference from this note only. The file stays put, and you can delete it once you've caught up.

Removing the reference is an ordinary edit, so Ctrl+Z brings it back. Deleting the file is not - if you undo after a delete, the picture comes back as a broken image with its description showing, because there's no longer a file behind it.

Tip: you can always tidy up later instead. Graph settings (the cog in the toolbar) has Scan for orphaned assets, which finds every file no note references at all.

Where your assets are stored

In a local graph (Your Notes In Your Own Folder), assets live in the assets/ folder inside your graph folder, right next to journals/ and pages/. They are real files on your disk - back them up, sync them, or open them in any other app, just like your notes.

Each asset is saved with a tidy, unique name: the original name in lower-case-with-hyphens, followed by a short fingerprint of the contents, for example:

assets/quarterly-chart.a1b2c3d4.png

That fingerprint means the same image is only ever stored once - drop the same picture into ten different notes and there is still just one file in assets/, referenced ten times. It's the contents that decide, not the name: add the same picture again under a different filename and EtherPK points at the file it already has, rather than storing a second copy. The description you see in the note is still the name you added it with.

The same is true of a synced graph, though the server never sees the fingerprint. Your device sends a scrambled version of it that only holds meaning inside your graph; if the graph already holds those exact bytes, the server says so, nothing is uploaded, your storage footprint does not grow, and the upload message reads "already in this graph, reused". The server learns only that two things in your graph are identical, never what they are, and cannot compare across graphs. Assets uploaded before this feature existed are indexed for reuse the next time you run Scan for orphaned assets in the graph settings.

A synced graph's assets are only ever stored encrypted, so you cannot open them from a folder the way a local graph's can be opened. If you want readable copies of them on your own disk, turn on a Local Mirror: it downloads and decrypts every attachment the graph holds, orphans included, into a folder you choose. See Keeping A Local Copy Of A Synced Graph.

Who can access a synced asset

With a private storage bucket, a synced asset is not public. A signed-in EtherPK user cannot fetch an asset from somebody else's graph unless they are an active member of that graph. Knowing the graph ID, asset ID or bucket path is not enough, and a valid Sync token for a different graph does not grant access.

That is the graph's protection, not a document's. A file attached to a protected document (see Protecting Sensitive Documents) is encrypted for the graph like any other asset, so every member can open it, and a link to it from any other document shows it - the protection passphrase covers the document's text only.

The download has two separate protections:

  1. EtherPK asks the Sync Server for the asset. The Server checks that the credential belongs to an active member of this exact graph before returning anything.
  2. The Server returns signed download addresses for only that asset's encrypted chunks. Each address expires after 15 minutes. An unsigned request to a private bucket is refused.

The signed address is not the decryption key. Assets are split into chunks and encrypted on your device with AES-256-GCM under a random key for that asset. The asset key, original filename, file type and content fingerprint are themselves encrypted under the graph's key. Bucket object names use random IDs rather than filenames or content fingerprints. The Sync Server and storage operator therefore hold ciphertext and cannot turn it back into the original asset.

Limits worth knowing

Good to know