Models 44

GPT-5 Nano

by OpenAIReasoning2 console errors
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
20.2 s
Cost
$0.0013
Output tokens
3,205
Spent thinking
0 tokens
Speed
165.4 tok/s
Console errors
2
First token after
864 ms
First visible text after
864 ms
Prompt tokens
423
Code size
11.4 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-5-nano
Reasoning sent
{"effort":"minimal"}
Max output
128,000 tokens
Generated
Nov 12, 2026

Console errors

Caught in the first 3 seconds after load, in a sandboxed iframe like the one above.

Failed to load resource: the server responded with a status of 404 ()

Failed to load resource: the server responded with a status of 404 ()

What it was asked

The prompt
“a 3D aquarium with Three.js where the fish swim away when I move the mouse near them (Load Three.js only through this import map: <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>)”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 324 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>3D Aquarium - Fish Swim Away</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    :root {
      --bg: #0b1020;
      --panel: rgba(10, 20, 40, 0.7);
      --text: #e9f0ff;
      --accent: #66e0ff;
    }
    html, body {
      margin: 0;
      padding: 0;
      height: 100%;
      background: linear-gradient(#0a0f1a, #0b1020);
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial;
      color: var(--text);
      overflow: hidden;
    }
    .container {
      position: relative;
      width: 100%;
      height: 100vh;
    }
    canvas {
      display: block;
      width: 100%;
      height: 100%;
    }
    /* Overlay */
    .overlay {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      background: linear-gradient(135deg, rgba(10,20,40,0.95), rgba(10,20,40,0.75));
      border: 1px solid rgba(100,180,255,0.6);
      border-radius: 12px;
      padding: 18px 22px;
      text-align: center;
      max-width: 90vw;
      box-shadow: 0 8px 30px rgba(0,0,0,0.4);
      z-index: 2;
      pointer-events: auto;
    }
    .overlay h1 {
      margin: 0 0 6px 0;
      font-size: 18px;
      letter-spacing: .4px;
    }
    .overlay p {
      margin: 0;
      font-size: 13px;
      color: #cbdcff;
    }
    .start {
      margin-top: 12px;
      display: inline-block;
      padding: 8px 14px;
      border-radius: 8px;
      background: linear-gradient(135deg, #2f6eff, #1b4bdc);
      color: white;
      font-weight: bold;
      cursor: pointer;
      user-select: none;
      border: none;
    }
    @media (max-width: 700px) {
      .overlay { padding: 14px; }
      .overlay h1 { font-size: 16px; }
      .overlay p { font-size: 12px; }
    }
  </style>
  <script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
    }
  }
  </script>
