Repository navigation
Phase 1 Spike Results
Phase 1 ran four throwaway experiments (spikes) to answer the riskiest questions before real code depended on the answers. Each spike ended in an architecture decision record (ADR). This page summarizes them in plain words. The spikes README has the commands, and each ADR has the full measurements.
All numbers come from one machine: a Microsoft Surface Laptop Studio 2. It has a 120 Hz screen at 150% scaling, and it runs Windows 11 with WebView2 154. It is much faster than the reference laptop, so the reference laptop must repeat the runs. The spike code never ships.
| Spike | Decision |
|---|---|
| Ink latency | ADR 0004 |
| Text on a freeform page | ADR 0005 |
| PDF export | ADR 0006 |
| Audio capture | ADR 0007 |
Question: can a pen stroke reach the screen within 25 ms in WebView2? If not, and it can't be fixed, the interface moves to Flutter before Phase 2.
Answer: close, but not proven. A desynchronized 2D canvas that draws in the pointer handler showed ink 13.7 ms after injected input at the median, and 16.1 ms at the 95th percentile. On this screen, that is about one frame behind a plain native window. At the 95th percentile, every stack measured is estimated to miss the 60 Hz end-to-end budget, native windows included.
Decision: keep Tauri, so the Flutter fallback doesn't trigger. Phase 5 draws live ink on a desynchronized canvas in the pointer handler. It must also try two fixes: delegated ink trails with a real pen, and a native ink layer above the WebView.
Still to do:
- A camera check with a Surface Pen and a Wacom tablet, filmed at 240 frames per second, which covers the parts the spike can't see.
- A decision on whether the brand guide restates the pen budget in frames at the 95th percentile.
- A reference laptop run.
Keep heavy work off the main thread while the pen draws. A busy main thread raised the 95th percentile from 16.1 to 22.5 ms.
Question: does typing stay within 16 ms with several Tiptap editors on a zoomable canvas, mixed with ink?
Answer: yes for rendering, with three rules. With the rules, the page's own measure, from key down to drawn, stayed under 16 ms at the 95th percentile. On screen at 120 Hz, the display adds 9 to 13.5 ms, so no setup reached 16 ms on screen.
Decision: build each text container as its own Tiptap editor inside one "world" element that zooms with a single CSS transform. The rules are:
- Give every top-level block
contain: paint. Without it, a 20-page note misses the budget (a 17.0 ms median, against 8.6 ms with it). - Draw ink into cached tiles off the main thread. Never use SVG, and never redraw all of it each frame. Tiles took zooming and panning from 5 to 10 frames per second up to over 100.
- Add
will-change: transformonly during a zoom or pan gesture.
Still to do: the owner's review of the typing budget, a Phase 4 benchmark on the reference laptop, and a limit on how many off-screen editors stay mounted.
Question: does WebView2's print to PDF match the paginated page on screen?
Answer: yes, to within 1 pixel at 144 DPI, once two layout rules are followed. Without them, text below a table moved by about 6 pixels. Ink stayed as vector paths. All 5 sheets exported as 5 pages, and manual page breaks landed in the same place.
Decision: export with WebView2 PrintToPdf from a hidden second WebView. Printing in the visible page stalled it for up to 50 ms at 5 pages, and half a second at 50. The two layout rules are:
- Nothing that affects layout may depend on the screen's pixel density. Use inset shadows, backgrounds, or SVG for table rules, never borders.
- Each paper size uses the width Chromium writes for it. A4 is 594.96 points wide.
Still to do:
- Test static fonts, because variable fonts embed as Type 3 fonts.
- Print a page on paper and measure it.
- Open the PDFs in other viewers.
- Repeat the timings at 100%, 125%, and 200% scaling.
Question: can cpal record the microphone and system audio at the same time?
Answer: yes. Over 10 minutes, both clocks matched the Windows performance counter within 0.1 parts per million, far inside the 9.3 parts per million that the 100 ms budget allows over 3 hours. Windows loopback delivers nothing while nothing plays, and it delivers a held packet when sound resumes. OpenNote fills those gaps with silence. Opus at 32 kbps took about 44 MB for 3 hours and used under 4% of one core per track.
Decision: use cpal on WASAPI in shared mode. Keep each source as its own track with a timeline that maps frame counts to performance counter times. Encode Opus in Ogg pages of at most 500 ms, so a crash loses under 1 second.
Still to do, by a person:
- Record a real Teams or Zoom meeting.
- Measure the offset between the microphone and loopback tracks.
- Try headsets, including Bluetooth, and device changes mid-recording.
- Record for 3 hours and check that a stroke at the end lands within 100 ms.
- The Flutter fallback stays in reserve and didn't trigger.
- Phase 4 gets a typing benchmark, and Phase 5 gets two ink fixes to try.
- Phase 6 gets two layout rules and a hidden WebView for export.
- Phase 9 gets per-track timelines and gap filling.
- Architecture overview
- Design decisions
- Development updates, for the plain-language version
OpenNote is licensed under the Apache License 2.0. Repository | Issues | Releases
- Getting started
- Installing and updating
- Where your notes are stored and how they stay safe
- Notebooks, sections, and pages
- Typed notes
- Ink and drawing
- Audio recording
- Math and study tools
- Productivity and study tools
- Tables and charts
- Search and links
- Page views, printing, and PDF
- Import and export
- On-device intelligence
- Settings and Connectors
- Keyboard shortcuts
- Accessibility
- Privacy and your data
- Troubleshooting
- FAQ