惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
T
Threat Research - Cisco Blogs
N
News and Events Feed by Topic
Hacker News: Ask HN
Hacker News: Ask HN
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Security Latest
Security Latest
Spread Privacy
Spread Privacy
aimingoo的专栏
aimingoo的专栏
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
U
Unit 42
Cyberwarzone
Cyberwarzone
小众软件
小众软件
Scott Helme
Scott Helme
Engineering at Meta
Engineering at Meta
Microsoft Security Blog
Microsoft Security Blog
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
爱范儿
爱范儿
S
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Schneier on Security
Schneier on Security
Latest news
Latest news
GbyAI
GbyAI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
PCI Perspectives
PCI Perspectives
Jina AI
Jina AI
AI
AI
NISL@THU
NISL@THU
I
Intezer
G
GRAHAM CLULEY
B
Blog
S
Secure Thoughts
IT之家
IT之家
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
Y
Y Combinator Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
有赞技术团队
有赞技术团队
V2EX - 技术
V2EX - 技术
Recorded Future
Recorded Future
Hacker News - Newest:
Hacker News - Newest: "LLM"

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Building a Generative Jewelry Configurator with Vanilla JS, SVG, and Numerology
Camille Guerineau Loch Ness · 2026-06-22 · via DEV Community

published: false
description: How GemStudio 360™ turns a name and a birth date into a one-of-a-kind, hand-crafted bracelet — and why we built the rendering engine without a single framework.
tags: javascript, svg, pwa, webdev
cover_image:
canonical_url: https://lochness-paris.com/configurateur-de-bracelet.html
A few months ago we set out to build something that doesn't fit neatly into the usual "product configurator" template: a tool that turns your name and birth date into a personalized gemstone bracelet, lets you fine-tune every single bead by hand, and ends with a real artisan crafting the physical piece.

Loch Ness : Système Algorithmique de Détermination Archétypale et de Synergies Minérales à Géométrie Variable. | Zenodo

