diff --git a/api/components/corner-action.css b/api/client/components/corner-action.css
similarity index 100%
rename from api/components/corner-action.css
rename to api/client/components/corner-action.css
diff --git a/api/components/corner-action.mjs b/api/client/components/corner-action.mjs
similarity index 97%
rename from api/components/corner-action.mjs
rename to api/client/components/corner-action.mjs
index 3b21cf0..85dbe05 100644
--- a/api/components/corner-action.mjs
+++ b/api/client/components/corner-action.mjs
@@ -12,7 +12,7 @@
  * @module notion-enhancer/api/components/corner-action
  */
 
-import { web } from '../_.mjs';
+import { web } from '../../index.mjs';
 
 web.loadStylesheet('api/components/corner-action.css');
 
diff --git a/api/components/feather.mjs b/api/client/components/feather.mjs
similarity index 96%
rename from api/components/feather.mjs
rename to api/client/components/feather.mjs
index 087b3da..61108a7 100644
--- a/api/components/feather.mjs
+++ b/api/client/components/feather.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/components/feather
  */
 
-import { fs, web } from '../_.mjs';
+import { fs, web } from '../../index.mjs';
 
 let _$iconSheet;
 
diff --git a/api/components/_.mjs b/api/client/components/index.mjs
similarity index 100%
rename from api/components/_.mjs
rename to api/client/components/index.mjs
diff --git a/api/components/panel.css b/api/client/components/panel.css
similarity index 100%
rename from api/components/panel.css
rename to api/client/components/panel.css
diff --git a/api/components/panel.mjs b/api/client/components/panel.mjs
similarity index 99%
rename from api/components/panel.mjs
rename to api/client/components/panel.mjs
index 3613372..d7e9e5f 100644
--- a/api/components/panel.mjs
+++ b/api/client/components/panel.mjs
@@ -12,7 +12,7 @@
  * @module notion-enhancer/api/components/side-panel
  */
 
-import { fmt, web, components, registry } from '../_.mjs';
+import { fmt, web, components, registry } from '../../index.mjs';
 
 web.loadStylesheet('api/components/panel.css');
 
diff --git a/api/components/tooltip.css b/api/client/components/tooltip.css
similarity index 100%
rename from api/components/tooltip.css
rename to api/client/components/tooltip.css
diff --git a/api/components/tooltip.mjs b/api/client/components/tooltip.mjs
similarity index 97%
rename from api/components/tooltip.mjs
rename to api/client/components/tooltip.mjs
index 83cfd0d..7e55473 100644
--- a/api/components/tooltip.mjs
+++ b/api/client/components/tooltip.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/components/tooltip
  */
 
-import { fmt, web } from '../_.mjs';
+import { fmt, web } from '../../index.mjs';
 
 const _$tooltip = web.html`<div id="enhancer--tooltip"></div>`;
 web.loadStylesheet('api/components/tooltip.css');
diff --git a/api/env.mjs b/api/client/env.mjs
similarity index 95%
rename from api/env.mjs
rename to api/client/env.mjs
index 9cb89ff..91142cf 100644
--- a/api/env.mjs
+++ b/api/client/env.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/env
  */
 
-import * as env from '../env/env.mjs';
+import * as env from '../../env/env.mjs';
 
 /**
  * the environment/platform name code is currently being executed in
diff --git a/api/fmt.mjs b/api/client/fmt.mjs
similarity index 98%
rename from api/fmt.mjs
rename to api/client/fmt.mjs
index 53881f7..a1f94d7 100644
--- a/api/fmt.mjs
+++ b/api/client/fmt.mjs
@@ -11,9 +11,10 @@
  * @module notion-enhancer/api/fmt
  */
 
-import { web, fs, components } from './_.mjs';
+import { web, fs, components } from '../index.mjs';
+import '../../dep/prism.min.js';
+import '../../dep/markdown-it.min.js';
 
-import '../dep/prism.min.js';
 /** syntax highlighting using https://prismjs.com/ */
 export const prism = Prism;
 Prism.manual = true;
@@ -24,7 +25,6 @@ Prism.hooks.add('complete', async (event) => {
     .prepend(web.html`${await components.feather('clipboard')}`);
 });
 
