Skip to main content
Blinks

Blinks — User Guide

Using Blinks

Blinks are the building block of OrbitingFox. A Blink can be a note, task, event, expense, reminder, or any other piece of information you want to capture.

Creating a Blink

  1. Open Blinks from the app menu.
  2. Click New Blink and choose a type: Note, Task, Event, Expense, Reminder, etc.
  3. Fill in the title, body, due date (for tasks/events), and any tags.
  4. Save. Your Blink is immediately available across apps that support linking Blinks.

Blink types

  • Note — free-text capture. Think digital sticky note.
  • Task — actionable item with a due date and completion flag.
  • Event — appears on your Calendar.
  • Expense — financial entry; feeds the Finance dashboard.
  • Reminder — triggers a Notification at the due time.

Linking Blinks

Blinks can be linked to Goals, Projects, Businesses, and FoxCom Spaces for richer context. They also appear on the Kanban board when added to it.

OrbitPilot

All your Blinks are available to OrbitPilot. Ask questions like "What tasks are due this week?" or "Summarise my expenses for May."

Images inside a Blink's description (2026-08)

You can paste or drop an image straight into the description of a Blink — handy for notes where a picture belongs between the lines. Those images are now fully shapeable and easy to find:

  • Resize & move: hover an image to select it, then drag any corner handle to resize, or use the little toolbar to set a size (S / M / L / Full) and align it left, center, or right. Works with touch on phones and tablets too.
  • Shown in the Images section: images living inside the description also appear in the Blink's Images list (and "Existing images" on the edit page), tagged with a 📝 "In note" badge so you can tell them apart from separately attached images. They have no delete button there on purpose — to remove one, delete it inside the description text, so you never accidentally drop an image your note refers to.
  • Open full-size: click any image (attached or in-note) to open it large in a new tab.