Résumé du Concept (Abstract) Le projet Loch Ness redéfinit l'interaction entre la psychologie individuelle et la lithothérapie à travers une interface numérique propriétaire. Contrairement aux approches standardisées à sortie fixe, ce concept repose sur deux piliers innovants : une taxonomie archétypale originale et un algorithme de séquençage minéral à géométrie variable. 1. L'Ontologie du « Monstre Noble » Le système utilise une taxonomie d'archétypes originaux créés pour refléter la complexité de la psyché humaine, incluant ses parts d'ombre et sa puissance brute. L'utilisateur n'est pas classé selon des critères sociologiques ou démographiques classiques, mais selon sa « nature sauvage » et sa capacité à canaliser une force intérieure singulière. Cette classification produit, pour chaque profil, un vecteur multidimensionnel d'intensité plutôt qu'une étiquette unique. 2. L'Algorithme de Calcul à Géométrie Variable L'application traite les données de l'utilisateur pour générer une réponse minérale dont la structure est unique à chaque profil : Séquençage Dynamique — le nombre de pierres (de 3 à 8 unités) n'est pas fixe ; il est déterminé par l'algorithme en fonction de la « densité » calculée du profil archétypal. Synergie de Compensation — chaque pierre est sélectionnée pour remplir un rôle fonctionnel spécifique (Ancre, Cœur, Mental, Bouclier, Élan), créant une armure vibratoire sur mesure plutôt qu'un assemblage arbitraire. Cette indirection rôle → pierre permet de faire évoluer indépendamment la nomenclature des rôles et le catalogue minéral, sans recalibrer l'ensemble du système à chaque ajout. 3. Pipeline Algorithmique Le traitement repose sur un pipeline en trois étapes fonctionnelles strictement découplées, chacune testable indépendamment : Normalisation identitaire — les données d'identité (prénom(s), nom, date de naissance) sont transformées en un vecteur de profil multidimensionnel (intensité, part d'ombre, élan, stabilité), sans dépendance au rendu ni à l'interface. Calcul de densité et résolution du nombre de slots — une fonction de densité agrège le vecteur de profil en un score scalaire, ensuite projeté sur l'intervalle entier [3, 8] pour déterminer dynamiquement la longueur de la séquence minérale. Résolution des rôles puis sélection minérale — pour chaque slot, un rôle fonctionnel est résolu en premier (Ancre, Cœur, Mental, Bouclier, Élan), puis une pierre est sélectionnée dans le catalogue pour satisfaire ce rôle au regard du vecteur de profil. 4. Architecture Logicielle Le système est implémenté comme une application web monopage (SPA statique), sans dépendance à un framework JavaScript, avec les caractéristiques techniques suivantes : Stack — HTML5, CSS3 (custom properties), JavaScript natif (vanilla) ; aucune dépendance à un framework de rendu. Moteur de rendu génératif — chaque minéral du catalogue est rendu en SVG généré dynamiquement (gradients radiaux, filtres, clip-paths) à partir d'un identifiant de minéral (« preset ») et d'une graine aléatoire (« seed ») propre à chaque occurrence, simulant veinage, translucidité et inclusions sans recourir à une banque d'images statiques. Disposition géométrique dynamique — la position de chaque pierre sur le support (bracelet) est calculée trigonométriquement en fonction de son index et du nombre total de slots résolu par l'algorithme (N variable, et non une constante), avec mise à l'échelle automatique de la taille des perles selon la densité de la séquence. Gestion d'état — l'état de la composition est représenté par un tableau ordonné de perles, avec piles d'historique (undo/redo) et re-rendu ciblé (et non un re-rendu complet) à chaque mutation, pour préserver la fluidité sur mobile. Progressive Web App — manifeste d'installation (icônes, couleur de thème, mode standalone) et Service Worker assurant la mise en cache des ressources statiques et une résilience hors-ligne partielle. Données structurées — balisage Schema.org (SoftwareApplication, FAQPage) pour l'indexation enrichie, en complément du contenu HTML visible. La documentation d'architecture complète (diagrammes de flux, choix techniques justifiés) ainsi que des exemples de code simplifiés à but pédagogique sont publiés séparément. Les tables de normalisation réelles, la fonction de densité, les seuils de résolution des rôles et le catalogue minéral complet ne sont pas publiés et constituent le cœur propriétaire du système. Objectif du Dépôt Ce document consigne la propriété intellectuelle de la logique algorithmique, de la nomenclature des archétypes et de la méthodologie de sélection des minéraux associée à la marque Loch Ness. Il protège l'invention d'un système de personnalisation où la technologie devient le pont entre l'identité profonde de l'individu et l'objet talismanique. Application en ligne : lochness-paris.com/configurateur-de-bracelet.html

favicon zenodo.org

The result is GemStudio 360™, the engine behind Loch Ness Paris' bracelet configurator. This post walks through the architecture, the technical trade-offs, and a few of the more interesting problems we had to solve — without giving away the proprietary parts (the numerology algorithm and the full gem-rendering engine stay closed source, but the shape of the system is worth sharing).
If you want to dig deeper, the architecture documentation and a few simplified code examples are public on GitHub: application-configurateur-de-bracelets-en-pierres-fines.
The brief, in one sentence

Turn an identity (first name, last name, birth date) into 8 symbolic gemstones, let the user build a real bracelet around them bead by bead, and hand the final design off to a craftsperson.
No accounts, no backend database of users, no checkout — just a fast, installable web app that ends in a personalized request sent to a human artisan.
Why no framework?
This was a deliberate choice. The whole app — numerology engine, SVG bead renderer, drag-to-build canvas, smart suggestions, cart — is built in vanilla JavaScript, plain CSS, and a single HTML file.
Three reasons drove that decision:
Load time matters more than developer convenience here. A big chunk of traffic comes from organic/mobile search for terms like "bracelet chemin de vie." Every extra hundred kilobytes of framework runtime is a few more bounces.
The DOM tree is genuinely simple. Four tabs, one SVG canvas, a handful of lists. State management doesn't need a library when the state is "an ordered array of beads plus some UI flags."
PWA installability and offline behavior are easier to reason about when you fully control the bootstrapping sequence instead of going through a framework's hydration lifecycle.
That said — vanilla JS at this scale means you have to be disciplined about state, which brings us to the next point.
State management without a framework
The entire bracelet is represented as an ordered array of bead objects. Every mutation (add, remove, reorder, change size) goes through a small set of functions that:
update the array,
push the previous state onto an undo stack,
re-render only the parts of the SVG that changed.
That last point matters a lot for performance: with up to ~19 beads rendered as gradient-filled SVG circles, a naive full re-render on every drag event is noticeable on mid-range phones. Re-rendering only the affected bead (and recalculating positions trigonometrically around the guide circle) keeps things smooth.

// Simplified illustration of bead positioning on the guide circle
function getBeadPosition(index, total, radius, center) {
  const angle = (index / total) * 2 * Math.PI - Math.PI / 2;
  return {
    x: center.x + radius * Math.cos(angle),
    y: center.y + radius * Math.sin(angle),
  };
}

Undo/redo is just two stacks of array snapshots — simple, but it's the kind of "boring technology" that makes a configurator feel trustworthy. Users mis-click constantly; cheap undo is a UX feature, not a nice-to-have.
Generating gemstones instead of photographing them
This is the part I find most interesting. With 70+ stone types in the catalog, maintaining a photo library (multiple angles, lighting consistency, file size, retina variants…) would have been a maintenance nightmare.
Instead, every bead is a procedurally generated SVG. Each stone type has a "preset" describing its visual family (translucent crystal, opaque mineral, banded stone, metallic finish…), and each individual bead instance gets a random seed that introduces small variations — hue jitter, gradient stop shifts — so that no two beads of the same stone type look perfectly identical, the same way no two real gemstones do.
A heavily simplified version of the idea:

function renderBead({ id, baseHue, seed }) {
  const rng = seededRandom(seed);
  const hue = baseHue + (rng() - 0.5) * 12; // small natural variation

  return `
    <radialGradient id="grad-${id}" cx="40%" cy="35%" r="65%">
      <stop offset="0%"  stop-color="hsla(${hue}, 45%, 75%, 1)" />
      <stop offset="60%" stop-color="hsla(${hue}, 45%, 55%, 1)" />
      <stop offset="100%" stop-color="hsla(${hue}, 45%, 35%, 1)" />
    </radialGradient>
    <circle cx="50" cy="50" r="48" fill="url(#grad-${id})" />
  `;
}

The production renderer is considerably more involved — it layers multiple gradients, clip paths, and noise patterns per mineral family to approximate veining (think lapis lazuli or labradorite) and translucency — but the core trick is the same: vector + seed beats a static image library when you need infinite, lightweight variation.
The numerology layer
The app's signature feature is the "Life Path Bracelet": you type in a first name and a birth date, and the engine computes 8 symbolic stones — Foundation, Summit, Life Path, Calling, Personality, Expression, Final Touch, and Wish — each tied to a different facet of numerology.
I won't detail the letter-to-number mapping or reduction rules here since that's the proprietary core of the product, but structurally it's a pure function:

identity (name + date) → numeric reduction → archetype (1–9) → stone(s)

Keeping it as a pure, side-effect-free transformation made it trivial to unit test and to keep completely decoupled from the rendering and cart logic. The numerology module has no idea an SVG even exists.
Smart suggestions and the "litho score"
Beyond manual bead-picking, there's a "Smart" tab with:
Harmonious palettes — pre-grouped stones by color coherence,
Predefined themes — ready-made compositions for intents like "protection" or "calm,"
A coherence score that evaluates how energetically consistent a user's manual selection is.
These are all derived/precomputed layers sitting on top of the same stone catalog — no real-time AI inference, just well-structured data and some scoring heuristics. It's a good reminder that "smart suggestions" don't always need a model; sometimes a well-curated lookup table does the job at a fraction of the latency and cost.
PWA bits that actually mattered
A few small, unglamorous details ended up making a real difference on mobile:
touch-action: manipulation on all interactive elements to kill the old 300ms tap delay.
Loading the webfont with media="print" then switching to all on load, so it never blocks first paint.
A Service Worker caching static assets for offline resilience and faster repeat visits.
A manifest.json so the app can be installed straight from the browser, no app store round-trip.
None of this is novel, but it's the kind of checklist that's easy to skip under deadline pressure — and it's exactly the stuff that determines whether a configurator feels like an app or like a website pretending to be one.
From pixels to a physical object
The configurator deliberately doesn't end in a checkout button. Once a composition is validated, the user lands on a recap + contact form, and the actual fulfillment is handled by a human artisan partner who crafts the bracelet by hand using the validated design as a spec sheet.
That constraint shaped a lot of UI decisions — for instance, the cart view always shows an estimated price range rather than a fixed price, since the final quote depends on material choices (precious metal findings, natural pearls, etc.) confirmed with the artisan.
What's public, what isn't
We open-sourced the documentation and architecture of this project, along with a few deliberately simplified code examples, in a public GitHub repo. What you'll find there:
a full architecture breakdown (diagrams included),
a feature-by-feature functional spec,
simplified illustrative examples of the numerology pattern and the SVG bead rendering pattern (not the production algorithms),
a roadmap and contribution guidelines.
What stays closed: the actual numerology letter/reduction tables, the full multi-preset rendering engine, the complete stone catalog, and the litho-score algorithm — those remain Loch Ness®'s IP.
Try it
The live configurator is here: lochness-paris.com/configurateur-de-bracelet.html
The project is also archived and citable via Zenodo: zenodo.org/records/19836838
If you're into vanilla-JS architecture, generative SVG, or PWA details, I'd genuinely love feedback — open an issue on the repo or drop a comment below.