-import '../dep/markdown-it.min.js';
 /** markdown -> html using https://github.com/markdown-it/markdown-it/ */
 export const md = new markdownit({
   linkify: true,
diff --git a/api/fs.mjs b/api/client/fs.mjs
similarity index 97%
rename from api/fs.mjs
rename to api/client/fs.mjs
index e821d87..4484085 100644
--- a/api/fs.mjs
+++ b/api/client/fs.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/fs
  */
 
-import * as fs from '../env/fs.mjs';
+import * as fs from '../../env/fs.mjs';
 
 /**
  * transform a path relative to the enhancer root directory into an absolute path
diff --git a/api/notion.mjs b/api/client/notion.mjs
similarity index 99%
rename from api/notion.mjs
rename to api/client/notion.mjs
index cd9a565..9834f90 100644
--- a/api/notion.mjs
+++ b/api/client/notion.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/notion
  */
 
-import { web, fs, fmt } from './_.mjs';
+import { web, fs, fmt } from '../index.mjs';
 
 const standardiseUUID = (uuid) => {
   if (uuid?.length === 32 && !uuid.includes('-')) {
diff --git a/api/registry-validation.mjs b/api/client/registry-validation.mjs
similarity index 99%
rename from api/registry-validation.mjs
rename to api/client/registry-validation.mjs
index 12b13fb..e75e34e 100644
--- a/api/registry-validation.mjs
+++ b/api/client/registry-validation.mjs
@@ -6,7 +6,7 @@
 
 'use strict';
 
-import { fmt, registry } from './_.mjs';
+import { fmt, registry } from '../index.mjs';
 
 const check = async (
   mod,
diff --git a/api/registry.mjs b/api/client/registry.mjs
similarity index 98%
rename from api/registry.mjs
rename to api/client/registry.mjs
index 6fa99a1..eafd41c 100644
--- a/api/registry.mjs
+++ b/api/client/registry.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/registry
  */
 
-import { env, fs, storage } from './_.mjs';
+import { env, fs, storage } from '../index.mjs';
 import { validate } from './registry-validation.mjs';
 
 /**
diff --git a/api/storage.mjs b/api/client/storage.mjs
similarity index 88%
rename from api/storage.mjs
rename to api/client/storage.mjs
index 17d1ab4..a1d9c66 100644
--- a/api/storage.mjs
+++ b/api/client/storage.mjs
@@ -11,7 +11,7 @@
  * @module notion-enhancer/api/storage
  */
 
-import * as storage from '../env/storage.mjs';
+import * as storage from '../../env/storage.mjs';
 
 /**
  * get persisted data
@@ -59,9 +59,7 @@ export const removeChangeListener = storage.removeChangeListener;
 /**
  * @callback onStorageChangeCallback
  * @param {object} event
- * @param {string} event.type - 'set' or 'reset'
- * @param {string} event.namespace- the name of the store, e.g. a mod id
- * @param {string} [event.key] - the key associated with the changed value
+ * @param {string} event.path- the path of keys to the changed value
  * @param {string} [event.new] - the new value being persisted to the store
  * @param {string} [event.old] - the previous value associated with the key
  */
diff --git a/api/web.mjs b/api/client/web.mjs
similarity index 99%
rename from api/web.mjs
rename to api/client/web.mjs
index baa101c..342824c 100644
--- a/api/web.mjs
+++ b/api/client/web.mjs
@@ -11,14 +11,14 @@
  * @module notion-enhancer/api/web
  */
 
-import { fs } from './_.mjs';
+import { fs } from '../index.mjs';
+import '../../dep/jscolor.min.js';
 
 let _hotkeyEventListeners = [],
   _documentObserver,
   _documentObserverListeners = [],
   _documentObserverEvents = [];
 
-import '../dep/jscolor.min.js';
 /** color picker with alpha channel using https://jscolor.com/ */
 export const jscolor = JSColor;
 
diff --git a/api/_.cjs b/api/index.cjs
similarity index 65%
rename from api/_.cjs
rename to api/index.cjs
index c1424d7..92d255d 100644
--- a/api/_.cjs
+++ b/api/index.cjs
@@ -10,13 +10,13 @@
 
 module.exports = {
   /** environment-specific methods and constants */
-  env: require('notion-enhancer/api/env.cjs'),
+  env: require('notion-enhancer/api/node/env.cjs'),
   /** environment-specific file reading */
-  fs: require('notion-enhancer/api/fs.cjs'),
+  fs: require('notion-enhancer/api/node/fs.cjs'),
   /** environment-specific data persistence */
-  storage: require('notion-enhancer/api/storage.cjs'),
+  storage: require('notion-enhancer/api/node/storage.cjs'),
   /** helpers for formatting, validating and parsing values */
-  fmt: require('notion-enhancer/api/fmt.cjs'),
+  fmt: require('notion-enhancer/api/node/fmt.cjs'),
   /** interactions with the enhancer's repository of mods */
-  registry: require('notion-enhancer/api/registry.cjs'),
+  registry: require('notion-enhancer/api/node/registry.cjs'),
 };
diff --git a/api/_.mjs b/api/index.mjs
similarity index 62%
rename from api/_.mjs
rename to api/index.mjs
index a81a82a..def92b8 100644
--- a/api/_.mjs
+++ b/api/index.mjs
@@ -9,19 +9,19 @@
 /** @module notion-enhancer/api */
 
 /** environment-specific methods and constants */
-export * as env from './env.mjs';
+export * as env from './client/env.mjs';
 /** environment-specific file reading */
-export * as fs from './fs.mjs';
+export * as fs from './client/fs.mjs';
 /** environment-specific data persistence */
-export * as storage from './storage.mjs';
+export * as storage from './client/storage.mjs';
 
 /** a basic wrapper around notion's unofficial api */
-export * as notion from './notion.mjs';
+export * as notion from './client/notion.mjs';
 /** helpers for formatting, validating and parsing values */
-export * as fmt from './fmt.mjs';
+export * as fmt from './client/fmt.mjs';
 /** interactions with the enhancer's repository of mods */
-export * as registry from './registry.mjs';
+export * as registry from './client/registry.mjs';
 /** helpers for manipulation of a webpage */
-export * as web from './web.mjs';
+export * as web from './client/web.mjs';
 /** shared notion-style elements */
-export * as components from './components/_.mjs';
+export * as components from './client/components/index.mjs';
diff --git a/api/env.cjs b/api/node/env.cjs
similarity index 95%
rename from api/env.cjs
rename to api/node/env.cjs
index 27a6a49..536e442 100644
--- a/api/env.cjs
+++ b/api/node/env.cjs
@@ -12,7 +12,7 @@ module.exports = {};
  * @module notion-enhancer/api/env
  */
 
-const env = require('../env/env.cjs');
+const env = require('notion-enhancer/env/env.cjs');
 
 /**
  * the environment/platform name code is currently being executed in
diff --git a/api/fmt.cjs b/api/node/fmt.cjs
similarity index 98%
rename from api/fmt.cjs
rename to api/node/fmt.cjs
index a429b19..e82716e 100644
--- a/api/fmt.cjs
+++ b/api/node/fmt.cjs
@@ -131,7 +131,7 @@ module.exports.is = async (value, type, { extension = '' } = {}) => {
     case 'color':
       return typeof value === 'string' && test(value, patterns[type]) && extension;
     case 'file': {
-      const { isFile } = require('notion-enhancer/api/fs.cjs');
+      const { isFile } = require('notion-enhancer/api/node/fs.cjs');
       return typeof value === 'string' && value && (await isFile(value)) && extension;
     }
   }
diff --git a/api/fs.cjs b/api/node/fs.cjs
similarity index 96%
rename from api/fs.cjs
rename to api/node/fs.cjs
index ed352ab..d189dcd 100644
--- a/api/fs.cjs
+++ b/api/node/fs.cjs
@@ -12,7 +12,7 @@ module.exports = {};
  * @module notion-enhancer/api/fs
  */
 
-const fs = require('../env/fs.cjs');
+const fs = require('notion-enhancer/env/fs.cjs');
 
 /**
  * transform a path relative to the enhancer root directory into an absolute path
diff --git a/api/registry-validation.cjs b/api/node/registry-validation.cjs
similarity index 97%
rename from api/registry-validation.cjs
rename to api/node/registry-validation.cjs
index a0833ad..9e385c4 100644
--- a/api/registry-validation.cjs
+++ b/api/node/registry-validation.cjs
@@ -19,7 +19,7 @@ const check = async (
     optional = false,
   } = {}
 ) => {
-  const { is } = require('notion-enhancer/api/fmt.cjs');
+  const { is } = require('notion-enhancer/api/node/fmt.cjs');
   let test;
   for (const type of Array.isArray(types) ? [types] : types.split('|')) {
     if (type === 'file') {
@@ -39,7 +39,7 @@ const check = async (
 };
 
 const validateEnvironments = async (mod) => {
-    const { supportedEnvs } = require('notion-enhancer/api/registry.cjs');
+    const { supportedEnvs } = require('notion-enhancer/api/node/registry.cjs');
     mod.environments = mod.environments ?? supportedEnvs;
     const isArray = await check(mod, 'environments', mod.environments, 'array');
     if (!isArray) return false;
@@ -134,7 +134,7 @@ const validateEnvironments = async (mod) => {
     return tests;
   },
   validateOptions = async (mod) => {
-    const { supportedEnvs, optionTypes } = require('notion-enhancer/api/registry.cjs'),
+    const { supportedEnvs, optionTypes } = require('notion-enhancer/api/node/registry.cjs'),
       isArray = await check(mod, 'options', mod.options, 'array');
     if (!isArray) return false;
     const tests = [];
diff --git a/api/registry.cjs b/api/node/registry.cjs
similarity index 91%
rename from api/registry.cjs
rename to api/node/registry.cjs
index ed88ba9..9aca6bc 100644
--- a/api/registry.cjs
+++ b/api/node/registry.cjs
@@ -41,7 +41,7 @@ module.exports.optionTypes = ['toggle', 'select', 'text', 'number', 'color', 'fi
  * @returns {string}
  */
 module.exports.profileName = async () => {
-  const storage = require('notion-enhancer/api/storage.cjs');
+  const storage = require('notion-enhancer/api/node/storage.cjs');
   return storage.get(['currentprofile'], 'default');
 };
 
@@ -50,7 +50,7 @@ module.exports.profileName = async () => {
  * @returns {object} the get/set functions for the profile's storage
  */
 module.exports.profileDB = async () => {
-  const storage = require('notion-enhancer/api/storage.cjs');
+  const storage = require('notion-enhancer/api/node/storage.cjs');
   return storage.db(['profiles', await module.exports.profileName()]);
 };
 
@@ -63,8 +63,8 @@ let _list,
  */
 module.exports.list = async (filter = (mod) => true) => {
   if (!_list) {
-    const { validate } = require('notion-enhancer/api/registry-validation.cjs'),
-      { getJSON } = require('notion-enhancer/api/fs.cjs');
+    const { validate } = require('notion-enhancer/api/node/registry-validation.cjs'),
+      { getJSON } = require('notion-enhancer/api/node/fs.cjs');
     _list = new Promise(async (res, rej) => {
       const passed = [];
       for (const dir of await getJSON('repo/registry.json')) {
@@ -112,7 +112,7 @@ module.exports.get = async (id) => {
  * @returns {boolean} whether or not the mod is enabled
  */
 module.exports.enabled = async (id) => {
-  const env = require('notion-enhancer/api/env.cjs'),
+  const env = require('notion-enhancer/api/node/env.cjs'),
     mod = await module.exports.get(id);
   if (!mod.environments.includes(env.name)) return false;
   if (module.exports.core.includes(id)) return true;
@@ -149,7 +149,7 @@ module.exports.optionDefault = async (id, key) => {
  * @returns {object} an object with the wrapped get/set functions
  */
 module.exports.db = async (id) => {
-  const storage = require('notion-enhancer/api/storage.cjs'),
+  const storage = require('notion-enhancer/api/node/storage.cjs'),
     db = await module.exports.profileDB();
   return storage.db(
     [id],
diff --git a/api/storage.cjs b/api/node/storage.cjs
similarity index 88%
rename from api/storage.cjs
rename to api/node/storage.cjs
index 47f01eb..db30e53 100644
--- a/api/storage.cjs
+++ b/api/node/storage.cjs
@@ -12,7 +12,7 @@ module.exports = {};
  * @module notion-enhancer/api/storage
  */
 
-const storage = require('../env/storage.cjs');
+const storage = require('notion-enhancer/env/storage.cjs');
 
 /**
  * get persisted data
@@ -60,9 +60,7 @@ module.exports.removeChangeListener = storage.removeChangeListener;
 /**
  * @callback onStorageChangeCallback
  * @param {object} event
- * @param {string} event.type - 'set' or 'reset'
- * @param {string} event.namespace- the name of the store, e.g. a mod id
- * @param {string} [event.key] - the key associated with the changed value
+ * @param {string} event.path- the path of keys to the changed value
  * @param {string} [event.new] - the new value being persisted to the store
  * @param {string} [event.old] - the previous value associated with the key
  */