<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Levi Ackerman00</title>
    <description>The latest articles on DEV Community by Levi Ackerman00 (@levi_ackerman00_69cc17b2c).</description>
    <link>https://dev.to/levi_ackerman00_69cc17b2c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111764%2F8fdf891f-95d6-4518-b920-ab5d25649751.png</url>
      <title>DEV Community: Levi Ackerman00</title>
      <link>https://dev.to/levi_ackerman00_69cc17b2c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/levi_ackerman00_69cc17b2c"/>
    <language>en</language>
    <item>
      <title>Building Beyond CRUD with Claude and Codex: How we Created an Interactive Digital Museum</title>
      <dc:creator>Levi Ackerman00</dc:creator>
      <pubDate>Sun, 06 Sep 2026 01:30:51 +0000</pubDate>
      <link>https://dev.to/levi_ackerman00_69cc17b2c/building-beyond-crud-with-claude-and-codex-how-i-created-an-interactive-digital-museum-8n8</link>
      <guid>https://dev.to/levi_ackerman00_69cc17b2c/building-beyond-crud-with-claude-and-codex-how-i-created-an-interactive-digital-museum-8n8</guid>
      <description>&lt;p&gt;&lt;strong&gt;What does building with AI look like when your application needs interactive planets, a working 3D interface, scientific content, and cinematic storytelling?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s what I’ve been exploring with &lt;strong&gt;Loupe&lt;/strong&gt;, an interactive digital museum built with the help of Claude and Codex.&lt;/p&gt;

&lt;p&gt;The application brings together exhibits about space, dinosaurs, human evolution, anatomy, jet engines, and Apollo 11’s lunar descent.&lt;/p&gt;

&lt;p&gt;Each exhibit presents a different engineering challenge. A planetary explorer needs camera controls and coordinated viewing modes. A mission narrative needs scroll progression. An engine exhibit needs to make invisible processes understandable.&lt;/p&gt;

&lt;p&gt;This post explains how those experiences work, how the application is structured, and where AI coding agents have been useful throughout development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://loupe-museum.vercel.app/" rel="noopener noreferrer"&gt;Explore Loupe →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6xm9lfhiemzvhcftbi6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6xm9lfhiemzvhcftbi6y.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Loupe’s homepage connects visitors to exhibits with different subjects and interaction models.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The application idea: make curiosity interactive
&lt;/h2&gt;

&lt;p&gt;The starting point was a question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Could a website make exploring a scientific subject feel like using an instrument?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A visitor should be able to select an object, investigate a feature, change the view, and understand what changed.&lt;/p&gt;

&lt;p&gt;In Loupe, that takes several forms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Exhibit&lt;/th&gt;
&lt;th&gt;Visitor experience&lt;/th&gt;
&lt;th&gt;Engineering challenge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Atlas of Worlds&lt;/td&gt;
&lt;td&gt;Explore planets and compare their features&lt;/td&gt;
&lt;td&gt;Textures, camera orientation, viewing modes, and state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Engine Is a River&lt;/td&gt;
&lt;td&gt;Investigate a turbofan and its flow stations&lt;/td&gt;
&lt;td&gt;Model loading, particles, shaders, and linked explanations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thirteen Minutes&lt;/td&gt;
&lt;td&gt;Follow Apollo 11’s powered descent&lt;/td&gt;
&lt;td&gt;Scroll progression, scene state, and narrative timing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Becoming Human&lt;/td&gt;
&lt;td&gt;Explore human evolution through a cinematic journey&lt;/td&gt;
&lt;td&gt;Content sequencing and visual continuity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dinosaurs, Reconsidered&lt;/td&gt;
&lt;td&gt;Inspect specimens and examine evidence&lt;/td&gt;
&lt;td&gt;Asset preparation, annotations, and model switching&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This shaped an important product decision: &lt;strong&gt;the interaction should fit the subject.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The museum needs a coherent identity, but a planet and a lunar descent should not behave like the same page with different assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The stack behind Loupe
&lt;/h2&gt;

