> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mercuryworkshop/scramjet/llms.txt
> Use this file to discover all available pages before exploring further.

# Working with frames

> Create and manage isolated browsing contexts using ScramjetFrame

The `ScramjetFrame` class provides an abstraction over proxy iframe creation, allowing you to manage isolated browsing contexts without worrying about proxy internals.

## Creating a frame

Frames are created using the `createFrame()` method on your `ScramjetController` instance:

```javascript theme={null}
const { ScramjetController } = $scramjetLoadController();
const scramjet = new ScramjetController({ prefix: '/scramjet/' });
await scramjet.init();

// Create a new frame
const frame = scramjet.createFrame();

// Add it to the DOM
document.body.appendChild(frame.frame);
```

<Tip>
  You can also pass an existing iframe element to `createFrame()` if you want to use a pre-configured iframe:

  ```javascript theme={null}
  const existingIframe = document.getElementById('myIframe');
  const frame = scramjet.createFrame(existingIframe);
  ```
</Tip>

## Navigation methods

The `ScramjetFrame` class provides several methods for controlling navigation within the isolated context:

### Navigate to a URL

Use the `go()` method to navigate to a new URL:

```javascript theme={null}
// Navigate with a string URL
frame.go('https://example.com');

// Navigate with a URL object
frame.go(new URL('https://example.com/page'));
```

### Browser history navigation

<CodeGroup>
  ```javascript Back theme={null}
  // Go back in history
  frame.back();
  ```

  ```javascript Forward theme={null}
  // Go forward in history
  frame.forward();
  ```

  ```javascript Reload theme={null}
  // Reload the current page
  frame.reload();
  ```
</CodeGroup>

## Accessing frame properties

The `ScramjetFrame` instance provides access to useful properties:

### Current URL

Get the current proxified URL:

```javascript theme={null}
const currentUrl = frame.url;
console.log('Current URL:', currentUrl.href);
console.log('Hostname:', currentUrl.hostname);
console.log('Path:', currentUrl.pathname);
```

### ScramjetClient instance

Access the `ScramjetClient` instance running inside the iframe:

```javascript theme={null}
const client = frame.client;
// The client provides low-level access to the proxy internals
```

<Note>
  The `client` property gives you access to the Scramjet instance running within the iframe's context, allowing for advanced manipulation if needed.
</Note>

### Raw iframe element

Access the underlying HTMLIFrameElement:

```javascript theme={null}
const iframeElement = frame.frame;

// You can manipulate the iframe directly
iframeElement.style.width = '100%';
iframeElement.style.height = '600px';
iframeElement.setAttribute('sandbox', 'allow-scripts allow-same-origin');
```

## Building a browser interface

Here's a complete example of building a simple browser interface with navigation controls:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: system-ui, -apple-system, sans-serif;
      display: flex;
      flex-direction: column;
      height: 100vh;
    }

    .toolbar {
      display: flex;
      gap: 8px;
      padding: 12px;
      background: #f5f5f5;
      border-bottom: 1px solid #ddd;
    }

    .toolbar button {
      padding: 8px 16px;
      border: 1px solid #ccc;
      background: white;
      cursor: pointer;
      border-radius: 4px;
    }

    .toolbar button:hover {
      background: #e9e9e9;
    }

    .toolbar input {
      flex: 1;
      padding: 8px 12px;
      border: 1px solid #ccc;
      border-radius: 4px;
      font-size: 14px;
    }

    #frameContainer {
      flex: 1;
      position: relative;
    }

    iframe {
      width: 100%;
      height: 100%;
      border: none;
    }
  </style>