For developers: the resize/align mini-module lives in templates/blink/_blink_form.html (overlay anchored to the editor wrapper, outside Quill's contenteditable so Quill does not strip it; width saved as the img width attribute, alignment as text-align on the block — both pass the render_description sanitizer). The blink_extras.description_images filter surfaces in-note images (policy-matched: data:image/* except svg, http(s), site-relative). Data-URI images are opened via a blob URL (templates/blink/_note_image_open_js.html) because browsers block top-level navigation to data: URLs.

Formatting your notes & the tidier edit page (2026-08)

Click ✦ Formatting above a Blink's description to reveal the style toolbar. It now includes text colour and highlight alongside bold, italic, headings, lists, quotes, code and alignment.

  • How to style: select the words you want and click a style. If you just place the cursor inside a word and click a style, it applies to that whole word — no selecting needed. A hint under the toolbar reminds you.
  • Colours and the highlight save with the note and show on the Blink's page.

The Edit page is now organised into clearly labelled cards — Blink details, Images, Files, and Voice notes — so each section is easy to recognise. The Update · Preview · Cancel buttons sit together under the form and are repeated at the very bottom of the page, so you can save without scrolling back up.

For developers: colour/highlight use Quill inline-style attributors (attributors/style/color + /background); the description sanitizer (blink_extras.render_description) validates styles declaration-by-declaration — text-align + colour/background with hex/rgb()/rgba()/named values are kept, everything else (position, url(), …) is dropped. The word-on-cursor styling is a mousedown-capture helper in _blink_form.html. The bottom action bar submits the form via form="blink-edit-form".

Keeping one Blink private from OrbitPilot (2026-08-23)

Some things you capture are nobody else's business — not even your assistant's. Every Blink now has a compact switch (tap the small "i" beside it to read what it does), "Keep this Blink private from OrbitPilot", at the bottom of the Basic tab on the Blink form. It is off by default, which means OrbitPilot can read it — you do not have to switch anything on.

Turn it on and that Blink becomes private to you: OrbitPilot can no longer read it, and it also loses access to that Blink's voice memos, images and files. Anything it had already memorised from that Blink is deleted straight away — you do not have to rebuild anything or wait. In your Library the Blink wears a small Private badge so you can see at a glance which ones the AI cannot see.

You can switch it back off at any time; the Blink returns to the AI's knowledge the next time your memory is rebuilt. This sits alongside the two broader controls you already have: choosing which parts of your workspace OrbitPilot may read at all, and the OrbitPilot Files folder for documents.

Terminology: Blink is the primary word (2026-08-23)

The owner decided that Blink is the primary user-facing word. Wink stays alive deliberately as the legacy alias: it is named in the naming story on Our Philosophy, FAQ and Terminology, and OrbitPilot's retriever still matches it so older phrasing and older links keep working. When you write new copy, write Blink.

The conversion is phased — see docs/brand/BLINK-RENAME-PLAN.md and docs/BACKLOG.md §1c — and guarded by manage.py terminology_audit plus adminapp/test_terminology.py, a ratchet whose count may fall but never rise.

Code identifiers that read blink are frozen, not pending work. max_winks is a live Feature.key behind the plan limits — renaming it makes gating fail open. The same applies to template filenames, URL names, session keys, CSS classes and the {wink_title}-style placeholders inside admin-saved prompts. The full freeze list is in the plan and in terminology.ALLOWED_IDENTIFIERS.

"Catch another" after saving a Blink (2026-08-28)

The Blink saved! Where next? banner on the Blink dashboard offers four choices. Three of them take you somewhere else. The fourth, Catch another, used to point at the dashboard — the page you were already on — so it reloaded everything in order to reveal a Blink form that was already open, already empty, a few hundred pixels below on the same screen.

It now takes you to that form instead: it jumps to the "Catch a Blink" panel, opens it if it happens to be collapsed, and puts the cursor in the Title so the next thought can be typed straight away. No page reload, nothing lost.

Developer note: the control is #blinkCatchAnother in templates/dashboard.html, an anchor to #blink-create-panel with the open-and-focus behaviour in that template's own script block. The banner itself is gated on the blink_just_saved context flag (blink/views.py, set from ?blink_saved=1). Pinned by blink/test_post_save_where_next.py, including that the other three buttons still leave the page.

Long descriptions no longer jump to the top (2026-08-28)

If a Blink's Details ran long, clicking out of it and back in threw the page to the very top, far above where you were typing. On a phone, a description of around sixty paragraphs put roughly two thousand pixels between your cursor and where you landed.

The Details box now has a maximum height and scrolls inside itself, the way editors normally do. Your place is kept, the page stays a sensible length, and nothing is hidden — long text simply scrolls within the box instead of stretching the page.

Nothing about writing or saving changed; only the shape of the box.

Developer notes — why it happened (BL-66)

The cause was not a bug in our code. The description editor was one unbounded editable area: with a long description it measured 4933px tall at 375px wide. Focusing an element makes the browser scroll that element into view, and the element began thousands of pixels above the caret — so the browser was behaving correctly and the editor was simply the wrong shape.

Measured before and after, with a 60-paragraph description:

  • before — 375px: scrollY 2379 → 134 on refocus; 1280px: 1032 → 0; page 6729px long
  • after — 375px: 213 → 213 → 213; 1280px: 311 → 308; page 2056px long

The change is in templates/blink/_blink_form.html: #desc-editor gains max-height + overflow-y: auto (420px, 260px under the canonical 575.98px breakpoint), and its sizing moved out of an inline style= into the template's stylesheet — an inline style cannot be overridden by the phone media query, which is why the two had to move together. The white fill became the --of-surface-strong token on a new .of-desc-editor-wrap class, scoped so nothing else inherits it.

Tests. blink/test_description_editor_scroll.py pins the cap, the phone-specific cap, the canonical breakpoint, and the absence of inline styles. blink/test_description_editor_visual.py drives real Chromium and measures the scroll position at 375 and 1280; it SKIPS where Playwright is absent, so CI is unaffected and no dependency was added to it.

A trap that file records for the next live-server test: a LiveServerTestCase is a TransactionTestCase and truncates tables after every test, taking the migration-seeded plan rows with it. Without a plan the app redirects to /billing/plans/, so the first test passes and every one after it loads a 500 page. The fix is to re-seed what the page needs in setUp (via apps.get_model, never a cross-app import — the coupling ratchet counts those in tests too).

🪐 OrbitPilot