A surface
extension/ sits beside api/ and web/
It earns its own directory because its config, its tests and its release are all different answers — and it reaches the same services with the same client.
$ fli make:extension
$ fli dev:extension # MV3, hot-reloaded
$ fli extension:build
Replaces
PlasmoWXTa hand-rolled MV3 setup
The relay
A service worker carries calls to the API
The adapter is the real client rather than a lookalike, so sign-in, live updates and gating behave exactly as they do in the app.
Replaces
fetch calls duplicated in the worker
Islands
A content script builds in lib mode
An MV3 content script is a CLASSIC script, so the preload helper a bundler normally writes makes the engine reject the whole file at parse time — before one line of it runs, with nothing at build time saying so.
Replaces
Nothing — there is no common equivalent to swap out.
The store
It remembers the query its rows answer
Nothing else can grade a record that arrives later: without the query, an update belonging to a different filter lands in the list anyway.
Replaces
a cache keyed by id alone
Permissions
extension:audit grades the manifest
A permission is easy to add while debugging and invisible afterwards, right up until a store review.
Replaces
reading the manifest before you submit