</head>
<body>
  <div class="toolbar">
    <button id="backBtn">← Back</button>
    <button id="forwardBtn">Forward →</button>
    <button id="reloadBtn">↻ Reload</button>
    <input type="text" id="urlBar" placeholder="Enter URL..." />
    <button id="goBtn">Go</button>
  </div>
  <div id="frameContainer"></div>

  <script>
    (async () => {
      // Initialize Scramjet
      if ('serviceWorker' in navigator) {
        await navigator.serviceWorker.register('/scramjet.all.js', {
          scope: '/scramjet/',
        });
      }

      await navigator.serviceWorker.ready;

      const { ScramjetController } = $scramjetLoadController();
      const scramjet = new ScramjetController({
        prefix: '/scramjet/',
      });
      await scramjet.init();

      // Create frame
      const frame = scramjet.createFrame();
      document.getElementById('frameContainer').appendChild(frame.frame);

      // Get UI elements
      const urlBar = document.getElementById('urlBar');
      const backBtn = document.getElementById('backBtn');
      const forwardBtn = document.getElementById('forwardBtn');
      const reloadBtn = document.getElementById('reloadBtn');
      const goBtn = document.getElementById('goBtn');

      // Navigation functions
      const navigate = () => {
        let url = urlBar.value.trim();
        if (!url) return;

        // Add protocol if missing
        if (!url.match(/^https?:\/\//)) {
          url = 'https://' + url;
        }

        frame.go(url);
      };

      // Event listeners
      goBtn.addEventListener('click', navigate);
      urlBar.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') navigate();
      });

      backBtn.addEventListener('click', () => frame.back());
      forwardBtn.addEventListener('click', () => frame.forward());
      reloadBtn.addEventListener('click', () => frame.reload());

      // Update URL bar when navigation occurs
      frame.addEventListener('urlchange', (event) => {
        urlBar.value = event.url;
        document.title = event.url;
      });

      // Optional: Log navigation events
      frame.addEventListener('navigate', (event) => {
        console.log('Navigating to:', event.url);
      });

      // Start with a default page
      frame.go('https://example.com');
    })();
  </script>
</body>
</html>
```

## Multiple frames

You can create and manage multiple frames simultaneously:

```javascript theme={null}
const { ScramjetController } = $scramjetLoadController();
const scramjet = new ScramjetController({ prefix: '/scramjet/' });
await scramjet.init();

// Create multiple frames
const frame1 = scramjet.createFrame();
const frame2 = scramjet.createFrame();

document.getElementById('container1').appendChild(frame1.frame);
document.getElementById('container2').appendChild(frame2.frame);

// Navigate each frame independently
frame1.go('https://example.com');
frame2.go('https://example.org');

// Each frame has independent event listeners
frame1.addEventListener('urlchange', (e) => {
  console.log('Frame 1 URL:', e.url);
});

frame2.addEventListener('urlchange', (e) => {
  console.log('Frame 2 URL:', e.url);
});
```

## Advanced usage

### Detecting when context is ready

Listen for the `contextInit` event to know when the frame has fully initialized:

```javascript theme={null}
frame.addEventListener('contextInit', (event) => {
  console.log('Frame initialized!');
  console.log('Window object:', event.window);
  console.log('Client instance:', event.client);
});
```

### Styling frames

Style the iframe element to fit your application:

```javascript theme={null}
const frame = scramjet.createFrame();

// Apply styles directly
frame.frame.style.cssText = `
  width: 100%;
  height: 100%;
  border: none;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
`;

// Or use classes
frame.frame.className = 'proxy-frame';
```

### Frame cleanup

When you're done with a frame, remove it from the DOM:

```javascript theme={null}
// Remove the frame
frame.frame.remove();

// Or keep a reference and reuse it later
const frames = new Map();
frames.set('main', frame);

// Later...
const mainFrame = frames.get('main');
mainFrame.go('https://newurl.com');
```

## Related guides

<CardGroup cols={2}>
  <Card title="Event handling" icon="bolt" href="/guides/event-handling">
    Learn how to handle navigation, URL changes, and download events
  </Card>

  <Card title="Cookie management" icon="cookie" href="/guides/cookie-management">
    Manage cookies within isolated frame contexts
  </Card>
</CardGroup>
