experiments in a post-browser web

Peek Core API Reference#

The window.app API is automatically injected into all peek:// pages. This API provides access to window management, data storage, messaging, and shortcuts.

Context Detection#

// Check if running in peek:// context
if (window.app) {
  // API available
}

// Source address of current page
const source = window.location.toString();

// Context types:
// - peek://app/...     Core application pages
// - peek://ext/{id}/...  Extension pages

Window Management#

window.app.window.open(url, options)#

Open a new window.

const result = await window.app.window.open('peek://app/settings/settings.html', {
  key: 'settings',           // Reuse window with same key
  width: 900,                // Window width
  height: 650,               // Window height
  x: 100,                    // X position
  y: 100,                    // Y position
  title: 'Settings',         // Window title
  modal: true,               // Modal behavior
  transparent: false,        // Transparent background
  decorations: true,         // Window decorations
  alwaysOnTop: false,        // Stay on top
  visible: true,             // Initially visible
  resizable: true,           // Allow resize
  keepLive: false            // Keep window alive when closed
});
// Returns: { success: true, id: 'window_label' }

window.app.window.close(id?)#

Close a window. If no id, closes current window.

await window.app.window.close();              // Close current
await window.app.window.close('settings');    // Close by id
await window.app.window.close({ id: 'settings' }); // Object form

window.app.window.hide(id?) / window.app.window.show(id?)#

Toggle window visibility.

await window.app.window.hide('main');
await window.app.window.show('main');

window.app.window.focus(id?)#

Bring window to front and focus it.

await window.app.window.focus('settings');

window.app.window.list()#

List all open windows.

const result = await window.app.window.list();
// Returns: {
//   success: true,
//   data: [{
//     id: 'main',
//     label: 'main',
//     url: 'peek://app/background.html',
//     source: 'peek://app/background.html',
//     visible: false,
//     focused: false
//   }, ...]
// }

window.app.window.exists(id)#

Check if a window exists.

const result = await window.app.window.exists('settings');
// Returns: { success: true, data: true }

Datastore#

All datastore methods return { success: boolean, data?: any, error?: string }.

Addresses#

// Add a new address
const result = await window.app.datastore.addAddress('https://example.com', {
  title: 'Example',
  favicon: 'https://example.com/favicon.ico'
});
// Returns: { success: true, data: { id: 'addr_123', ... } }

// Get address by ID
const addr = await window.app.datastore.getAddress('addr_123');

// Update address
await window.app.datastore.updateAddress('addr_123', {
  title: 'New Title'
});

// Query addresses
const results = await window.app.datastore.queryAddresses({
  uri: 'example.com',  // Partial match
  limit: 10,
  offset: 0
});

Visits#

// Add a visit
await window.app.datastore.addVisit('addr_123', {
  referrer: 'addr_456'
});

// Query visits
const visits = await window.app.datastore.queryVisits({
  addressId: 'addr_123',
  limit: 50
});

Tags#

// Get or create a tag
const tag = await window.app.datastore.getOrCreateTag('important');
// Returns: { success: true, data: { id: 'tag_123', name: 'important' } }

// Tag an address
await window.app.datastore.tagAddress('addr_123', 'tag_123');

// Untag an address
await window.app.datastore.untagAddress('addr_123', 'tag_123');

// Get tags for an address
const tags = await window.app.datastore.getAddressTags('addr_123');

Generic Table Access#

// Get all rows from a table
const table = await window.app.datastore.getTable('extensions');
// Returns: { success: true, data: { row_id: { ... }, ... } }

// Set a row
await window.app.datastore.setRow('extensions', 'my-ext', {
  name: 'My Extension',
  enabled: true
});

Statistics#

const stats = await window.app.datastore.getStats();
// Returns: { success: true, data: {
//   addresses: 150,
//   visits: 1200,
//   tags: 25
// }}

PubSub Messaging#

Cross-window communication via publish/subscribe.

Scopes#

window.app.scopes = {
  SYSTEM: 1,  // System messages
  SELF: 2,    // Same source only
  GLOBAL: 3   // All windows
};

window.app.publish(topic, message, scope)#

Publish a message.

window.app.publish('settings:changed', { theme: 'dark' }, window.app.scopes.GLOBAL);

window.app.subscribe(topic, callback, scope)#

Subscribe to messages.

window.app.subscribe('settings:changed', (msg) => {
  console.log('Settings changed:', msg.data);
}, window.app.scopes.GLOBAL);

Keyboard Shortcuts#

window.app.shortcuts.register(shortcut, callback, options)#

Register a keyboard shortcut.

// Local shortcut (only when app focused)
window.app.shortcuts.register('Command+K', () => {
  console.log('Command+K pressed');
});

// Global shortcut (works even when app not focused)
window.app.shortcuts.register('Option+Space', () => {
  console.log('Global shortcut triggered');
}, { global: true });

Shortcut format:

  • Modifiers: Command, Control, Alt, Option, Shift, CommandOrControl
  • Keys: A-Z, 0-9, F1-F12, Space, Enter, Escape, ArrowUp, etc.
  • Examples: Command+Shift+P, Alt+1, Option+ArrowDown

window.app.shortcuts.unregister(shortcut, options)#

Unregister a shortcut.

window.app.shortcuts.unregister('Command+K');
window.app.shortcuts.unregister('Option+Space', { global: true });

Commands (Command Palette)#

Register commands that appear in the command palette.

window.app.commands.register(command)#

window.app.commands.register({
  name: 'my-extension:do-thing',
  description: 'Do the thing',
  execute: () => {
    console.log('Doing the thing');
  }
});

window.app.commands.unregister(name)#

window.app.commands.unregister('my-extension:do-thing');

window.app.commands.getAll()#

const commands = await window.app.commands.getAll();

Escape Handling#

Handle the ESC key to prevent window from closing.

window.app.escape.onEscape(() => {
  if (hasUnsavedChanges) {
    showConfirmDialog();
    return { handled: true };  // Prevent close
  }
  return { handled: false };   // Allow close
});

Logging#

Log messages to the backend console.

window.app.log('Something happened', { detail: 'value' });
// Output in terminal: [peek://app/mypage.html] Something happened { detail: 'value' }

Debug Mode#

if (window.app.debug) {
  console.log('Debug mode enabled');
}

// Debug levels
window.app.debugLevels = { BASIC: 1, FIRST_RUN: 2 };
window.app.debugLevel; // Current level

Extensions API#

Only available in core app pages (peek://app/...).

// Check permission
if (window.app.extensions._hasPermission()) {
  const exts = await window.app.extensions.list();
}

Settings API#

Only available in extension pages (peek://ext/{id}/...).

// Get all settings
const settings = await window.app.settings.get();

// Set all settings
await window.app.settings.set({ theme: 'dark' });

// Get/set individual keys
const theme = await window.app.settings.getKey('theme');
await window.app.settings.setKey('theme', 'light');

Response Format#

All async API methods return a consistent response format:

{
  success: true,      // Operation succeeded
  data: any,          // Result data (if applicable)
  error: string       // Error message (if success: false)
}

Always check success before using data:

const result = await window.app.datastore.getAddress(id);
if (result.success) {
  console.log(result.data);
} else {
  console.error(result.error);
}