&lt;p&gt;The core stack is familiar to many React developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js and TypeScript&lt;/strong&gt; for routing, application structure, and typed contracts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; for the interface and component composition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three.js and React Three Fiber&lt;/strong&gt; for browser-based 3D.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drei&lt;/strong&gt; for model loading, orbit controls, and scene utilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GSAP&lt;/strong&gt; for animation tooling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zustand&lt;/strong&gt; for shared exhibit state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vitest and Playwright&lt;/strong&gt; for automated verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; for hosting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part is how these pieces divide responsibility.&lt;/p&gt;

&lt;p&gt;The interface deals with choices: selecting a world, opening a panel, or changing a mode.&lt;/p&gt;

&lt;p&gt;The renderer deals with continuous changes: camera movement, object rotation, and particle animation.&lt;/p&gt;

&lt;p&gt;Keeping those responsibilities clear helps both performance and maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Structuring an exhibit as an application
&lt;/h2&gt;

&lt;p&gt;An interactive exhibit quickly becomes more complicated than a component containing a model.&lt;/p&gt;

&lt;p&gt;It has content, controls, visual modes, source information, loading behaviour, and state transitions.&lt;/p&gt;

&lt;p&gt;For Atlas of Worlds, the repository separates those concerns into three broad layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;content/space/
  atlas.ts
  atlas-assets.ts
  atlas-asset-licenses.json

lib/space/
  atlas-schema.ts
  atlas-store.ts
  atlas-scale.ts
  world-focus.ts

components/space/
  AtlasExperience.tsx
  AtlasStage.tsx
  AtlasCanvas.tsx
  AtlasFallback.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt; describes the worlds, assets, features, and explanations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic&lt;/strong&gt; handles calculations, state transitions, comparison policies, and focus behaviour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Components&lt;/strong&gt; turn those decisions into the visible experience.&lt;/p&gt;

&lt;p&gt;From an application perspective, this means changing an explanation does not require editing camera code.&lt;/p&gt;

&lt;p&gt;From a development perspective, it gives both humans and coding agents smaller, clearer problems to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How Atlas renders an interactive planet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flu1pju8lu5o13xh25off.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flu1pju8lu5o13xh25off.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The globe, controls, feature selection, and field guide respond to the same exhibit state.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Atlas combines procedural geometry, surface textures, materials, and selected model assets.&lt;/p&gt;

&lt;p&gt;For a roughly spherical world, a sphere provides the basic shape. Much of the visible detail comes from the texture and its treatment.&lt;/p&gt;

&lt;p&gt;Additional modes introduce different layers or representations.&lt;/p&gt;

&lt;p&gt;This makes the relationship between visual quality and asset complexity more interesting than “more polygons look better.”&lt;/p&gt;

&lt;p&gt;A convincing result also depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Correct texture mapping.&lt;/li&gt;
&lt;li&gt;Appropriate lighting.&lt;/li&gt;
&lt;li&gt;Camera framing.&lt;/li&gt;
&lt;li&gt;Surface material settings.&lt;/li&gt;
&lt;li&gt;The scale of the object in the viewport.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The renderer caps its device pixel ratio, which limits rendering cost on high-density displays.&lt;/p&gt;

&lt;p&gt;That choice matters because a canvas has to shade every rendered pixel. A visually small change in resolution can produce a substantial change in GPU workload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The aim is to spend rendering effort where the visitor can perceive it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. One selection can change the whole interface
&lt;/h2&gt;

&lt;p&gt;When someone selects a new planet, the application needs to update more than the globe.&lt;/p&gt;

&lt;p&gt;The selection can affect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The available viewing modes.&lt;/li&gt;
&lt;li&gt;The active feature.&lt;/li&gt;
&lt;li&gt;The field guide.&lt;/li&gt;
&lt;li&gt;Lighting defaults.&lt;/li&gt;
&lt;li&gt;The comparison world.&lt;/li&gt;
&lt;li&gt;Camera orientation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atlas coordinates those changes through a Zustand store.&lt;/p&gt;

&lt;p&gt;For example, changing worlds resets the viewing mode to the new world’s default, clears the selected hotspot, and issues a camera reset.&lt;/p&gt;

&lt;p&gt;That prevents inconsistent states, such as displaying a feature from one planet while rendering another.&lt;/p&gt;

