Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22.12.0
- run: npm install --no-audit --no-fund
- run: npm test
- run: npm run build
2 changes: 0 additions & 2 deletions README.md

This file was deleted.

14 changes: 14 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from 'astro/config'

export default defineConfig({
output: 'static',
compressHTML: true,
build: {
inlineStylesheets: 'auto',
},
vite: {
build: {
target: 'es2022',
},
},
})
46 changes: 46 additions & 0 deletions docs/animation-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Calcifer graph hero

## Rendering

The section is statically rendered by Astro. The heading, description, actions and technology labels are present in the first HTML response. The animated canvas is decorative and does not contain SEO-critical content.

The graph uses two Three.js draw calls:

- `THREE.Points` with a custom shader for every node;
- `THREE.LineSegments` for every connection.

No post-processing pass is used. Soft glow is calculated inside the point fragment shader, which avoids an additional framebuffer and reduces GPU cost on laptops and mobile devices.

## Shape generation

The flame body is generated deterministically from a seeded pseudo-random function. Points are accepted inside a union of a rounded body and five tapered flame tongues. Arms, eyes, pupils and the mouth are generated from explicit curves so the face remains readable at every quality level.

The graph connects flame points to nearby neighbours. Face rings and mouth curves have stronger internal springs. Each facial group is also attached to nearby flame nodes.

## Physics

Every node stores its current position, velocity and immutable target position. Each frame applies:

1. spring forces along graph edges;
2. a target-anchor force that preserves the silhouette;
3. velocity damping;
4. a very small role-aware idle drift.

While a node is dragged, its target anchor is weakened for connected nodes up to four graph steps away. Influence decays by graph distance. The selected node follows the pointer directly, while its neighbours follow through the spring network. After release, target anchors restore the original silhouette.

## Torch reveal

The code wall is a DOM layer behind the canvas. It remains transparent until a node is dragged. Pointer position updates CSS custom properties that control a radial mask. Pointer speed controls opacity, producing a torch-like reveal without rendering code into WebGL.

## Loading and fallbacks

The first render displays an inline SVG graph generated from the same deterministic model. Three.js is code-split and loaded after browser idle time or the first pointer interaction.

The implementation also:

- caps device pixel ratio;
- reduces node count for coarse pointers and small viewports;
- pauses animation when the document is hidden;
- disposes GPU resources on disconnect;
- preserves the SVG fallback after WebGL context failure;
- keeps the static SVG when `prefers-reduced-motion: reduce` is enabled.
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "webdev-agent-kit-frontend",
"version": "0.1.0",
"private": true,
"type": "module",
"engines": {
"node": ">=22.12.0",
"npm": ">=9.6.5"
},
"scripts": {
"dev": "astro dev",
"build": "astro check && astro build",
"check": "astro check",
"preview": "astro preview",
"test": "node --import tsx --test tests/**/*.test.ts"
},
"dependencies": {
"astro": "7.0.7",
"three": "0.185.1"
},
"devDependencies": {
"@astrojs/check": "0.9.9",
"@types/node": "26.1.1",
"@types/three": "0.185.1",
"tsx": "4.23.0",
"typescript": "6.0.3"
}
}
2 changes: 2 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
User-agent: *
Allow: /
Loading
Loading