</head>
<body>
  <div class="container" id="scene-container" aria-label="3D aquarium scene">
    <div class="overlay" id="start-overlay" role="dialog" aria-label="Start instructions">
      <h1>3D Aquarium</h1>
      <p>Move your mouse near the fish to make them swim away. Click or press any key to start the simulation.</p>
      <button class="start" id="start-btn">Click or press a key to start</button>
    </div>
    <!-- The canvas will be created by Three.js -->
  </div>

  <script type="module">
    // Import Three.js modules
    import * as THREE from 'three';
    import { GLTFLoader } from 'three/addons/GLTFLoader.js';
    import { OrbitControls } from 'three/addons/OrbitControls.js';
    // We'll implement a simple AI-like steering without full physics for robustness.
    
    // Scene setup
    const container = document.getElementById('scene-container');
    const overlay = document.getElementById('start-overlay');
    const startBtn = document.getElementById('start-btn');
    let started = false;

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0a1a2a);

    const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 4, 12);

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
    renderer.setSize(window.innerWidth, window.innerHeight, false);
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement);

    // Simple underwater ambient light
    const ambient = new THREE.AmbientLight(0x88aaff, 0.6);
    scene.add(ambient);
    // Directional light to create shading
    const dir = new THREE.DirectionalLight(0xffffff, 0.4);
    dir.position.set(5, 10, 8);
    scene.add(dir);

    // Water plane (soft gradient)
    const waterGeo = new THREE.PlaneGeometry(60, 40);
    const waterMat = new THREE.MeshPhongMaterial({ color: 0x1b2b57, side: THREE.DoubleSide, transparent: true, opacity: 0.25 });
    const water = new THREE.Mesh(waterGeo, waterMat);
    water.rotation.x = -Math.PI / 2;
    water.position.y = -0.5;
    scene.add(water);

    // Aquarium boundary walls (very light)
    const wallGeo = new THREE.BoxGeometry(60, 16, 1);
    const wallMat = new THREE.MeshBasicMaterial({ color: 0x1b2b57, transparent: true, opacity: 0.25 });
    const backWall = new THREE.Mesh(wallGeo, wallMat);
    backWall.position.set(0, 4, -20);
    scene.add(backWall);

    // Fish factory: create several simple fish as animated colored spheres with tails
    const fishCount = 14;
    const fishList = [];

    // Simple fish geometry: sphere body with small tail (cone) per fish
    function createFish(i) {
      // Body
      const bodyGeo = new THREE.SphereGeometry(0.75, 12, 8);
      const bodyMat = new THREE.MeshStandardMaterial({ color: new THREE.Color(`hsl(${(i * 26) % 360}, 80%, 60%)`), flatShading: true });
      const body = new THREE.Mesh(bodyGeo, bodyMat);
      body.castShadow = false;
      body.receiveShadow = false;
      // Tail
      const tailGeo = new THREE.ConeGeometry(0.5, 1.2, 8);
      tailGeo.rotateZ(Math.PI / 2);
      const tailMat = new THREE.MeshStandardMaterial({ color: bodyMat.color });
      const tail = new THREE.Mesh(tailGeo, tailMat);
      tail.position.x = -0.95;
      tail.rotation.z = Math.PI;
      // Group
      const group = new THREE.Group();
      group.add(body);
      group.add(tail);
      // Initial position
      group.position.set((i - fishCount/2) * 3.0 + (Math.random() - 0.5), 0.8 + Math.random(), (Math.random() - 0.5) * 18);
      // Velocity vector
      group.userData = {
        velocity: new THREE.Vector3((Math.random() - 0.5) * 0.2, 0, (Math.random() - 0.5) * 0.7),
        speed: 0.08 + Math.random() * 0.08,
        targetDir: new THREE.Vector3(0, 0, -1)
      };
      // Add to scene
      scene.add(group);
      return group;
    }

    for (let i = 0; i < fishCount; i++) {
      fishList.push(createFish(i));
    }

    // Mouse interaction: compute world position of mouse ray and influence nearby fish by steering away
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2(9999, 9999); // offscreen
    function updateMousePosition(e) {
      const rect = renderer.domElement.getBoundingClientRect();
      const x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
      const y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
      mouse.set(x, y);
    }
    // The iframe specs require a click to start keyboard/mouse events – we'll enforce overlay until started
    function onStart() {
      if (started) return;
      started = true;
      overlay.style.display = 'none';
      // Small initial calibration: spawn a gentle drift
      fishList.forEach((f, idx) => {
        f.userData.velocity.applyAxisAngle(new THREE.Vector3(0,1,0), (Math.random()-0.5)*0.2);
      });
      // Allow keyboard focus for potential accessibility
      renderer.domElement.focus({ preventDefault: true });
    }

    window.addEventListener('keydown', (e) => {
      if (!started) onStart();
    }, { passive: true });
    startBtn.addEventListener('click', onStart);
    renderer.domElement.addEventListener('mousemove', updateMousePosition, { passive: true });

    // Resize handling
    function onResize() {
      const w = window.innerWidth;
      const h = window.innerHeight;
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
      renderer.setSize(w, h, false);
    }
    window.addEventListener('resize', onResize, { passive: true });
    onResize();

    // Simple AI: fish steer away from a virtual predator around mouse position in world space
    function steerAwayFromPoint(fish, pointWorld, dt) {
      // compute vector from point to fish
      const toFish = new THREE.Vector3().subVectors(fish.position, pointWorld);
      const dist = toFish.length();
      const influenceRadius = 6.0;
      if (dist < influenceRadius && dist > 0.0001) {
        const away = toFish.normalize();
        const strength = (influenceRadius - dist) / influenceRadius; // 0..1
        // Apply velocity change
        fish.userData.velocity.addScaledVector(away, strength * 0.6);
        // Cap speed
        const maxSpeed = 0.25;
        if (fish.userData.velocity.length() > maxSpeed) {
          fish.userData.velocity.normalize().multiplyScalar(maxSpeed);
        }
        // Orient body roughly away from center
        const targetDir = fish.userData.velocity.clone().normalize();
        const currentDir = new THREE.Vector3(1,0,0).applyQuaternion(fish.quaternion);
        // Lerp orientation toward velocity
        const axis = new THREE.Vector3().crossVectors(currentDir, targetDir).normalize();
        const angle = Math.acos(THREE.MathUtils.clamp(currentDir.dot(targetDir), -1, 1)) * 0.25;
        if (!Number.isNaN(angle) && axis.lengthSq()) {
          const q = new THREE.Quaternion().setFromAxisAngle(axis, angle);
          fish.quaternion.multiply(q);
        }
      }
    }

    // Gentle ground clamp
    function clampPosition(p) {
      if (p.x < -28) p.x = -28;
      if (p.x > 28) p.x = 28;
      if (p.y < 0.3) p.y = 0.3;
      if (p.y > 6) p.y = 6;
      if (p.z < -18) p.z = -18;
      if (p.z > 18) p.z = 18;
    }

    // Animation loop
    let lastTime = performance.now();
    function animate(now) {
      requestAnimationFrame(animate);
      const dt = Math.min(0.05, (now - lastTime) / 1000);
      lastTime = now;

      // Update controls (optional gentle orbit for visual appeal if started)
      // We'll implement automatic subtle wandering around center
      // Mouse-based avoidance
      // Convert mouse normalized device coordinates to a world point roughly in front of camera
      let avoidPoint = new THREE.Vector3(0, 0, -5);
      if (renderer && renderer.domElement && started) {
        // Unproject mouse
        const ndc = new THREE.Vector3(mouse.x, mouse.y, 0.5);
        ndc.unproject(camera);
        const dir = ndc.sub(camera.position).normalize();
        const dist = 8;
        avoidPoint = camera.position.clone().add(dir.multiplyScalar(dist));
      }

      // Update each fish
      for (let i = 0; i < fishList.length; i++) {
        const f = fishList[i];
        // Steering away from the avoid point
        if (started) steerAwayFromPoint(f, avoidPoint, dt);

        // Move
        f.position.addScaledVector(f.userData.velocity, dt * 60 * 0.01);

        // Gentle boundary wrapping to keep fish within view
        clampPosition(f.position);

        // Add a tiny sine-based vertical bob for liveliness
        f.position.y += Math.sin(now * 0.001 + i) * 0.0008;

        // Ensure body orientation faces movement direction (approx)
        if (f.userData.velocity.lengthSq() > 0.0001) {
          const dir = f.userData.velocity.clone().normalize();
          const quat = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(1,0,0), dir);
          f.quaternion.slerp(quat, 0.1);
        }
      }

      // Minor camera drift for depth
      camera.position.x = Math.sin(now * 0.00015) * 1.2;
      camera.position.z = 12 + Math.cos(now * 0.00018) * 2;
      camera.lookAt(0, 1.5, 0);

      renderer.render(scene, camera);
    }

    // Start animation
    requestAnimationFrame(animate);

    // Ensure the canvas can receive focus to capture keyboard after click
    renderer.domElement.setAttribute('tabindex', '0');
    renderer.domElement.addEventListener('click', () => {
      if (!started) onStart();
    }, { passive: true });

  </script>
</body>
</html>