Build Mymind

KINDAreplaces $12.99/mosaves $155.88/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A local library that swallows links, images, screenshots and notes in one action, extracts what it can from each, derives tags and a one-line description, and serves a visual grid with search that covers extracted text, derived tags and the text inside images.

estimated effort weekendthe files for this build are in the project pack

RuntimeNode 22 with SQLite and full text searchExtractionReadability for pages, text recognition for imagesEnrichmentA model producing tags and a description, applied once per itemCaptureA bookmarklet, a share endpoint and a watched folderInterfaceA masonry grid with lazy loading

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the capture endpoints, extraction and search.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. installfree

    Why Screenshots are the majority of what a library like this holds and are invisible to search without it.

    Get it Install Tesseract with the language data you need, or use a platform recognition interface if one is available to you.

    Verify A screenshot of text returns its content

  3. have readyfree

    Why Search quality and grid performance are both meaningless against generated data, and the vague queries that matter only exist against your own material.

    Get it Import from wherever you currently save things: browser bookmarks, a screenshots folder, a notes application.

    Verify At least three hundred real items are imported

  4. API keypay per token; tagging an item is a fraction of a cent

    Why Phase 3 only. Capture, extraction and search all work with no model, which is a legitimate configuration.

    Get it A provider key with a spend limit, or a local model if you would rather nothing left the machine.

    Verify A captured item receives tags and a description

  5. have readyfree

    Why Phase 4's real benchmark. Exact-match testing tells you nothing about the retrieval this tool exists for.

    Get it Write down ten items you know are in your library described the way you would actually search for them.

    Verify The ten queries are recorded with their expected items

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- items(id, kind, url, title, description, captured_at, source, colour_hex) · kind is link, image, note or highlight
- content(item_id, extracted_text, ocr_text, extracted_at, extractor_version)
- assets(item_id, path, kind, width, height, bytes, thumb_path)
- tags(id, name), item_tags(item_id, tag_id, source, confirmed) · source is derived or manual
- items_fts · full text over title, description, extracted text and recognised text
- A derived tag is a suggestion until confirmed or corrected, and a correction is never overwritten by a later derivation.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DB_PATHrequired./data/library.dbItems, extracted text and tags. A revealing dataset, so treat backups accordingly.
ASSETS_DIRrequired./data/assetsOriginal images and stored page copies, plus thumbnails.
WATCH_DIRrequired~/Desktop/ScreenshotsFolder watched for screenshots. Files here are copied rather than moved.
CAPTURE_TOKENsecretrequiredreplace-with-a-random-tokenUsed by the bookmarklet and the share endpoint. Scoped to capture only.
ENRICH_PROVIDERrequiredlocalWhich model derives tags. Local means nothing leaves the machine.
THUMB_LONG_EDGErequired600Thumbnail size. Large enough to recognise, small enough to scroll thousands.

The build, in order

  1. Capture in one action

    Saving anything takes one action and asks for nothing.

    1. Posts the URL, title and any selection. No form, no confirmation dialogue.

      Files public/bookmarklet.js

    2. With a settle check, so a file still being written is not captured half formed.

      Files src/watch.js

    3. An endpoint taking a URL or an image. The phone is where most captures happen.

      Files src/capture.js

    done when · tick each as it passes
    watch out
    • Adding one optional field at capture is enough to break the premise, because an optional field still asks for a decision and most people will stop to fill it. Capture nothing but the content and the source; everything else is derived or edited later.
  2. Getting text out of everything

    A screenshot is as findable as a note, because its text was read.

    1. Readability, sanitised so the stored copy makes no outbound requests when viewed.

      Files src/extract.js

      terminal
      npm install @mozilla/readability jsdom
    2. Every image, not only ones that look like screenshots. The distinction is not reliable.

      Files src/ocr.js

    3. Rather than letting them vanish from search. They are the ones you will look for and not find.

      Files src/extract.js

    done when · tick each as it passes
    watch out
    • A screenshot with no recognised text is invisible to search, and screenshots are usually the majority of what people save in a tool like this. Run recognition on every image, and where it produces nothing, mark the item as needing attention rather than letting it disappear into the grid.
  3. Tags derived, never demanded

    Items acquire tags without you filing anything, and your corrections stick.

    1. On capture, from extracted text. Not on a schedule over the whole library.

      Files src/enrich.js

    2. Corrected and removed tags are permanent decisions and are excluded from derivation.

      Files src/tags.js

    3. An item with no extraction gets no tags. Invented tags are worse than none.

      Files src/enrich.js

    done when · tick each as it passes
    watch out
    • Re-deriving tags on a schedule and overwriting user corrections teaches people their edits do not matter, and they stop correcting, and the tags degrade. Mark corrected tags and leave them alone, deriving only for items that have none.
  4. Retrieval, which is where the effort belongs

    Something you saved a year ago and cannot describe still comes back.

    1. Title, description, page text, recognised text and tags in one index.

      Files src/search.js

    2. Kind, date and dominant colour. Colour is surprisingly effective for images.

      Files src/filters.js

    3. Ten things you half remember. This is the real benchmark rather than exact matches.

      Files eval/queries.json

    done when · tick each as it passes
    watch out
    • Searching only titles and tags fails for exactly the items this tool exists to hold: the screenshot with no title and the image whose content you remember but cannot name. Index everything extracted, and test with queries describing content rather than metadata.
  5. A grid you actually browse

    Scrolling the library is fast and you recognise things by sight.

    1. Not on scroll. Doing it lazily is why these grids stutter.

      Files src/thumbs.js

    2. Stored at capture so the layout is stable before images load.

      Files src/grid.js

    3. No network request. The archive is the point and it must work offline.

      Files src/item.js

    done when · tick each as it passes
    watch out
    • Loading full images into a grid makes scrolling stutter and consumes memory, and it gets worse as the library grows so it feels fine for the first month. Generate thumbnails at capture, give every tile explicit dimensions so the layout does not shift, and load full images only when an item is opened.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more bookmarks.