&lt;p&gt;The camera commands also carry a sequence number. That allows repeated actions—such as pressing Reset twice—to remain distinct commands.&lt;/p&gt;

&lt;p&gt;These details are easy to overlook in an initial prototype. They become important once people start exploring freely.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Keeping animation out of React’s update cycle
&lt;/h2&gt;

&lt;p&gt;Continuous animation should not require a React state update for every frame.&lt;/p&gt;

&lt;p&gt;The project uses references and React Three Fiber’s &lt;code&gt;useFrame&lt;/code&gt; to update scene objects directly.&lt;/p&gt;

&lt;p&gt;A simplified example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mesh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mesh&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useFrame&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;motionEnabled&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;mesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;mesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rotationSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, React controls whether motion is enabled. The render loop updates the rotation.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;delta&lt;/code&gt; makes movement depend on elapsed time, which helps keep the intended speed consistent across different frame rates.&lt;/p&gt;

&lt;p&gt;Camera transitions follow a similar pattern. The interface chooses the destination, and the renderer interpolates toward it.&lt;/p&gt;

&lt;p&gt;The engine exhibit also stops automated camera movement when the visitor begins using the orbit controls.&lt;/p&gt;

&lt;p&gt;That is a small implementation detail with a direct product consequence: &lt;strong&gt;the camera respects the visitor’s input.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Explaining an engine with shaders
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fngb8da37zbxmg7o3ohko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fngb8da37zbxmg7o3ohko.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Selecting a flow station connects a physical location on the engine to its explanation and operating values.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The engine exhibit combines a loaded GLB model with procedural visualisations.&lt;/p&gt;

&lt;p&gt;Its airflow particles have attributes such as phase, angle, radius, and speed. A shader uses those attributes, time, and engine parameters to calculate their positions and colours.&lt;/p&gt;

&lt;p&gt;This avoids sending thousands of individual particle-position updates through React.&lt;/p&gt;

&lt;p&gt;The implementation also adjusts particle counts based on the canvas width. The bypass stream, for example, uses more particles in the wider layout than in the narrower one.&lt;/p&gt;

&lt;p&gt;The visitor still sees the flow relationship, while the renderer performs less work on a smaller display.&lt;/p&gt;

&lt;p&gt;There is also a content responsibility here: the visualisation is an explanatory model. Its appearance should not imply that it is live telemetry or a computational fluid dynamics simulation.&lt;/p&gt;

&lt;p&gt;Engineering the visual and explaining its limits are both part of building the feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Turning scrolling into a narrative control
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvzp1pyc9057ou374woa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvzp1pyc9057ou374woa.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thirteen Minutes introduces the mission before the visitor enters the descent narrative.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For Apollo 11, the central interaction is progression through a sequence of events.&lt;/p&gt;

&lt;p&gt;The architecture separates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interpreting scroll position.&lt;/li&gt;
&lt;li&gt;Identifying the active narrative section.&lt;/li&gt;
&lt;li&gt;Resolving scene state.&lt;/li&gt;
&lt;li&gt;Moving the camera.&lt;/li&gt;
&lt;li&gt;Updating the mission interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One small utility determines which section contains the viewport’s centre:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;centeredBeatIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;viewportHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewportHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because it receives measurements and returns an index, this function can be tested without mounting a 3D scene.&lt;/p&gt;

&lt;p&gt;That separation also helps debugging. An incorrect camera view may originate in scroll interpretation, scene progression, or camera interpolation. Those are different problems, even when the visitor experiences them as “the animation feels wrong.”&lt;/p&gt;

&lt;h2&gt;
  
  
  9. The difficult part: everything around the first render
&lt;/h2&gt;

&lt;p&gt;The first working model is a milestone. Making it work well inside the application takes more iteration.&lt;/p&gt;

&lt;p&gt;During development, the dinosaur exhibit exposed issues including missing skeletons, incorrect model presentations, and delays when switching specimens.&lt;/p&gt;

&lt;p&gt;One particularly noticeable behaviour was a still image appearing before the interactive model.&lt;/p&gt;

&lt;p&gt;Displaying something quickly can be useful, but the transition can also make the experience feel as though it loads twice.&lt;/p&gt;

