LTM / WORKLOG.md
mlmihjaz
Rebrand to Sri Axis: remove AI + Three.js, rebuild 3D on Babylon.js
be189e0
|
Raw
History Blame Contribute Delete
22.4 kB

DesignForge Pro — Work Log

Continuation notes so any machine (or a fresh Claude session) can pick up where we left off. This file lives in the repo on purpose — git clone it on the new laptop and read this first.

What this is

▶ RESUME ON A NEW LAPTOP — read this first

  1. Clone: git clone https://huggingface.co/spaces/mlmihjaz/LTM then cd LTM.
  2. Auth for pushing: git push needs an HF write token — run huggingface-cli login, OR when git prompts use your HF username + a write token (from https://huggingface.co/settings/tokens) as the password. Credentials then cache in the OS keychain.
  3. It's a single static file — no install/build. Just open index.html, or serve locally to test: python -m http.server 8077 → open http://127.0.0.1:8077/index.html.
  4. External libs are all CDN (need internet): Fabric.js 5.3.0, ImageTracer.js (vector tracing), paper-core 0.12.17 (Pathfinder booleans). Pixabay key is inline (PIXABAY_KEY).
  5. Workflow: edit index.html → test locally (hard-refresh Ctrl+Shift+R) → git commit + git push origin main to deploy. The live .static.hf.space site only updates AFTER a push.
  6. Validate JS after edits: extract the inline <script> and run node --check (catches syntax errors before deploy).

Current feature set (as of 2026-06-16)

Shapes/text/images/filters/crop/pen · templates(placeholder) · Pixabay photos · export(png/jpg/webp/svg)+copy · visitor counter · snap guides · align/distribute · group/ungroup (top-bar icons + Ctrl+G/Shift+G) · save/open .dfp.json + autosave/restore + New · vector tracing (B&W/2/3/4/6/8/12/Full + Curvy/Sharp edge + detail) · My Library (localStorage, export/import) · deep color on groups/vectors · Pathfinder (unite/subtract/intersect/exclude) · middle-mouse pan · Alt-drag duplicate · right-click menu (copy/cut/paste/dup/group/ungroup/flip/delete) · rulers (px/mm/cm/in/m).

How to deploy

Plain git over HTTPS to the HF remote (origin = the Space repo):

git add index.html
git commit -m "..."
git push origin main      # pushes straight to the live Space; it rebuilds in seconds

Credentials were cached on the original laptop. On a new laptop you'll need to authhuggingface-cli login (or a write token as the git password) before git push works.

Verify a deploy landed:

curl -sL https://mlmihjaz-ltm.static.hf.space/ | grep -c <some-unique-string-you-just-added>

Features implemented (June 2026 session)

  • Bug fixes: stroke-only shapes (checkmark/cross/plus) were filled blobs → fixed; horizontal lines landed off-center → fixed; undo/redo pushed duplicate history states (needed 2 presses) → added dedupe in saveHist.
  • Shape editing: corner-radius slider, border style (solid/dashed/dotted), gradient fill/mix (two colors + direction) for shapes & lines.
  • Pen tool: click points → polygon; double-click/Enter to finish, Esc to cancel.
  • More shapes: added "More Shapes" category (semicircle, quarter, chevron, plus, chat, ribbon, flag, pac).
  • UX: left panel auto-switches to Text/Shapes on selection; Ctrl+A select-all; delete works on multi-selection.
  • Photos tab (Pixabay): image search next to Templates. API key in index.html (PIXABAY_KEY). Both API and image CDN send CORS *, so canvas export stays clean.
  • Templates: intentionally "coming soon" banner — clicking one only resizes the canvas. TODO: real templates (text + shapes + bg).
  • Branding/contact: welcome popup (once per browser via localStorage df_welcomed), scrolling promo marquee in top bar, WhatsApp + Facebook buttons top-right, credit + social links in status bar.
  • Visitor counter (status bar) — see below.
  • Load glitch fix: canvas now fit-zooms on first paint (was 100% then snap via setTimeout).

Visitor counter details

  • Service: counterapi.dev v1 (free, no auth, CORS *). No backend needed.
  • Namespace/key: designforge-ltm-mlmihjaz / visits
    • Increment: GET https://api.counterapi.dev/v1/designforge-ltm-mlmihjaz/visits/up
    • Read (CDN-cached! always add a cache-buster): .../visits/?cb=<ts>
    • Set: .../visits/set?count=N (cannot set 0 — Go required rejects zero)
  • App display = BASE + count, with BASE = 0 (so it shows the true server count).
  • Counts once per session (sessionStorage df_visit_counted); caches last value in localStorage df_visits_cache for instant paint + offline fallback.
  • Server value was seeded to 1990; it has since climbed naturally (1996 at last check). To re-seed: hit the set?count=N endpoint.

Features implemented (2026-06-16 session — "Pro editing" batch)

  • Smart snap guides: dragging an object snaps its edges/centers to the canvas (left/center/right, top/middle/bottom) and to other objects' edges/centers; pink dashed guide lines drawn on contextContainer in after:render. Threshold 7/zoom (screen-constant). State in snapLines; handlers wired inside initCanvas. NOTE: zoom is CSS scale() on #canvas-container, so Fabric viewport is identity — guide coords are raw canvas coords (× getRetinaScaling() via setTransform).
  • Align & Distribute: alignObjects(mode) — single object aligns to the canvas; multi-selection aligns within its bbox (discards the activeSelection so children are in absolute coords, then re-selects). Distribute needs 3+. UI = ⊞ Arrange ▾ topbar dropdown (#arrange-menu).
  • Group / Ungroup: groupSelection/ungroupSelection (Fabric toGroup/toActiveSelection); Ctrl+G / Ctrl+Shift+G + Arrange menu.
  • Save / Load projects: .dfp.json export (💾 Save / Ctrl+S) + 📂 Open import; autosave to localStorage df_autosave (debounced 800ms via scheduleAutosave in onCanvasChange), restored on load (restoreAutosave); ✲ New clears. Project shape: {app,v,name,w,h,json}.
  • Verified: JS node --check clean, all new IDs/functions resolve, served page contains them. Browser-tested visuals = snap lines + arrange menu.

Features implemented (2026-06-16 session #2 — vector tracing + library)

  • Vector tracing (raster→SVG): uses ImageTracer.js (CDN: cdn.jsdelivr.net/gh/jankovicsandras/imagetracerjs@master/imagetracer_v1.2.6.js, global ImageTracer). New Vector left tab (sec-trace). Source = selected canvas image / paste / upload (traceSourceEl). Color modes: B&W, 1 color (silhouette), 2–5 color (numberofcolors). runTrace(mode): downscale to ≤900px → imagedataToSVGfabric.loadSVGFromStringgroupSVGElements → add as _type:'vector' group (ungroup to edit each color). B&W/1-color pre-threshold the imagedata + use a black/white pal; 1-color also drops near-white paths. Detail slider maps to ltres/pathomit. Wrapped in setTimeout so the UI can paint a "Tracing…" status. Cross-origin/tainted images are caught + toasted.
  • My Library (persistent): new Library tab (sec-library), localStorage df_library. addToLibrary() serializes the active object (auto-groups an activeSelection) via toObject(['_name','_type']) + a PNG thumbnail (obj.toDataURL). renderLibrary() grid (click=add via fabric.util.enlivenObjects, hover ×=delete). Export/Import the whole library as JSON ("for future versions"). Quota errors are caught.
  • Verified: node --check clean, all new IDs/functions resolve, ImageTracer CDN 200. Browser-test the trace quality / tune detault detail.

Features implemented (2026-06-16 session #3 — deep color + Pathfinder)

  • Deep color on groups/vectors: setStyleDeep(obj,prop,val) recurses into group/activeSelection children so a fill applies to every path of a traced vector or grouped shapes (even while grouped). updateActiveShape routes groups/selections through it; updateRightPanel syncs sh-fill for groups (first child with a real fill); onSelectionChange opens the Shapes panel for group too. Colors survive ungroup→recolor→regroup.
  • Pathfinder boolean ops (paper.js): added paper-core CDN (paper@0.12.17, global paper, ensurePaper() lazy-inits an offscreen project). pathfinder(op) for unite/subtract/intersect/exclude in the Arrange menu ([data-pf]). Must select 2+ objects; it discards the activeSelection first so children are in absolute canvas coords, converts each to a paper path via obj.toSVG()importSVG (sub-paths united in objToPaperPath), runs the op (subtract = bottom minus the ones above, Illustrator "Minus Front"), then rebuilds one fabric.Path from result.pathData (fillRule evenodd, inherits bottom shape's style) and removes the originals.
  • Verified: node --check clean, both CDNs 200, all fns/wiring resolve. Browser-test boolean edge cases (holes/winding) + tune if needed.

Features implemented (2026-06-16 session #4 — editor UX + rulers)

  • Group/Ungroup as top-bar icon buttons (#btn-group/#btn-ungroup, .top-btn.ic).
  • Trace replaces the source raster even without clicking "Use selected" (runTrace derives traceSourceObj from the active image) so the original isn't left behind / copied.
  • Middle-mouse pan (FINAL, commit 5ce943e): done in setupPan() with Pointer Events on #canvas-wrappointerdown (button 1) in the capture phase calls preventDefault() to kill Chrome's middle-click autoscroll (the reason earlier attempts failed), setPointerCapture, then pointermove updates panX/panY from clientX/Y deltas; applyTransform = translate(panX,panY) scale(zoom). (Earlier fabric-mouse:* and window-listener versions did NOT work — autoscroll ate the moves.)
  • Alt-drag duplicate reworked: armed on mouse:down (altDragPending with original left/top), clone dropped on the first object:moving (so a plain alt-click doesn't duplicate).
  • Right-click menu expanded: Copy/Cut/Paste/Duplicate/Group/Ungroup/Flip/Delete. Object clipboard copyActive/cutActive/pasteCopied (reuses copiedObject); added Ctrl+X.
  • Ungroup freeze fix: updateLayers caps at 80 rows (+ "…N more"); ungroup is deferred with a toast + confirm if >300 parts; snap-guide object loop skips when >60 objects.
  • Rulers (#ruler-h/#ruler-v/#ruler-corner + #ruler-unit select) with px/mm/cm/inch/m (96px=1in mapping). drawRulers() uses canvas-container.getBoundingClientRect() for origin + zoom for scale, "nice" tick steps, pink cursor indicator; called from applyTransform, resize, and unit change.
  • Verified: node --check clean, both CDNs ok, served file has all markers. Needs browser pass for ruler alignment + middle-pan feel.
  • KNOWN: zoom is still CSS scale() on the container, so zooming past 100% rasterizes the whole canvas (vector edges pixelate). True crisp zoom = refactor to Fabric native setZoom/viewportTransform (touches applyZoom/fitZoom/snap-guides/rulers/pan) — deferred.

Features implemented (2026-06-17 session #5 — zoom/selection polish, popup-first UX, Smart Draw)

  • Selection handles vs CSS zoom: syncControlScale() (called from applyZoom) counter-scales cornerSize/touchCornerSize/borderScaleFactor by 1/zoom so handles stay constant on-screen; Canva-style white circular handles w/ purple stroke set on fabric.Object.prototype in initCanvas. Snap-guide line width also /zoom. Ruler robustness: trim CSS-var colors, ResizeObserver on #canvas-wrap, rAF-throttled cursor redraw.
  • Live transform readout: object:moving/scaling/rotatingupdateRightPanel so X/Y/W/H update live.
  • Shapes scale to artboard: addShape multiplies default sizes by k = clamp(min(cw,ch)/600, 0.6, 4) so shapes aren't specks on big pages.
  • Recent colors + shared color: recentColors (localStorage df_recent_colors, 8 max). applyColorToActive() is the single entry (text fill / shape fill) used by recent swatches, the popup color button, side-panel inputs. Swatches render in the popup (#ct-recent).
  • Contextual selection popup (#canvas-toolbar): updateToolbarForType(obj) shows image→#ct-adjust(⚙)/#ct-crop, text/shape→color button (.ctx-color); common = flip/rotate/layer/dup(#ct-dup)/opacity(#obj-opacity moved here)/recent/delete. Image Adjustments+Filters panel (#rp-adj) is moved at init into #ct-pop-adjust popover (toggled by ⚙); closes on outside-click / non-image select.
  • Single export path: removed right-panel Quick Export; topbar Download opens the modal; Copy-to-clipboard moved into the modal.
  • Resize consolidated: removed right-panel Canvas section; topbar ⊡ Resize → size modal (presets + custom W/H). updateSB/loadProject now sync custom-w/custom-h.
  • Topbar regroup: New/Open/Save/Undo/Redo are icon-only (.top-btn.ic), then Resize/Group/Ungroup/Arrange.
  • AI Designer panel (#rp-ai): front-end-only chat UI (gradient ✦ header, 13px bubbles, suggestion chips, autosize textarea). No backend yetsubmit() just echoes a "coming soon" bot reply. Ready to wire a real model later.
  • UNITE rotation bug — FIXED (took 5 tries): root cause = paper.js 0.12 boolean ops run on raw segment coords and IGNORE pending/unbaked matrices; also discardActiveObject() doesn't bake the active-selection's rotation back into children. FINAL fix in objToPaperPath(obj, m): capture each object's calcTransformMatrix() before discard (mats in pathfinder), neutralize the object to read transform-free centre-origin local geometry via toSVG, import to paper, then bake the matrix into the point coords with local.getPathData(paperMatrix, 4) and rebuild a fresh identity-matrix CompoundPath from that string → unite gets already-absolute geometry. Switched CDN to paper-full (was paper-core). VERIFIED WORKING by user.
  • Smart Draw (AutoDraw-style) in Shapes panel (#btn-autodraw, toggleDraw/startDraw/stopDraw, drawMode): drag to sketch → snaps to a clean editable shape. Live stroke painted in an after:render hook (NOT a canvas object, so no layer/history pollution). Recognition = least-squares fitting: _resample(64), Kåsa _fitCircle, PCA rotation-aware _fitEllipse, line fit, _rdp corners + _polyResidual (RMS pt→chord); decide by lowest fit error biased ×1.4 toward round. Outputs Line / Circle / Ellipse(rotated) / Rect(axis-aligned) / Polygon(triangle/penta/hexa/irregular via detected vertices) / open Polyline. Esc exits.
    • RESOLVED in session #6 — replaced by the AutoDraw clip-art flow (TF.js DoodleNet + Iconify) and folded into the Drawing Toolset as "Magic Pencil".

Features implemented (2026-06-17 session #6 — Drawing Toolset + AI AutoDraw)

All in the Shapes left panel under "Drawing Tools" (.draw-tools palette of .dtool buttons + .draw-opts: #draw-color, #draw-size, #brush-type). One tool active at a time via activeTool + selectTool(name) / deactivateAllTools(except) / refreshToolBtns(). State vars near drawMode: activeTool, brushActive, lineOn/linePts/lineCur, penBezOn/bezAnchors/bezDrag/bezCur, nodeEditOn/editNodes/editClosed/editStyle/editDrag. All tool pointer routing is added into the canvas mouse:down/move/up/dblclick handlers in initCanvas; live previews are drawn in after:render hooks (never as objects → no layer/history spam).

  • ✨ Magic Pencil (t-magic) — the AutoDraw-style AI tool (was "Smart Draw"). TF.js + DoodleNet (345 QuickDraw classes), lazy-loaded on first use from jsDelivr: model cdn.jsdelivr.net/gh/yining1023/doodleNet@master/demo/DoodleClassifier_345/model/model.json + sibling class_names.txt (CORS ok); @tensorflow/tfjs@4.22.0. Flow (drawEndsmartRecognize… actually now): keep the rough stroke as an editable Polyline, classify top-5 (topPredictions, input rasterized to 28×28 centred, strokes=1/bg=0 per _strokeToTensor), then Iconify search API (_iconifySearch/gatherIcons, free, CORS, 200k+ icons) for the guesses → render a suggestion bar (#ai-suggest/showSuggestions) of clip-art; click one (placeIcon) → fetch SVG, currentColor#333, loadSVGFromString→group, scaled to the sketch bbox, replaces the stroke (editable _type:'vector'). One-shot: pen deactivates on mouse release (deactivateDraw); suggestion bar persists (× / Esc / drawing again hides it). Graceful fallback keeps the sketch if AI/icons unavailable. NOTE: the old least-squares recognizer (recognizeStroke/geomFromLabel/createRecognized/_fitCircle/_fitEllipse/_rdp/_polyResidual) is still in the file but currently UNUSED by Magic Pencil — kept for reuse.
  • 🖌️ Brush (t-brush) — fabric free-drawing. enableBrush()/disableBrush(); types Pencil/Marker(2.2× width + 55% alpha via _hexA)/Spray/Dots(circle); size #draw-size, color #draw-color. path:created tags brush paths. Option changes re-apply via refreshBrush().
  • 📐 Line (t-line) — dot-click straight open polyline. lineClick (Shift-constrain to 0/45/90° via _constrain), preview hook, finishLine() on double-click / Enter → fabric.Polyline. Stays active for the next line.
  • ✒️ Pen (Bézier, Illustrator-style) (t-pen) — penDown/penMove(p,alt)/penUp; click = corner, click-drag = smooth mirrored handles, Alt-drag = break handle (cusp) (skip mirror), click the first anchor (within 9px) to close. _bezD(anchors,closed) builds the d (M/L/C/Z); finishBez(closed) on Enter/dbl-click → fabric.Path (closed fills with draw color).
  • Node editing (Direct-Selection) — double-click any path/polyline/polygonenterNodeEdit(obj) parses commands to canvas-coord nodes (maps via obj.calcTransformMatrix() + pathOffset, fabric.util.transformPoint), removes the object, edits a node model, draws live in after:render. nodeDown/Move/Up: drag anchors (handles follow), drag handles (mirror unless Alt → break), click a segment to insert an anchor (nodeInsert — straight split or De Casteljau _cubicPt/_lerp Bézier split, closing segment too), double-click an anchor to delete (nodeDblClick), Alt-click an anchor = corner↔smooth (toggleNode — drop handles, or add symmetric handles along the neighbour tangent). exitNodeEdit(true) (Enter/Esc/switch tool) rebuilds a clean fabric.Path.
  • Keyboard: Enter finishes Line/Pen; Enter/Esc commits node-edit; Esc exits the active tool. Verified: inline <script> parses clean (new Function) on every push.

Known notes / next ideas

  • Drawing toolset is the foundation for a "complete library": more brush textures/pressure/taper, dashed/calligraphy nibs, fill toggle for pen shapes, marquee multi-anchor select. The unused least-squares recognizer could power a "snap to clean shape" toggle.
  • Templates are placeholders — biggest remaining "real Canva" feature.
  • Counter relies on a 3rd-party free service; if it dies, swap for a tiny Gradio/Docker Space hosting a JSON counter.
  • Possible next: save/load projects (localStorage + JSON import/export), alignment/snap guides, grouping, multi-page.

Git history (recent)

Run git log --oneline for the full list. Latest session commits: shape/undo fixes → welcome/promo → sidebar spacing → visitor counter (+ stale-read fix, seed 1990) → load-glitch fix.


2026-06-18 — Major re-architecture: "Sri Axis" (3D-enabled 2D design app)

Rebranded DesignForge Pro → Sri Axis. Removed the Claude AI Designer + the Anthropic proxy (app.py is now a minimal FastAPI static server; requirements.txt = fastapi+uvicorn only) and removed Three.js entirely. 3D rebuilt on Babylon.js (CDN + earcut), woven into the 2D app as a transparent overlay synced to the Fabric artboard.

3D engine (Babylon): Extrude / Revolve / Inflate (puffy pillow on a uniform grid). Shapes AND text both convert through one accurate pipeline: object is rasterised (toCanvasElement) onto a padded canvas → ImageTracer (alpha-keyed, black-on-white) → contours grouped into fills+holes by even/odd nesting → per-part ExtrudePolygon + merge. This keeps strokes/line icons as real rings (e.g. bicycle wheels), letter counters open (o/a/e/g), and disjoint/decorative shapes intact. Camera tilt baked into geometry so the default face-on view reads Tilt X = 0. Per-object move (drag on ground plane) / Spin-Tilt-Roll-Size sliders (+editable number inputs) / right-drag tilt+roll / gizmo-free selection via Fabric pointer (auto-switch 2D↔3D) / delete+copy+paste for 3D / orthographic default + perspective toggle / wheel zooms 3D when a 3D object is selected (Ctrl+wheel = artboard) / multi-light setup (key+fill+ambient, colour/power/direction). Save composites 2D+3D into one PNG.

UI: top bar = Select(default)+Text+drawing tools(Magic/Brush/Pen/Line + brush options) + duplicate/delete; right panel = Inspector (dynamic) holding Position&Size (px/mm/cm/m/in/ft units), Appearance (fill/line/line-type/opacity/corner), Fill&Effects (gradient/shadow/skew), Text (font/size/spacing/align/justify/letter/line/bend), Pathfinder (unite/subtract/intersect/exclude), and the 3D controls — all contextual. Shapes panel = shapes only; shape search also queries Iconify (200k+ online icons → editable vectors). Resize modal unit-aware. Unlimited zoom. Removed promo marquee + social buttons + startup messages. Copy/paste/duplicate fixed for multi-selections (activeSelection). Curved/bend text via Fabric text-on-path.

NOT yet verified in a real browser end-to-end beyond local serving; tested via node --check + manual local serve on :8778.