TripoSplatWebGPU / e2e-web.html
Yosun's picture
Deploy TripoSplat WebGPU app (production)
9a77add verified
Raw
History Blame Contribute Delete
28.1 kB
<!doctype html>
<html lang="en" data-ui-theme="blueprint">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light" />
<meta name="theme-color" content="#f4f9fc" />
<meta name="application-version" content="0.1.0-preview.23" />
<meta name="application-revision" content="1481bd9c11a3" />
<meta name="application-environment" content="production" />
<meta name="application-build-time" content="2026-08-05T04:36:45.213Z" />
<meta name="description" content="Generate a Gaussian splat locally with WebGPU or through the free MutualGPU exchange." />
<meta property="og:type" content="website" />
<meta property="og:title" content="TripoSplat WebRunner · Local WebGPU + MutualGPU" />
<meta property="og:description" content="One image-to-3D runner: use this device or submit to MutualGPU." />
<meta property="og:image" content="https://triposplat-webgpu.vercel.app/corgi.ceo_image_header.social.jpg" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="TripoSplat WebRunner · Local WebGPU + MutualGPU" />
<meta name="twitter:description" content="One image-to-3D runner: use this device or submit to MutualGPU." />
<meta name="twitter:image" content="https://triposplat-webgpu.vercel.app/corgi.ceo_image_header.social.jpg" />
<title>TripoSplat WebRunner · Local + MutualGPU</title>
<link rel="canonical" href="/e2e-web" />
<script type="module" crossorigin src="/assets/e2eWeb-B3SkQG-G.js"></script>
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
<link rel="modulepreload" crossorigin href="/assets/preload-helper-BXl3LOEh.js">
<link rel="stylesheet" crossorigin href="/assets/e2e-web-Du4d9U9-.css">
</head>
<body>
<a class="skip-link" href="#main-content">Skip to generator</a>
<div class="ambient ambient-one" aria-hidden="true"></div>
<div class="ambient ambient-two" aria-hidden="true"></div>
<nav class="topbar" aria-label="Primary navigation">
<a class="brand" href="/e2e-web" aria-label="TripoSplat WebRunner image to 3D">
<span class="brand-mark" aria-hidden="true"><span></span></span><span>TRIPOSPLAT <b>WEBGPU</b></span>
</a>
<div class="topbar-meta">
<button id="ui-theme-toggle" class="ui-theme-toggle" type="button" aria-pressed="true" aria-label="Switch to dark interface">Dark UI <span aria-hidden="true"></span></button>
<span class="app-version" title="Build 2026-08-05T04:36:45.213Z · revision 1481bd9c11a3 · environment production"><b>WEB RUNNER</b> v0.1.0-preview.23 · 1481bd9c11a3 · production</span>
<span class="capability" id="platform-badge"><i></i><span>Checking platform</span></span>
</div>
</nav>
<main id="main-content" class="app-shell web-app">
<header class="web-hero">
<div class="eyebrow"><span>Image to 3D Model. </span></div>
<h1><em>Local when you can. Mutual when you can’t.</em></h1>
<p>Run the full TripoSplat model on this device when its WebGPU and storage qualify,<br />
or send the same job to a free MutualGPU provider from this page.<br />
Qualified devices can also opt in to help process another person’s TripoSplat job.</p>
<div class="hero-actions"><a class="github-link" href="#source-heading">Try it out <span aria-hidden="true"></span></a><a class="hero-text-link" href="/learn">Learn how it works <span aria-hidden="true"></span></a><a class="hero-text-link" href="#browser-experiment">Why this matters <span aria-hidden="true"></span></a></div>
</header>
<section class="compatibility-panel" aria-labelledby="compatibility-heading">
<div><span class="section-index">SYSTEM CHECK</span><h2 id="compatibility-heading">Preparing your browser</h2></div>
<ul id="compatibility-list" aria-live="polite"><li>Checking WebGPU and storage…</li></ul>
</section>
<div class="web-workspace">
<section class="web-controls panel" aria-labelledby="source-heading">
<div class="panel-heading"><div><span class="section-index">STEP 1 / IMAGE + SETTINGS</span><h2 id="source-heading">Choose an image and generation settings</h2></div><span class="local-badge">YOUR INPUT</span></div>
<p class="panel-copy">Choose a source image, then set the sampling values that control the generated scene. These settings apply whether the job runs locally or through MutualGPU.</p>
<input id="image-file" type="file" accept="image/png,image/webp,image/jpeg,image/avif" hidden />
<button id="choose-file" class="file-picker" type="button"><span>Choose image from your computer</span><b>Browse</b></button>
<label class="url-label" for="image-url"><span>Or start from an image URL</span><small id="image-url-help">The image host must allow browser CORS access.</small></label>
<div class="url-row"><input id="image-url" type="url" inputmode="url" placeholder="https://example.com/object.png" autocomplete="url" aria-describedby="image-url-help image-url-error" /><button id="load-image-url" type="button">Use URL</button></div>
<div id="image-url-error" class="image-url-error" role="alert" hidden></div>
<figure id="image-preview" class="image-preview" hidden>
<img id="image-preview-image" alt="Selected source image preview" />
<figcaption>Loaded source image</figcaption>
</figure>
<div id="image-summary" class="image-summary" data-state="empty" aria-live="polite">No image selected yet.</div>
<section class="image-preparation" aria-labelledby="image-preparation-heading">
<div><span class="section-index">OPTIONAL / LOCAL PROCESSING</span><h3 id="image-preparation-heading">Prepare a photo for TripoSplat</h3></div>
<p>Opaque photos start background removal and the official subject crop automatically in this browser. Your pixels stay on this device; use the button to process again.</p>
<button id="prepare-image" type="button" disabled><span>Process image locally</span><b aria-hidden="true"></b></button>
<p id="image-preparation-status" class="image-preparation-status" data-state="idle" role="status" aria-live="polite">Choose an image to enable local processing.</p>
</section>
<button id="drop-zone" class="drop-zone" type="button">Or drag an image here</button>
<details id="generation-settings" class="model-advanced generation-settings-panel" open><summary>Generation settings</summary><p>These sampling values apply to both local generation and MutualGPU requests. Keep the defaults for the qualified quality profile.</p><div class="generation-settings-grid"><label for="generation-steps"><span>Quality steps</span><small>4 is a fast draft; 20 is the qualified quality profile.</small><select id="generation-steps"><option value="4">4 · Draft</option><option value="20" selected>20 · Quality</option></select></label><label for="generation-guidance"><span>CFG scale</span><small>Classifier-free guidance strength. Default: 3.</small><input id="generation-guidance" type="number" inputmode="decimal" min="0" max="50" step="0.1" value="3" /></label><label for="generation-seed"><span>Random seed</span><small>Reuse a seed for a reproducible sampling request.</small><span class="generation-seed-control"><input id="generation-seed" type="number" inputmode="numeric" min="0" max="4294967295" step="1" value="42" /><button id="randomize-generation-seed" type="button">Randomize</button></span></label></div></details>
<a class="continue-to-engine" href="#model-heading">Continue to browser engine <span aria-hidden="true"></span></a>
</section>
<section class="preview-panel-web panel" aria-labelledby="scene-heading">
<div class="panel-heading"><div><span class="section-index">STEP 3 / RESULT</span><h2 id="scene-heading">Your spatial scene</h2></div><span id="viewer-state" class="viewer-state">Waiting</span></div>
<label class="preview-renderer" for="preview-renderer"><span>Preview renderer</span><select id="preview-renderer"><option value="gaussian-splats-3d" selected>Gaussian Splats 3D · default</option><option value="aholo">Aholo · alternative</option></select><small>Switch renderers to compare the completed scene without regenerating it.</small></label>
<div id="web-preview-root"></div>
<p id="preview-run-state" class="preview-run-state" data-state="waiting" role="status" aria-live="polite">A completed scene will appear here without leaving this page.</p>
<div class="download-row"><button id="download-ply" type="button" disabled>Download PLY</button><button id="download-splat" type="button" disabled>Download .splat</button><button id="download-result-zip" type="button" disabled>Download result ZIP</button></div>
</section>
<section class="model-panel panel" aria-labelledby="model-heading">
<div class="panel-heading"><div><span class="section-index">STEP 2 / EXECUTION</span><h2 id="model-heading">Choose where it runs</h2></div><span id="cache-mode" class="local-badge">CHECKING</span></div>
<p class="panel-copy">Use this device for private, browser-local WebGPU generation when it qualifies, or use MutualGPU without local GPU or storage requirements.</p>
<fieldset class="execution-mode" aria-describedby="execution-mode-help">
<legend>Execution mode</legend>
<label data-execution-card="local"><input id="execution-local" type="radio" name="execution-mode" value="local" checked /><span><strong>Run on this device</strong><small id="local-mode-status">Checking WebGPU, model storage, and desktop requirements…</small></span><b>LOCAL</b></label>
<label data-execution-card="mutualgpu"><input id="execution-mutualgpu" type="radio" name="execution-mode" value="mutualgpu" /><span><span class="execution-mode-title"><img src="/assets/mutual-gput-logo-only-flat-white-BLrUD_A9.png" width="40" height="21" alt="" /><strong>Run on MutualGPU</strong></span><small>Use free community-contributed compute. No local WebGPU or 6.5 GB model cache required.</small></span><b>NO LOCAL GPU REQUIRED</b></label>
</fieldset>
<p id="execution-mode-help" class="execution-mode-help">The result returns to this same viewer. Selecting remote mode sends the selected image to the MutualGPU exchange and assigned provider.</p>
<p class="execution-expectation"><strong>Engineering preview.</strong> A first local run may download about 6.5 GB and generation can take several minutes. MutualGPU wait time depends on network, service, and provider availability. Browser support and output quality vary.</p>
<div class="model-layout"><div id="model-status" class="model-status" aria-live="polite">Checking local model storage and MutualGPU configuration…</div></div>
<details id="local-model-settings" class="model-advanced"><summary>Local model server</summary><label for="model-base"><span>Model CDN directory</span><small>Used only for on-device runs and provider work. Must contain manifest.json and allow CORS.</small><input id="model-base" type="url" inputmode="url" autocomplete="url" spellcheck="false" /></label></details>
<details id="mutualgpu-settings" class="model-advanced"><summary>MutualGPU connection</summary><label for="mutualgpu-api-base"><span>MutualGPU HTTPS API</span><small>Defaults to the public MutualGPU exchange. The requestor origin and result storage must allow this application.</small><input id="mutualgpu-api-base" type="url" inputmode="url" autocomplete="url" spellcheck="false" value="https://mutualgpu.com/" /></label></details>
<button id="generate" class="primary-action" type="button" disabled><span>Choose an image to begin</span><b aria-hidden="true"></b></button>
<div class="run-feedback"><small id="run-stage">STATUS</small><p id="run-status" aria-describedby="run-stage">Checking browser compatibility…</p><span id="run-announcement" class="visually-hidden" role="status" aria-live="polite" aria-atomic="true"></span><div class="progress-track" role="progressbar" aria-label="Generation progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><span id="progress-fill"></span></div></div>
<section id="mutualgpu-capacity" class="mutualgpu-capacity" role="alert" hidden>
<span>NO COMPUTERS AVAILABLE</span>
<strong>No community computer is available for TripoSplat right now.</strong>
<p>MutualGPU is online, but no TripoSplat provider is currently enrolled. Your image was not processed or queued. Try again shortly, or use the Contribute Compute bar below from a qualified WebGPU device.</p>
<button id="retry-mutualgpu" type="button">Check MutualGPU again</button>
</section>
<section id="mutualgpu-task-history" class="mutualgpu-task-history" aria-labelledby="mutualgpu-task-history-heading">
<div class="mutualgpu-task-history-heading"><div><span class="section-index">COOKIE-SCOPED RECOVERY</span><h3 id="mutualgpu-task-history-heading">Previous MutualGPU tasks</h3></div><button id="refresh-mutualgpu-tasks" type="button">Refresh</button></div>
<p id="mutualgpu-task-history-status" role="status" aria-live="polite">Checking this browser’s MutualGPU requestor session…</p>
<ul id="mutualgpu-task-list" aria-label="Tasks associated with this browser’s MutualGPU requestor cookie"></ul>
<small>Only tasks associated with this browser’s anonymous MutualGPU requestor cookie are shown. Result links are requested again when opened because signed downloads expire.</small>
</section>
<section class="generation-flow" aria-labelledby="generation-flow-heading">
<div class="flow-heading"><div><span class="section-index">LOCAL / MUTUALGPU PIPELINE</span><h3 id="generation-flow-heading">Image-to-3D pipeline</h3></div><div class="progress-detail-switch" role="group" aria-label="Progress detail level"><button type="button" data-progress-detail="guided" aria-pressed="true">Guided</button><button type="button" data-progress-detail="technical" aria-pressed="false">Technical</button></div></div>
<p id="progress-detail-description" class="progress-detail-description">Live stages follow this browser for local runs or the assigned provider for MutualGPU runs.</p>
<ol id="generation-flow" class="flow-steps">
<li data-flow-stage="source" data-state="active" aria-current="step"><span class="flow-marker">01</span><div><strong>Source image</strong><span>Inspect, prepare, and securely transfer when remote.</span></div><small>READY</small></li>
<li data-flow-stage="model" data-state="waiting"><span class="flow-marker">02</span><div><strong>Model package</strong><span>Verify the manifest and load model graphs on the executor.</span></div><small>WAITING</small></li>
<li data-flow-stage="conditioning" data-state="waiting"><span class="flow-marker">03</span><div><strong>Conditioning</strong><span>Preprocess → DINOv3 → Flux VAE.</span></div><small>WAITING</small></li>
<li data-flow-stage="sampling" data-state="waiting"><span class="flow-marker">04</span><div><strong>Flow sampler</strong><span>20 official steps · 40 CFG DiT calls.</span></div><small>WAITING</small></li>
<li data-flow-stage="decode" data-state="waiting"><span class="flow-marker">05</span><div><strong>Spatial decode</strong><span>Octree occupancy → Gaussian decoder.</span></div><small>WAITING</small></li>
<li data-flow-stage="preview" data-state="waiting"><span class="flow-marker">06</span><div><strong>Scene handoff</strong><span>Package PLY / .splat, verify, and open the result.</span></div><small>WAITING</small></li>
</ol>
</section>
<section id="benchmark-report" class="benchmark-report" aria-labelledby="benchmark-heading" hidden>
<div class="flow-heading"><div><span class="section-index">RUN REPORT</span><h3 id="benchmark-heading">Copyable benchmark summary</h3></div><button id="copy-benchmark" type="button" disabled>Copy report</button></div>
<p id="benchmark-summary" class="benchmark-summary" role="status" aria-live="polite">Complete a generation to capture its timing and browser environment.</p>
<pre id="benchmark-details" class="benchmark-details" tabindex="0"></pre>
</section>
<div class="secondary-actions"><button id="cancel" type="button" disabled>Cancel current operation</button><button id="clear-cache" type="button">Clear cached model files</button></div>
<section id="diagnostics" class="diagnostics" aria-labelledby="diagnostic-heading" hidden>
<div class="diagnostic-heading"><div><span class="section-index">FAILURE DIAGNOSIS</span><h3 id="diagnostic-heading">What likely caused this</h3></div></div>
<p id="diagnostic-message"></p>
<div class="diagnostic-guidance"><div><strong>Likely cause</strong><p id="diagnostic-cause"></p></div><div><strong>What to try</strong><ol id="diagnostic-actions"></ol></div></div>
<div class="diagnostic-recovery"><button id="retry-generation" type="button">Retry generation</button><button id="use-mutualgpu" type="button">Use MutualGPU instead</button></div>
<details class="diagnostic-evidence"><summary>Technical evidence and runtime event trail</summary><div class="diagnostic-evidence-tools"><span id="diagnostic-copy-status" role="status" aria-live="polite">Select any text, or copy the complete technical log.</span><button id="copy-diagnostics" type="button">Copy technical log</button></div><pre id="diagnostic-details" tabindex="0"></pre></details>
</section>
<p class="privacy-note"><strong>Privacy:</strong> local mode keeps image processing and inference on this device. MutualGPU mode uploads the selected image to the exchange and assigned provider. The latest verified MutualGPU result ZIP may be retained in this browser’s private origin storage for crash-safe download recovery; clearing this site’s browser data removes it. Provider mode receives untrusted requestor images and uses the local model cache. TripoSplat model artifacts come from the official <a href="https://huggingface.co/Yosun/TripoSplat-WebGPU/">Hugging Face package</a> unless you choose another server.</p>
</section>
</div>
<button id="contribute-compute" class="community-compute-bar" type="button" aria-controls="provider-panel" aria-expanded="false" hidden>
<img src="/assets/mutual-gput-logo-only-flat-white-BLrUD_A9.png" width="36" height="19" alt="" />
<span><small>COMMUNITY COMPUTE</small><strong>Contribute Compute on MutualGPU</strong></span>
<b>Share your idle GPU · <span id="contribute-compute-action">More info</span> <span aria-hidden="true"></span></b>
</button>
<details id="provider-panel" class="provider-panel" aria-labelledby="provider-heading">
<summary class="provider-summary flow-heading"><span><span class="section-index">OPTIONAL / SHARE YOUR GPU</span><strong id="provider-heading" class="provider-heading">Become a MutualGPU provider</strong></span><span id="provider-state" class="viewer-state">Checking</span></summary>
<p>Qualified Chrome devices can receive one remote requestor’s TripoSplat assignment at a time. Accepted work runs on this browser and can download the same 6.5 GB model cache while sustaining heavy GPU and power use for several minutes. The requestor identity is not disclosed, but every activity line shows the assignment ID, phase, and progress. The provider key stays in this page’s memory and is never saved. Closing the page interrupts the session. Only enable this in an operator-controlled browser.</p>
<section id="provider-machine-guide" class="provider-machine-guide" aria-labelledby="provider-machine-guide-heading">
<div class="provider-machine-guide-heading"><span class="section-index">PREFLIGHT / KEEP THIS DEVICE ONLINE</span><h3 id="provider-machine-guide-heading">Set up this provider machine</h3></div>
<p class="provider-machine-warning"><strong>System sleep, suspend, hibernation, or a sleeping browser tab interrupts the WebGPU provider connection.</strong> The display may turn off, but the operating system and this browser tab must remain active for the entire provider session.</p>
<ul class="provider-machine-checklist">
<li>Connect to external power where possible and use a stable network connection.</li>
<li>Prevent system sleep, suspend, and hibernation while providing. Keep this tab open and exclude this page from browser energy-saving or sleeping-tab features when necessary.</li>
<li>Do not close a laptop lid unless the device is explicitly configured to stay awake while docked or on external power.</li>
<li>A brief sleep can recover if the device resumes before the provider-session timeout. After the timeout, the provider disconnects; restore connectivity and select <strong>Start providing</strong> again.</li>
</ul>
<p class="provider-machine-note">These are manual host settings. This page never changes your operating-system or browser power settings.</p>
<div class="provider-machine-platforms">
<section class="provider-machine-platform" aria-labelledby="provider-machine-macos"><h4 id="provider-machine-macos">macOS</h4><p>Open <strong>System Settings → Battery</strong>, review power-adapter options, and prevent automatic sleep while the display is off. On supported Macs, consider High Power mode for sustained work. Closing a Mac laptop lid normally sleeps it unless it is in a supported docked configuration.</p><a href="https://support.apple.com/en-euro/guide/mac-help/mchle41a6ccd/mac" target="_blank" rel="noreferrer">Apple: sleep and wake settings <span aria-hidden="true"></span></a></section>
<section class="provider-machine-platform" aria-labelledby="provider-machine-windows"><h4 id="provider-machine-windows">Windows</h4><p>Open <strong>Settings → System → Power &amp; battery</strong>. While hosting, set plugged-in sleep and hibernate timeouts to <strong>Never</strong>, choose a high-performance power mode where available, and exclude this page from browser energy-saving or sleeping-tab features.</p><a href="https://support.microsoft.com/en-us/windows/power-settings-in-windows-11-0d6a2b6b-2e87-4611-9980-ac9ea2175734" target="_blank" rel="noreferrer">Microsoft: Windows 11 power settings <span aria-hidden="true"></span></a></section>
<section class="provider-machine-platform" aria-labelledby="provider-machine-linux"><h4 id="provider-machine-linux">Linux</h4><p>Disable automatic suspend while connected to AC power in your desktop environment’s power settings. Exact controls vary by distribution and desktop environment; in GNOME, review <strong>Power → Automatic Suspend</strong> for plugged-in behavior.</p><a href="https://help.gnome.org/users/gnome-help/stable/power-autosuspend.html.en" target="_blank" rel="noreferrer">GNOME: automatic suspend settings <span aria-hidden="true"></span></a></section>
</div>
</section>
<div class="provider-fields">
<label for="provider-key"><span>Provider key</span><small>Issued for one MutualGPU execution unit.</small><input id="provider-key" type="password" autocomplete="off" spellcheck="false" /></label>
<label for="provider-profile"><span>Advertised machine profile</span><small>Choose a profile this device can honestly sustain.</small><select id="provider-profile"><option value="Small:8">Small · 8 GiB</option><option value="Medium:16">Medium · 16 GiB</option><option value="Large:32">Large · 32 GiB</option><option value="ExtraLarge:64">Extra Large · 64 GiB</option></select></label>
</div>
<div class="provider-actions"><button id="start-provider" type="button">Start providing</button><button id="stop-provider" type="button" disabled>Stop</button></div>
<p id="provider-status" class="provider-status" role="status" aria-live="polite">Checking local WebGPU, model, and storage requirements…</p>
<details class="provider-terminal" aria-labelledby="provider-terminal-heading">
<summary class="provider-terminal-heading"><span id="provider-terminal-heading">REMOTE PROVIDER ACTIVITY · LAST 120 EVENTS</span><span class="provider-terminal-toggle" aria-hidden="true"></span></summary>
<div class="provider-terminal-tools"><span id="provider-terminal-copy-status" role="status" aria-live="polite">Select any text, or copy the complete log. New activity never moves your reading position.</span><div class="provider-terminal-actions"><button id="jump-to-provider-terminal-latest" class="provider-terminal-latest" type="button" hidden aria-label="Jump to the latest provider activity" title="Jump to latest activity"><span aria-hidden="true"></span><span>New activity</span></button><button id="copy-provider-terminal" type="button">Copy log</button></div></div>
<pre id="provider-terminal-output" role="log" aria-label="Remote MutualGPU provider activity" aria-live="off" tabindex="0"><span class="provider-terminal-line" data-level="info">Provider is idle. Accepted assignments run on this browser for a MutualGPU requestor; each activity line identifies the remote task.</span></pre>
</details>
</details>
<section id="browser-experiment" class="experiment-panel panel" aria-labelledby="experiment-heading">
<div class="experiment-intro"><span class="section-index">WHY THIS MATTERS</span><h2 id="experiment-heading">A monumental attempt to put CUDA-era 3D generation in reach of more people.</h2></div>
<div class="experiment-copy"><p>TripoSplat started as a CUDA-based 3D generation pipeline. With Codex GPT 5.6 Sol Ultra and GPT 5.6 Sol Max in Kiro, this project is porting that work to WebGPU—replacing the usual requirements for NVIDIA hardware, CUDA, terminal commands, environment setup, and local dependency installation with a browser-native workflow.</p><p>The goal is not a cosmetic port. It is an attempt to make advanced AI 3D generation radically more accessible: for GPUPoor MacBook users, students, independent developers, and anyone without an expensive GPU. When a browser passes the system check, they can generate a 3D asset locally on hardware they already own—no terminal, no installation, and no cloud GPU bill for inference.</p><p>This is still an engineering preview, with compatibility and quality under active qualification. But the direction is clear: keep powerful spatial-generation tools inspectable, local, and available to more builders.</p><a class="github-link" href="https://github.com/ai3d-dev/TripoSplatWebGPU" target="_blank" rel="noreferrer">Read the source, benchmarks, and open issues on GitHub <span aria-hidden="true"></span></a></div>
</section>
</main>
<footer><span>TRIPOSPLAT WEBGPU · ENGINEERING PREVIEW</span><a href="#source-heading">Try it out</a><a href="https://github.com/ai3d-dev/TripoSplatWebGPU" target="_blank" rel="noreferrer">View source on GitHub <span aria-hidden="true"></span></a><a href="https://www.producthunt.com/products/triposplat-webgpu?embed=true&amp;utm_source=badge-featured&amp;utm_medium=badge&amp;utm_campaign=badge-triposplat-webgpu" target="_blank" rel="noopener noreferrer"><img alt="TripoSplat WebGPU - Image to 3D Model: Offline. Local. Portable. | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1198682&amp;theme=light&amp;t=1784320164461"></a><a href="/e2e-lab.html">Qualification lab</a><a href="/sharp-lab.html">Legacy SHARP lab</a></footer>
</body>
</html>