Filter
Exclude
Time range
-
Near
Reverie 静的ポートレートをインタラクティブな3D体験に拡張するツール Project Overview ## 概要 静的ポートレート画像をインタラクティブな3D体験に拡張する単一HTMLファイルツール。 AMICRE Witnessシリーズ("subtle revolution in digital identity")の哲学に基づく。 ## 技術スタック - Three.js 0.169 WebGL - EffectComposer(UnrealBloom / BokehPass / FilmPass / ShaderPass) - Custom ShaderMaterial(GLSL vertex fragment) - Canvas 2D(パーティクルオーバーレイ) ## 主要機能 - 画像アップロード → PlaneGeometryにテクスチャ適用、アスペクト自動補正 - カスタムシェーダー:Fresnel rim / subsurface warmth / flow ripple(髪エッジ) - 視線アニメーション:約4秒周期でUVシフト、マウスに15%追従 - マウス視差:カメラ微回転 二色光源(cyan/magenta)追従 - ポストプロセス:Bloom → DoF → FilmGrain → ChromaticAberration - Y2K MODE:彩度低下・シャドウリフト・ハレーション(トグル) - GLITCH MODE:帯域ティアリング・スキャンラインノイズ(トグル) - パーティクル:ambient float クリックバースト ## UI - フォント:Courier New、白ベース(cyan/magentaはglow装飾のみ) - CSSスキャンライン、ローディング画面付き - トグルボタン3種 画像アップロード ## ファイル構成 - 単一HTML(全コードインライン) - 外部依存:Three.js CDN(importmap)のみ ## サウンドコンセプト 432Hz sine / CRT hum / glitch stutter / reversed breath Genre: dark ambient / glitch / hauntology(Grouper × Arca × early Burial)
5
1,176
Chungus retweeted
importmap is awesome!
1
17
1,793
Replying to @andrew_dizenzo
It’s using Three.js (from jsDelivr). Also importmap / ES modules, DOM APIs like document.getElementById, classList, innerHTML, textContent, CSS/layout APIs, window.innerWidth, innerHeight, devicePixelRatio etc...
1
1
11
2,336
Here prompt I've used: Build a Wipeout-style anti-gravity racing prototype as a single self-contained index.html file. STACK & CONSTRAINTS - Three.js loaded from a CDN (importmap, no build step). Plain JS, no frameworks. - Everything in one file. No localStorage or any browser storage — keep all state in memory. - Fixed-timestep physics loop (e.g. 60Hz accumulator) decoupled from the render loop so handling feels identical at any frame rate. - Put ALL tunable physics constants (thrust, max speed, drag, turn rate, bank angle, hover height, brake force, camera lag/FOV) in a single CONFIG object at the top of the file. Never hardcode these inline. BUILD IN PHASES. Do not move to the next phase until the current one visibly works. After each phase, briefly tell me what to look for on screen. PHASE 1 — Scene & loop Three.js scene, perspective camera, requestAnimationFrame loop, flat ground plane, ambient directional light, and close-pulled fog with a gradient/dark sky. Handle window resize. Confirm with a placeholder ship mesh visible on the plane. PHASE 2 — Ship & arcade physics (spend the most effort here) Low-poly wedge ship. Implement: - Forward thrust with velocity cap and exponential drag (ship coasts, has weight). - Speed-scaled yaw steering. - Visual banking: roll the mesh into turns. - Air-brakes: separate left/right brake keys that bleed speed on one side to tighten cornering (this is THE Wipeout control — implement it). - Hover: raycast down to the surface and spring the ship to a hover height so it follows terrain. Tune entirely on the flat plane. The ship must feel floaty-but-controllable BEFORE any track exists. Controls: arrows/WASD to thrust steer, Q/E or comma/period for left/right air-brakes. PHASE 3 — Track Define the track as a CatmullRomCurve3 centerline spline with width and per-section banking. Extrude a ribbon mesh with raised side walls. Include elevation changes and at least one hairpin. Use the spline's parametric position as the hover raycast target. PHASE 4 — Collision & progress Constrain the ship to the track using lateral distance from the centerline: soft repulsion near edges, speed-losing bounce off walls. Track lap progress via the spline parameter. PHASE 5 — Camera & sense of speed Chase camera that lags behind the ship, widens FOV and pulls back with speed, with subtle shake near top speed. Add fog density tied to velocity and a speed-streak/vignette effect. Sell speed through camera and post-processing, not raw numbers. PHASE 6 — Game loop & HUD HTML overlay div with speed readout, lap timer, and lap counter. Checkpoint validation so reversing doesn't count laps. Countdown start and a finish state. Start with Phase 1 now. Show me the full index.html after each phase.
3
891
May 13
Ilha is truly buildless, so all you need to get started is an index.html file with a simple importmap. It lacks type hints, of course, but that should be enough to prototype simple things.
2
1
9
1,375
Rails importmap-rails Propshaft has a silent failure mode: a bare import lib/foo with no matching pin in importmap.rb just 404s. No bundler to save you. The controller never registers — UI silently breaks
2
40
I built csspin-rails — like importmap-rails, but for CSS. Pin CSS packages from npm, vendor them into vendor/assets/stylesheets, and use them. No Node.js needed. Not sure if I’m the only one who needed this 😄 Feedback welcome 👇 github.com/elalemanyo/csspin…
8
1,177
Source code for the music visualiser: <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Enhanced Electric Wave Visualizer</title> <script src="cdn.tailwindcss.com"></script> <style> body { margin: 0; overflow: hidden; background-color: #020204; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; color: #ffffff; } .glass-panel { background: rgba(15, 15, 20, 0.45); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255,255,255,0.02); } .glass-btn { background: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.08); color: #ffffff; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); display: flex; align-items: center; justify-content: center; } .glass-btn:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.2); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0,0,0,0.3); } .glass-btn:active { transform: translateY(0); background: rgba(255, 255, 255, 0.05); } input[type=range] { -webkit-appearance: none; background: rgba(255, 255, 255, 0.1); height: 3px; border-radius: 2px; outline: none; transition: background 0.3s ease; } input[type=range]:hover { background: rgba(255, 255, 255, 0.2); } input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 10px; height: 10px; border-radius: 50%; background: #fff; cursor: pointer; box-shadow: 0 0 10px rgba(255,255,255,0.8); transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1); } input[type=range]::-webkit-slider-thumb:hover { transform: scale(1.4); } input[type="file"] { display: none; } #canvas-container { position: absolute; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 0; } #drop-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(10px); z-index: 100; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; border: 4px dashed rgba(255,255,255,0.2); margin: 10px; border-radius: 20px; } #drop-overlay.active { opacity: 1; } .marquee-container { overflow: hidden; white-space: nowrap; mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); -webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); } .marquee { display: inline-block; animation: marquee 10s linear infinite; } @keyframes marquee { 0% { transform: translateX(100%); } 100% { transform: translateX(-100%); } } </style> <script type="importmap"> { "imports": { "three": "cdn.jsdelivr.net/npm/three@0…", "three/addons/": "cdn.jsdelivr.net/npm/three@0…" } } </script> <div id="canvas-container"></div> <div id="drop-overlay"> <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="mb-4 text-white/70"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="17 8 12 3 7 8"></polyline> <line x1="12" y1="3" x2="12" y2="15"></line> </svg> <h2 class="text-2xl font-light tracking-wider">Drop Audio File Here</h2> </div> <div class="fixed bottom-4 left-1/2 -translate-x-1/2 flex flex-col p-2.5 rounded-xl glass-panel z-50 w-[85%] max-w-[240px] gap-2"> <div class="flex items-center gap-2 w-full"> <span id="currentTime" class="text-[9px] text-white/50 font-mono w-7 text-right">0:00</span> <input type="range" id="progressSlider" value="0" min="0" max="100" step="0.1" class="flex-1 w-full cursor-pointer"> <span id="totalTime" class="text-[9px] text-white/50 font-mono w-7 text-left">0:00</span> </div> <div class="flex items-center justify-center gap-3"> <label class="glass-btn w-7 h-7 rounded-full cursor-pointer" title="Upload Audio"> <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> <input type="file" id="fileInput" accept="audio/*"> </label> <button id="playPauseBtn" class="glass-btn w-9 h-9 rounded-full mx-1" title="Play/Pause"> <svg id="playIcon" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" style="margin-left: 2px;"><polygon points="5 3 19 12 5 21 5 3"/></svg> <svg id="pauseIcon" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="hidden"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg> </button> <button id="stopBtn" class="glass-btn w-7 h-7 rounded-full" title="Stop"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/></svg> </button> </div> </div> <script type="module"> import * as THREE from 'three'; import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; let audioCtx, analyser, source; let isPlaying = false; let isDraggingSlider = false; let bassIntensity = 0; let targetBloom = 2.2; const audio = new Audio(); audio.crossOrigin = "anonymous"; const progressSlider = document.getElementById('progressSlider'); const currentTimeEl = document.getElementById('currentTime'); const totalTimeEl = document.getElementById('totalTime'); const playIcon = document.getElementById('playIcon'); const pauseIcon = document.getElementById('pauseIcon'); const formatTime = (timeInSeconds) => { if (isNaN(timeInSeconds)) return "0:00"; const m = Math.floor(timeInSeconds / 60); const s = Math.floor(timeInSeconds % 60); return `${m}:${s < 10 ? '0' : ''}${s}`; }; const dataArray = new Uint8Array(256); const audioTexture = new THREE.DataTexture(dataArray, 256, 1, THREE.RedFormat, THREE.UnsignedByteType); const initAudio = () => { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioCtx.createAnalyser(); analyser.fftSize = 512; analyser.smoothingTimeConstant = 0.85; source = audioCtx.createMediaElementSource(audio); source.connect(analyser); analyser.connect(audioCtx.destination); } if (audioCtx.state === 'suspended') { audioCtx.resume(); } }; const loadAudioFile = (file) => { initAudio(); const objectUrl = URL.createObjectURL(file); audio.src = objectUrl; playAudio(); }; const playAudio = () => { initAudio(); if (audio.src) { audio.play(); isPlaying = true; playIcon.classList.add('hidden'); pauseIcon.classList.remove('hidden'); } }; const pauseAudio = () => { if (audio.src) { audio.pause(); isPlaying = false; playIcon.classList.remove('hidden'); pauseIcon.classList.add('hidden'); } }; const stopAudio = () => { if (audio.src) { audio.pause(); audio.currentTime = 0; isPlaying = false; playIcon.classList.remove('hidden'); pauseIcon.classList.add('hidden'); dataArray.fill(0); audioTexture.image.data.set(dataArray); audioTexture.needsUpdate = true; progressSlider.value = 0; currentTimeEl.textContent = "0:00"; } }; document.getElementById('fileInput').addEventListener('change', function(e) { if (this.files.length > 0) loadAudioFile(this.files[0]); }); document.getElementById('playPauseBtn').addEventListener('click', () => { isPlaying ? pauseAudio() : playAudio(); }); document.getElementById('stopBtn').addEventListener('click', stopAudio); const dropOverlay = document.getElementById('drop-overlay'); ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { window.addEventListener(eventName, preventDefaults, false); }); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } window.addEventListener('dragenter', () => dropOverlay.classList.add('active')); window.addEventListener('dragleave', (e) => { if (e.relatedTarget === null) dropOverlay.classList.remove('active'); }); window.addEventListener('drop', (e) => { dropOverlay.classList.remove('active'); let dt = e.dataTransfer; let files = dt.files; if (files.length && files[0].type.startsWith('audio/')) { loadAudioFile(files[0]); } }); audio.addEventListener('timeupdate', () => { if (audio.duration && !isDraggingSlider) { progressSlider.value = (audio.currentTime / audio.duration) * 100; currentTimeEl.textContent = formatTime(audio.currentTime); } }); audio.addEventListener('loadedmetadata', () => { totalTimeEl.textContent = formatTime(audio.duration); }); audio.addEventListener('ended', stopAudio); progressSlider.addEventListener('input', (e) => { isDraggingSlider = true; if (audio.duration) { currentTimeEl.textContent = formatTime((e.target.value / 100) * audio.duration); } }); progressSlider.addEventListener('change', (e) => { if (audio.duration) { audio.currentTime = (e.target.value / 100) * audio.duration; } isDraggingSlider = false; }); const container = document.getElementById('canvas-container'); const scene = new THREE.Scene(); scene.fog = new THREE.FogExp2(0x020204, 0.03); const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100); camera.position.set(0, 0, 12); let targetCameraX = 0; let targetCameraY = 0; const renderer = new THREE.WebGLRenderer({ antialias: false, powerPreference: "high-performance" }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.setClearColor(0x020204); container.appendChild(renderer.domElement); const renderScene = new RenderPass(scene, camera); const bloomPass = new UnrealBloomPass( new THREE.Vector2(window.innerWidth, window.innerHeight), 1.8, 1.2, 0.05 ); const composer = new EffectComposer(renderer); composer.addPass(renderScene); composer.addPass(bloomPass); const particleCount = 800; const pGeometry = new THREE.BufferGeometry(); const pPositions = new Float32Array(particleCount * 3); const pSizes = new Float32Array(particleCount); for(let i=0; i < particleCount; i ) { pPositions[i*3] = (Math.random() - 0.5) * 40; pPositions[i*3 1] = (Math.random() - 0.5) * 20; pPositions[i*3 2] = (Math.random() - 0.5) * 30 - 5; pSizes[i] = Math.random(); } pGeometry.setAttribute('position', new THREE.BufferAttribute(pPositions, 3)); pGeometry.setAttribute('aSize', new THREE.BufferAttribute(pSizes, 1)); const pMaterial = new THREE.ShaderMaterial({ uniforms: { uTime: { value: 0 }, uBass: { value: 0 } }, vertexShader: ` uniform float uTime; uniform float uBass; attribute float aSize; varying float vAlpha; varying vec3 vPos; void main() { vec3 pos = position; pos.x = sin(uTime * 0.2 pos.y) * 0.5; pos.y = cos(uTime * 0.15 pos.x) * 0.5; vPos = pos; vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0); gl_PointSize = aSize * (15.0 uBass * 40.0) * (1.0 / -mvPosition.z); vAlpha = aSize * 0.6 (uBass * 0.6); gl_Position = projectionMatrix * mvPosition; } `, fragmentShader: ` varying float vAlpha; varying vec3 vPos; void main() { float dist = length(gl_PointCoord - vec2(0.5)); if (dist > 0.5) discard; float alpha = (0.5 - dist) * 2.0 * vAlpha; vec3 color1 = vec3(0.0, 0.8, 1.0); vec3 color2 = vec3(1.0, 0.2, 0.8); vec3 color = mix(color1, color2, sin(vPos.x * 0.1 vPos.y * 0.2) * 0.5 0.5); gl_FragColor = vec4(color, alpha * 0.4); } `, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false }); const particles = new THREE.Points(pGeometry, pMaterial); scene.add(particles); const vertexShader = ` uniform float uTime; uniform float uOffset; uniform sampler2D uAudioTex; varying vec2 vUv; varying float vAudio; float random (in vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123); } float noise (in vec2 st) { vec2 i = floor(st); vec2 f = fract(st); float a = random(i); float b = random(i vec2(1.0, 0.0)); float c = random(i vec2(0.0, 1.0)); float d = random(i vec2(1.0, 1.0)); vec2 u = f*f*(3.0-2.0*f); return mix(a, b, u.x) (c - a)* u.y * (1.0 - u.x) (d - b) * u.x * u.y; } void main() { vUv = uv; float freqPos = abs(uv.x - 0.5) * 2.0; float audio = texture2D(uAudioTex, vec2(freqPos, 0.0)).r; vAudio = audio; vec3 pos = position; float t = uTime uOffset; float idle = sin(uv.x * 5.0 t * 0.8) * 0.2 noise(vec2(uv.x * 6.0, t * 0.4)) * 0.3 - 0.15; float energy1 = (noise(vec2(uv.x * 15.0, t * 3.0)) - 0.5) * 2.5; float energy2 = (noise(vec2(uv.x * 30.0, t * 6.0)) - 0.5) * 1.5; float sharpNoise = (abs(noise(vec2(uv.x * 45.0, t * 10.0)) - 0.5)) * 1.2; float displacement = idle (energy1 energy2 sharpNoise) * pow(audio, 1.5) * 2.5; float taper = smoothstep(0.0, 0.15, uv.x) * smoothstep(1.0, 0.85, uv.x); pos.y = displacement * taper; float zDisplacement = sin(uv.x * 12.0 t * 1.5) * 1.2 * audio; pos.z = zDisplacement * taper; gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); } `; const fragmentShader = ` uniform float uTime; uniform float uReflection; uniform vec3 uBaseColor; uniform float uThickness; uniform float uBassBoost; varying vec2 vUv; varying float vAudio; void main() { float dynamicThickness = uThickness * (1.0 vAudio * 0.5); float core = 1.0 - abs(vUv.y - 0.5) * (2.0 / dynamicThickness); core = pow(max(core, 0.0), 2.0); float energy = vAudio uBassBoost * 0.5; float glow = core * (1.0 energy * 3.5); vec3 finalColor = mix(uBaseColor, uBaseColor vec3(0.35), core * energy * 0.5); finalColor *= glow * uReflection; float fadeX = smoothstep(0.0, 0.05, vUv.x) * smoothstep(1.0, 0.95, vUv.x); gl_FragColor = vec4(finalColor, core * uReflection * fadeX); } `; const baseUniforms = { uTime: { value: 0 }, uAudioTex: { value: audioTexture }, uReflection: { value: 1.0 }, uOffset: { value: 0.0 }, uBaseColor: { value: new THREE.Color(0xffffff) }, uThickness: { value: 1.0 }, uBassBoost: { value: 0.0 } }; const material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, uniforms: baseUniforms, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide }); const geometry = new THREE.PlaneGeometry(38, 0.1, 700, 1); const allWaves = []; const waveConfigs = [ { offset: 0.0, color: new THREE.Color(0x00d2ff), thickness: 1.3, y: 0.8 }, { offset: 20.4, color: new THREE.Color(0xff007f), thickness: 0.7, y: 1.0 }, { offset: 45.2, color: new THREE.Color(0x7000ff), thickness: 0.35, y: 0.6 }, { offset: 60.5, color: new THREE.Color(0x00ff88), thickness: 0.15, y: 0.9 } ]; waveConfigs.forEach(config => { const mat = material.clone(); mat.uniforms = { ...baseUniforms, uOffset: { value: config.offset }, uBaseColor: { value: config.color }, uThickness: { value: config.thickness }, uReflection: { value: 1.0 } }; const wave = new THREE.Mesh(geometry, mat); wave.position.y = config.y; scene.add(wave); allWaves.push(wave); const refMat = mat.clone(); refMat.uniforms = { ...mat.uniforms, uReflection: { value: 0.35 } }; const refWave = new THREE.Mesh(geometry, refMat); refWave.position.y = -config.y - 0.05; refWave.scale.y = -1.0; scene.add(refWave); allWaves.push(refWave); }); const floorGeo = new THREE.PlaneGeometry(60, 20); const floorMat = new THREE.MeshBasicMaterial({ color: 0x010102, transparent: true, opacity: 0.7, depthWrite: false }); const glassFloor = new THREE.Mesh(floorGeo, floorMat); glassFloor.rotation.x = -Math.PI / 2; glassFloor.position.y = 0; scene.add(glassFloor); document.addEventListener('mousemove', (e) => { const x = (e.clientX / window.innerWidth) * 2 - 1; const y = -(e.clientY / window.innerHeight) * 2 1; targetCameraX = x * 2.0; targetCameraY = y * 1.0; }); const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); const time = clock.getElapsedTime(); camera.position.x = (targetCameraX - camera.position.x) * 0.03; camera.position.y = (targetCameraY - camera.position.y) * 0.03; camera.lookAt(0, 0, 0); if (isPlaying && analyser) { analyser.getByteFrequencyData(dataArray); audioTexture.image.data.set(dataArray); audioTexture.needsUpdate = true; let bassSum = 0; for(let i=0; i<10; i ) bassSum = dataArray[i]; const newBass = (bassSum / 10.0) / 255.0; bassIntensity = (newBass - bassIntensity) * 0.2; targetBloom = 1.8 bassIntensity * 3.5; } else { bassIntensity *= 0.95; targetBloom = 1.8; } bloomPass.strength = (targetBloom - bloomPass.strength) * 0.1; allWaves.forEach(wave => { wave.material.uniforms.uTime.value = time; wave.material.uniforms.uAudioTex.value = audioTexture; wave.material.uniforms.uBassBoost.value = bassIntensity; }); pMaterial.uniforms.uTime.value = time; pMaterial.uniforms.uBass.value = bassIntensity; composer.render(); } window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); composer.setSize(window.innerWidth, window.innerHeight); }); animate(); </script>

9
667
Week 09/10/11 - Understanding importmap-rails, Herb v0.9, and more! hotwireweekly.com/archive/we…

2
7
590
Mar 16
External Import Mapsをビルドツールなしで利用する方法について。 `<script type="importmap">`をDOMで動的に注入することで、外部ファイルとしてImport Mapを管理できる。`document.currentScript.after()`を使い`<script type="importmap">`要素を挿入する。 … "" lea.verou.me/blog/2026/exter…
1
2
1,422
Mar 4
Tokens used : 70,000 - 80,000 Prompt : Create a complete HTML file with a Three.js floating island scene using importmap for Three.js v0.160.0 and OrbitControls. The island should feature a custom shader sky, fog, terrain with mountains (with snow caps), rocks, grass, trees, bushes, flowers, and tall grass patches. Build a detailed village area with multiple houses (with porches, chimneys, windows, doors), a tavern/community hall, a central well with water, a campfire with animated fire particles and log seats, garden plots with plants, a wooden fence, lantern posts, and stone pathways. Add a waterfall with custom GLSL vertex/fragment shaders for flowing water effects, a pool, and mist particle system. Include animated elements: floating island bobbing/rotation, orbiting clouds, 25 floating golden orbs, 25 butterflies with wing flapping, 15 birds with wing animation, and campfire light flickering. Use various materials (grass, dirt, rock, wood, leaves, stone, roof, wall, window) with proper shadow casting/receiving, AmbientLight and DirectionalLight with shadow maps, and responsive resize handling. All animations should run in a requestAnimationFrame loop with clock-based timing.
5
1,016
This is not hyperbole, from when I clicked "run" on the Cerebras playground (and got to the front of the queue), to when GLM 4.7 had finished (including 4 seconds of thinking, plus 7 seconds of outputting the HTML) was 11 seconds. Now I'll admit, this is not heaps of complicated code, but it worked first time out the gate. I made sure to provide it with a valid CDN link to threeJS so that it didn't hallucinate that, but everything else was up to the LLM's own "imagination". Here is the prompt I used: ``` Always respond in English. Create a single, self-contained HTML file that is a love letter to the Winamp visualization era - but reimagined with modern 3D graphics. Use Three.js via importmap: <script type="importmap"> { "imports": { "three": "cdn.jsdelivr.net/npm/three@0…", "three/addons/": "cdn.jsdelivr.net/npm/three@0…" } } </script> No audio input - instead, synthesize your own fake frequency data using layered sine waves, noise, and beat simulation so the visuals pulse and breathe as if reacting to music with dynamics, drops, and builds. Go beyond the usual sphere-with-displacement or bar EQ clichés. Think: impossible geometry, feedback loops, bloom, trails, glitch aesthetics, or something no one has seen before. The visualization should be fullscreen, black background, and absolutely mesmerizing at 60fps. Surprise me. ```

1
2
1,133
🧵 5. “Create a complete 3D kart racing game called **"Turbo Blox Grand Prix"** in a single HTML file using Three.js (via CDN importmap). The game should be fully playable with keyboard controls and feature a polished, arcade-style experience similar to Mario Kart. All code (HTML, CSS, JS) must be in one file. Use Web Audio API to generate all sounds procedurally (no external audio files).” Live site running at - fy2kcgisoyj1.space.minimax.i…
5
997
2/2 月 153日目 1️⃣卒制 各種エラー 手直し モーダルの表示がうまくいかず壁打ちしてたが 自分のわからない範囲までちゃっぴいに頼ってしまい しかも理想の動作にならなかったので エンジニアマインドパワー発揮して明日こそ あとtimesにimportmapとかstimulus画像化して まとめました。
6
426