&lt;p&gt;That taught me to evaluate performance through the complete interaction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens between clicking a specimen and being able to inspect it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Download time matters. So do decoding, GPU preparation, camera framing, and the visual handoff.&lt;/p&gt;

&lt;p&gt;Preloading can help, but loading everything upfront introduces bandwidth and memory costs. It needs to be applied selectively.&lt;/p&gt;

&lt;p&gt;I also would not claim a Lighthouse score or universal frame rate without measurements across representative devices. The application’s behaviour is the evidence that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Where Claude and Codex help
&lt;/h2&gt;

&lt;p&gt;The strongest benefit of Claude and Codex has been their ability to help work through connected problems across the repository.&lt;/p&gt;

&lt;p&gt;A rendering bug may involve several files: the loader, scene component, state store, and fallback boundary.&lt;/p&gt;

&lt;p&gt;Agents can help inspect that path, propose an implementation, make coordinated changes, and support verification.&lt;/p&gt;

&lt;p&gt;The prompts become more useful when they describe observable behaviour and constraints.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Selecting a feature should bring it into view while preserving manual orbit controls. Inspect the coordinate conversion and focus behaviour, explain the cause of the current failure, and implement a focused fix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That gives the agent a specific outcome to pursue.&lt;/p&gt;

&lt;p&gt;The development loop becomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define what the visitor should experience.&lt;/li&gt;
&lt;li&gt;Give the agent the relevant context.&lt;/li&gt;
&lt;li&gt;Implement a bounded change.&lt;/li&gt;
&lt;li&gt;Inspect the application.&lt;/li&gt;
&lt;li&gt;Report specific failures.&lt;/li&gt;
&lt;li&gt;Refine and verify.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The human contribution remains substantial: choosing the experience, judging the result, checking the scientific representation, and deciding what deserves further work.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Making quality requirements explicit
&lt;/h2&gt;

&lt;p&gt;Loupe keeps exhibit standards in the repository.&lt;/p&gt;

&lt;p&gt;They ask questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What should the visitor understand?&lt;/li&gt;
&lt;li&gt;Does each control have meaningful behaviour?&lt;/li&gt;
&lt;li&gt;Are sources and reconstruction limits visible?&lt;/li&gt;
&lt;li&gt;What happens on mobile?&lt;/li&gt;
&lt;li&gt;How does the experience behave when an asset fails?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes expectations available across development sessions.&lt;/p&gt;

&lt;p&gt;The project also includes tests for state, calculations, content, and browser interactions. But automated checks are only one part of verification.&lt;/p&gt;

&lt;p&gt;A test can confirm that a focus calculation returns the expected orientation. Visual inspection still needs to confirm that the selected feature is understandable on screen.&lt;/p&gt;

&lt;p&gt;The same applies to accessibility and fallbacks. Atlas checks WebGL availability and includes an error boundary. The Apollo experience considers reduced motion, reduced data, and viewport proximity.&lt;/p&gt;

&lt;p&gt;These behaviours help the application remain useful outside the ideal desktop scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. What this project showed me about AI-assisted development
&lt;/h2&gt;

&lt;p&gt;Building Loupe has made me more willing to attempt projects that cross several technical disciplines.&lt;/p&gt;

&lt;p&gt;Claude and Codex help with the implementation capacity needed to explore those ideas: components, state, graphics, asset integration, debugging, and tests.&lt;/p&gt;

&lt;p&gt;The application improves through the combination of that capacity and deliberate product decisions.&lt;/p&gt;

&lt;p&gt;What should be interactive? What needs explanation? Where does motion help? Which details justify their performance cost?&lt;/p&gt;

&lt;p&gt;Those decisions shape the result as much as the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://loupe-museum.vercel.app/" rel="noopener noreferrer"&gt;Try Loupe →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you explore it, I’d especially appreciate feedback on model loading, camera controls, and how the exhibits behave on your device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What application have AI coding tools made you willing to build?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Suggested DEV tags:&lt;/strong&gt; &lt;code&gt;ai&lt;/code&gt;, &lt;code&gt;webdev&lt;/code&gt;, &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;showdev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Publishing note: upload the four screenshots to DEV and replace their local paths with the uploaded image URLs.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
