A MicroPython library in Velxio IS a .py file in the project, copied onto
the board's filesystem before main.py runs. That mechanism worked, but
getting the file meant hunting GitHub by hand — the gap issue #214 is
about. Now the Library Manager fills it, in both halves:
Backend: /api/micropython-libs proxies the official micropython-lib
package index (the same one `mip` uses on real hardware). /search filters
the index; /fetch resolves a package plus its declared deps into .py
files. The proxy is what makes this safe to expose: only the official
index is reachable (the name must exist in index.json, files come from its
content-addressed store), source only (.py, never .mpy bytecode), path-
safe, and capped at 24 files / 256 KB per install. In-process TTL cache
over the index.
Frontend: the same Library Manager modal, mode-aware. On a MicroPython
board the search hits the index and "Add to project" writes the package's
files into the board's workspace (upsert — re-adding is the upgrade path),
visible in the explorer and travelling with the project. Before typing it
shows featured picks (ssd1306, umqtt.*, urequests) and the modules already
frozen into the firmware (neopixel, dht, onewire, ds18x20, machine,
network) labeled "built into the firmware", so searching for one answers
"just import it" instead of an empty list.
The file-materialization prelude now creates package directories: umqtt
ships as umqtt/simple.py, and MicroPython's open() does not mkdir, so the
prelude died with ENOENT on any packaged module.
Also ships a gallery example ("ESP32 + MicroPython: use an external
library") that documents the file-is-the-library mechanism with the
ssd1306 driver on the wired OLED.
The unified-toolbar responsiveness work gave .unified-toolbar
container-type: inline-size, which makes it the containing block for
position:fixed descendants. The three modals rendered inside the toolbar
(library manager, install-libraries, circuit verification) shrank to the
toolbar's 89px box: pinned to the top, header and close button clipped
offscreen. createPortal(document.body) makes them immune to ancestor
containment. The library manager also gets a fixed tall height
(min(86vh, 1000px)) instead of a bouncy 80vh cap.
(1) The explorer's per-board manifest entry is renamed velxio.json -> libraries.json
and clicking it now opens a READ-ONLY JSON view of that board's declared libraries
(board.libraries) in the editor, instead of the modal. New editor state
manifestViewBoardId: when set, CodeEditor renders a read-only Monaco showing
{libraries:[...]} live; opening/activating any real file clears it. No file is
added to the workspace, so nothing touches compile or save. Library actions are
done in the Library Manager modal (toolbar button).
(2) Drop the 'Uninstall' button for shared index/cache libraries — you can't
uninstall a copy everyone shares (content-addressed cache). Only your own custom
.zip uploads keep a 'Remove' (per-user store). Index libs: just Add to / In project.
Remove the 3 tabs (In project / Search / Installed). One list now: browse your
installed + custom libraries by default, search the index when you type. Each
row is state-aware:
+ Add to project — installs if needed, then declares it on the active board
In project (toggle) — click to remove from this board's manifest
Uninstall / Remove — free the cache / remove your custom upload
'Install' is folded into 'Add to project' (install-on-add) for simplicity. The
per-board manifest (board.libraries) stays the compile scope. The pro custom-zip
upload button still injects into .lib-modal-header. The in-modal velxio.json
editor tab is gone (the manifest is shown by the explorer's libraries.json file).
The Library Manager Installed tab + the velxio.json add-autocomplete now merge
the user's per-user custom uploads (getCustomLibraries -> GET /api/pro/libraries/
custom) with the shared global index list, so users can see and reuse their own
uploads (which live in the per-user store, not the global list). A custom lib's
button removes it via the per-user delete endpoint (not arduino-cli uninstall,
which would not find it). Degrades to [] for OSS/anon.
- compile.py: owner_id = project owner ELSE the requester (so an unsaved
compile resolves the libs the user just uploaded, which are their own);
threaded requester_id into _run_compile from both call sites.
- LibraryManagerModal: on a custom .zip upload, auto-add the lib to the active
board's velxio.json + show the Project tab, so the compile resolves it via the
owner per-user path (the upload now lands in the per-user store, not the
shared dir, so it must be declared to be found).
Library manifests are now PER-BOARD (each board carries its own velxio.json),
so two boards in one project can use different (even conflicting) libraries
without clashing — the multi-board extension of the no-clash guarantee.
- board.libraries on BoardInstance + serialisableBoard: rides in boards_json,
so it round-trips, dirty-checks, autosaves and restores natively. This also
removes the load-restore hacks (useLibraryManifestStore + applyProjectManifest
deleted): the manifest is plain board state.
- loadProjectState now restores per-board boardOptions/spiffsFiles/libraries
(it previously dropped them).
- EditorToolbar single + compile-all send the COMPILING board's libraries.
- Backend compile.py prefers the client's per-board request.libraries; the
project-level libraries_json (now the union of all boards) is the fallback.
- buildLoadPayload migrates pre-per-board projects: seed each board with the
project union so they keep compiling scoped.
- Library Manager 'In project' tab edits the ACTIVE board's velxio.json (shows
the board name) and the add field is now an autocomplete (installed libs +
index search) so users pick from a list instead of typing names.
Deletes useLibraryManifestStore.ts + applyProjectManifest.ts.
End users can now configure a project's declared libraries (the compile scope):
- Library Manager gains an 'In project' tab = the project's velxio.json:
declared libs as removable rows, quick add-by-name, and a raw velxio.json
editor. Installing a library auto-adds it to the project. Installed-tab rows
get an 'Add to project' toggle.
- FileExplorer shows a velxio.json entry (with declared count) that opens the
Library Manager via a window event the toolbar listens for.
- applyProjectManifest(): restore a saved project's manifest into the store on
load so the editor/toolbar/Library Manager/velxio.json reflect it.
- computeProjectStateHash() includes the manifest so declaring a library marks
the project dirty and autosaves.
Note: the OSS ProjectByIdPage also calls applyProjectManifest for parity, but
velxio.dev routes the pro-overlay ProjectByIdPage (wired separately).
ComponentPickerModal — the "Add Component" dialog:
- Header (title + close button), search input placeholder + clear,
category tabs (All Components / Boards), loading + empty-state
copy, "Clear filters" button.
LibraryManagerModal — the Arduino library browser:
- Window title, Search / Installed tabs, filter input placeholder.
- Search-tab states: searching-for-query, generic loading, no
results (with optional query interpolation).
- Per-library row: "by {{author}}" caption, Install / Installing /
Uninstall / Uninstalling button labels.
- Installed-tab empty-state with the prompt to use the Search tab.
Brand and product names left untouched ("LIBRARY MANAGER" stays
all-caps in English; the localised variants follow each language's
convention for product UI titles). Hand-translated for all 9
locales.
InstallLibrariesModal still pending — it's the auto-install
prompt that fires when an example needs libraries; smaller scope
but lives in the same area.
Backend:
- Add version field to InstallLibraryRequest
- Add fallback and requested_version to InstallResponse
- Add DELETE /api/libraries/uninstall endpoint
- Enhance install_library() for versioned installs (LibName@version)
- Add semver validation and fallback logic
- Add uninstall_library() method
- Fix _parse_version() to reject non-numeric version parts
Frontend:
- Update installLibrary() with optional version parameter
- Add uninstallLibrary() and resolveLibraryVersion() helpers
- Add version selector dropdown in Library Manager
- Add UNINSTALL button for installed libraries
- Show fallback messages when requested version unavailable
- Add parseLibSpec() and version badges in InstallLibrariesModal
- Modified the index file to reflect the new naming convention for Velxio components.
- Changed JSX declarations to use 'velxio-' prefix for various components.
- Updated component overrides to replace 'wokwi-' with 'velxio-' for logic gates and other components.
- Adjusted SVG generation script to use 'velxio-' prefix for BMP280 and Raspberry Pi components.
- Marked submodules as dirty in QEMU and RP2040 libraries.
- Added .prettierignore and .prettierrc.json for consistent code formatting.
- Introduced InstrumentComponent with support for Voltmeter and Ammeter, including pin information handling.
- Added tracking for simulation events: start, stop, and reset.
- Implemented tracking for library manager interactions, including library installations.
- Enhanced project management tracking with save and create project events.
- Integrated tracking for user authentication events: sign-up and login.
- Added tracking for CTA clicks on landing and SEO pages.
- Updated analytics utility functions to support new tracking events.
- Improved GitHub and Discord link tracking in the app header.
- Refactored existing components to utilize new tracking functions for better user engagement insights.