Dokumen ini mencatat tujuan, struktur dan keputusan arsitektur untuk platform Lolly. Ini mencerminkan baik visi produk maupun kondisi basis kode saat ini.
Status: Lolly sudah dirilis. Versi 1.0 diluncurkan sebagai open source di bawah MPL-2.0 pada 30 Agustus 2026, dan fitur, bawaan serta katalog tool masih berubah antar rilis. Mesinnya deterministik, dengan satu jalur render di balik setiap shell. Keamanannya belum pernah diaudit secara independen, dan bukti adopsinya berusia beberapa bulan. Lihat Adopsi & Tata Kelola untuk kondisi saat ini dan cara adopsi diukur.
Cara membaca halaman ini. Halaman ini memuat dua jenis materi, secara berurutan. Separuh pertama adalah mengapa ini ada: masalahnya, positioning-nya dan siklus hidup yang dilalui satu aset. Mulai dari Gambaran besar dan seterusnya adalah bagaimana lapisan-lapisannya menyatu: dokumen arsitektur untuk kontributor, mencakup pemisahan engine/shell/pack, tata letak repositori, target pengiriman dan komitmen yang membatasi setiap perubahan pada platform. Jika Anda di sini untuk mengubah basis kode alih-alih memahami produknya, mulailah dari gambaran besar.
Dua dokumen pendamping menyelami lebih dalam daripada halaman ini.
engine/README.mddi repositori adalah peta modul-demi-modul dari engine, dengan tabel yang dihasilkan otomatis dari setiap modul dan apa yang diuraikan atau ditulisnya. Model Ancaman & Batas Kepercayaan adalah arsitektur yang sama dibaca sebagai batas kepercayaan, dan itu adalah halaman yang tepat untuk pertanyaan apa pun tentang apa yang dianggap engine sebagai tidak tepercaya.
Mengapa ini ada
Pekerjaan kreatif yang bisa diulang terlalu dapat diprediksi untuk membenarkan tangan terampil setiap kali, dan terlalu sensitif terhadap kualitas untuk diserahkan tanpa pengaman. Jika dibiarkan, hasilnya salah satu dari tiga: lambat, tidak konsisten atau terkunci pada template vendor.
Platform ini adalah jawaban langsungnya:
Kreatif dan konten programatik dalam skala besar - aset yang dihasilkan dari input, dengan aturan yang ditetapkan sekali, untuk siapa pun yang membutuhkannya.
Lolly bukan tempat sebuah design system diciptakan - melainkan tempat design system itu diproduksi. Anggap seperti sebuah vending machine untuk desain: buat pilihan, dapatkan hasil. Setiap saat. Engine ini bekerja untuk kualitas tertinggi yang bisa dihasilkan setiap format pada perangkat keras di hadapan Anda, dan engine yang sama membuat berkas yang sama pada setiap platform tempatnya dirilis.
Hasilnya adalah kelimpahan: setiap acara memiliki signage yang benar, setiap peringatan CVE cocok dengan gaya perusahaan, setiap label tercetak bersih, setiap tanda tangan email selalu terkini - semua dari alat yang sudah membawa aturannya sendiri. Platform ini menangani kreatif operasional yang berulang. Ini sengaja bukan alat kreatif custom - desainer tetap memegang kendali atas karya unggulan.
Berinovasi secara probabilistik, berskala secara deterministik
Setiap perdebatan tentang AI dalam alur kerja kreatif terhenti pada pertanyaan yang sama: bagian mana dari ini yang menjadi tugas mesin? Ini pertanyaan lama dengan jawaban yang sudah mapan. Juru tulis dan pelukis manuskrip sudah bekerja di antara dua instrumen - sketsa bebas, di mana tidak ada yang tetap dan segalanya bisa dicoba, dan mesin cetak, yang menakutkan justru karena ia mengikat komitmen. Sketsa adalah tempat seni terjadi. Mesin cetak adalah cara seni itu menjangkau siapa pun. Tak seorang pun mencampuradukkan keduanya, dan keduanya terus maju - tinta baru, huruf baru, mesin cetak baru - masing-masing berkembang selaras dengan kerajinan dan maksud yang dilayaninya.
Lolly menarik garis yang sama. Jelajahi secara probabilistik: sebuah model, seorang desainer, ide kasar, sebuah prompt yang menuju ke arah yang tidak direncanakan siapa pun. Lalu berskalalah secara deterministik - hal yang menjadi banyak output adalah sebuah alat, dan alat merender dengan cara yang sama setiap kali dari input yang bisa Anda baca. Eksplorasi tetap bebas karena tidak ada apa pun di hilir yang bergantung pada hasil yang sama dua kali. Outputnya mendapatkan kepercayaan karena bukan tebakan. Membawa eksperimen AI ke hasil yang dapat diprediksi dan direproduksi bukanlah disiplin baru; itu adalah pembagian kerja yang sama yang membuat karya cetak layak dipercaya sejak awal.
Percayai proses kreatif, berskala dengan kedisiplinan.
Melawan alternatif
Lolly includes lolly.work, the same project's separately deployed organisation service. Local creation needs no account; shared work and server rendering use the configured instance. Competitor scores: August 2026. Lolly coverage: 28 September 2026.
| Capability | Lolly+ lolly.work | Penpotopen design | CanvaAffinity Cavalry |
Adobedesktop pro | Brand DAMFrontify Bynder |
Cloudinarymedia pipeline | Figmaonline pro | Render APIsBannerbear Placid Creatomate |
|---|---|---|---|---|---|---|---|---|
| Overall completenessunweighted mean - weight rows for your own context · columns are sorted by this row | 84 | 70 | 57 | 48 | 41 | 41 | 41 | 34 |
Production maturity & track recordCanva, Adobe, Figma, Bynder/Frontify: a decade-plus at massive scale. Render APIs: years in production pipelines. Penpot: shipping, large community, younger at enterprise scale. Lolly: version 1.0 public since 30 August 2026 under MPL-2.0, and SUSE runs it as an internal deployment; no usage data is shared yet and there are no public case studies yet. Cloudinary: 2012, enterprise media infrastructure at global scale. |
25 | 75 | 100 | 100 | 100 | 100 | 100 | 75 |
Mass generation from data (CSV / API)Lolly: batch grid and CLI, plus lolly.work's recoverable server jobs and batches with retries, cancellation and retained outputs. Canva: Bulk Create + Autofill API - real, but Enterprise-gated, async, text/image fields only; Affinity Publisher adds desktop data merge. Adobe: InDesign data merge and scripting. Figma: Buzz fills templates from CSV or XLSX, free in beta (Aug 2026) - cloud- and account-gated, 50. Penpot: open API/MCP, not purpose-built. Render APIs: this is their entire product - account- and cloud-gated, so 75 under the method rule. DAM: Studio-style batch create and resize. Cloudinary: URL-driven overlays and named transforms derive variants at scale - account-gated, 75. |
100 | 50 | 50 | 50 | 75 | 75 | 50 | 75 |
Offline & air-gap operationLolly: standalone creation works offline once its assets are available; lolly.work's organisation services need a reachable instance, which can run on an internal network. The Canva column is scored on its best family member: Affinity (free since Oct 2025) runs offline as a desktop suite once a verified account activates it - 75, the same deduction Adobe takes. Canva's own Offline (2026) still edits pre-synced designs only, per device, in a 14-day window. Adobe: desktop apps run offline; licensing phones home. Figma: cached-file viewing and limited editing. Penpot: self-host on your infra behind a firewall (server required). Cloud APIs and DAM: none. |
100 | 75 | 75 | 75 | 0 | 0 | 25 | 0 |
On-device rendering - data never leavesLolly: local rendering and conversion in-browser or CLI need no upload. Choosing lolly.work's shared storage, work collabs or server rendering sends the relevant data to the configured instance. Adobe: local desktop rendering, but cloud services and telemetry in the suite. Figma: canvas renders locally, files live in Figma's cloud. Penpot: 90 - rendering happens in the browser and the save target is a server that can be your own sovereign private cloud, even your own laptop, with private export throughout; only the server hop separates it from Lolly. Canva itself is server-side by design; the column's 75 is Affinity - local desktop rendering, account activation and telemetry, the same shape as Adobe. Render APIs, DAM: server-side by design. |
100 | 90 | 75 | 75 | 0 | 0 | 25 | 0 |
Hard brand constraints (structural)Lolly: templates fix layout rules and expose permitted inputs. lolly.work adds group access, input policies, shared catalogues, approvals and audit records. Copy and usage rights can still need review. Canva: element locks - permission-based, admin-set and static: no template logic such as conditional logo switching or responsive recomposition at fill time, and Canva AI does not yet respect Brand Controls - 50. Render APIs: templates are fixed (only declared fields vary) but no governance layer. DAM: locked templates with restrictions. Figma: Buzz templates hold locked guidelines at fill time; the design surface stays review-enforced - 50. Penpot: tokens and systems enforced by review, not runtime. Adobe: libraries, little enforcement. Cloudinary: presets and Enterprise-gated transformation templates fix operations, not brand layout - 50. |
100 | 50 | 50 | 25 | 75 | 50 | 50 | 75 |
C2PA provenance, signed at creationAdobe: the broadest shipped implementation (Photoshop, Lightroom, Premiere, Firefly) - signing happens locally in the desktop apps and in the cloud for the Content Authenticity web app, and nothing signs without an Adobe account and an Adobe-provisioned identity, so it is account-gated end to end: 75 under the method rule. Lolly: optional on-device signing without an account, plus lolly.work server signing with a configured organisation identity. A verifier must trust the signer's root to show a trusted identity. Version 1.0 is public and SUSE runs it internally, but no usage data is shared yet, so 75. Penpot: 50 via the official Lolly Export plugin - the same on-device engine signing Lolly uses, opt-in, as in Lolly (and disclosed plainly: it is Lolly's own plugin). No evidence of C2PA writing in Canva, Figma, render APIs or DAM as of Aug 2026. Cloudinary: 50 - signs images on delivery (fl_c2pa, CAI member since 2020), attesting delivery by Cloudinary rather than creation by you. |
75 | 50 | 0 | 75 | 0 | 50 | 0 | 0 |
CLI, pipeline & AI-agent automationLolly: CLI, TUI, MCP server and URL mode, plus lolly.work's authenticated render API, recoverable batches and governed delivery. One engine across the local and server paths. Render APIs: API-first, webhooks, integrations - account- and cloud-gated, so 75 under the method rule. Penpot: open API, plugins, official MCP server. Canva: Connect API - Enterprise-gated, async, rate-limited. Adobe: UXP/ExtendScript plus Firefly APIs. Figma: strong REST/plugin API, no render pipeline. DAM: asset-management APIs. Cloudinary: API-first media pipeline - account-gated, 75. |
100 | 75 | 50 | 50 | 50 | 75 | 50 | 75 |
Live collaboration (real-time co-editing)Figma: the scale benchmark - 200 simultaneous editors, up to 500 people in a file - account and cloud required. Canva: mature real-time editing across the product, same precondition. Penpot: real-time multiplayer with live cursors; self-hosting lifts the vendor-account precondition, but a server is still required. Lolly: direct two-device private collabs without an account, plus authenticated work collabs through lolly.work with shared edits, cursors and saved team sessions. Partial reflects the current single-node work deployment and limited operating history. Private collabs work without internet on a shared network; work collabs need the organisation's instance. Adobe: Live Co-Editing in beta, cloud documents only. Render APIs: no editing surface. DAM: comments and approvals, not canvas co-editing. Cloudinary: DAM comments and workflows, no canvas co-editing. |
50 | 75 | 75 | 25 | 25 | 25 | 75 | 0 |
No design skill requiredCanva: the category benchmark for ease. DAM: fill a locked template. Lolly: fill in fields using an existing tool, or publish a tool from Design through Share with rules. lolly.work manages access and input policy for the team. Render APIs: swaps design skill for developer skill. Adobe, Figma, Penpot: professional tools. Cloudinary: the media library is easy; transformations are developer territory. |
100 | 25 | 100 | 25 | 100 | 50 | 25 | 50 |
Open source, self-hosted, no lock-inPenpot: MPL-licensed, 51k+ stars, self-host via Docker/K8s - fully verifiable today. Lolly and lolly.work: MPL-2.0 open source in separate repositories, both self-hostable. lolly.work provides the organisation services as part of the project. The current 75 reflects the young project and limited deployment history. Everything else is proprietary SaaS or proprietary desktop. |
75 | 100 | 0 | 0 | 0 | 0 | 0 | 0 |
Cost at production scaleLolly + lolly.work and Penpot: no per-seat software licence charge for the open-source self-hosted path; hardware, storage and operations remain costs. Render APIs: metered - roughly $0.005–0.049 per image, credits often expiring monthly. Canva/Figma: per-seat; Canva's automation needs Enterprise, though Affinity itself is free since Oct 2025. Adobe: premium per-seat suite. DAM: sales-led enterprise quotes, MAU or seat models. Cloudinary: credit-metered across transforms, storage and bandwidth - 25. |
100 | 100 | 50 | 25 | 25 | 25 | 50 | 25 |
Annual medium enterprise spendIndicative list-price arithmetic for a medium enterprise - think 500-5000 people - August 2026: a guess range, not a quote; deals vary and the seat mix dominates. Ring = how much of the board's largest annual spend (US$500k) you keep; the number in the ring is each range's upper bound. Canva (US$75k-400k; Affinity free since Oct 2025 pulls the design-seat share down), Adobe (US$100k-500k) and Figma (US$30k-250k) assume the realistic creative-seat share of an organisation this size - tens to hundreds of seats, not a licence for every employee. Render APIs price by usage (US$5k-60k). DAM is quote-only, commonly US$50k-250k and up. Penpot is hand-set at 99: "your server" can be your own laptop - a small technical hurdle at well under 1% of an Adobe-scale spend. Lolly + lolly.work: US$0 in software licence charges for self-hosting. The figure excludes devices, organisation hosting, storage, support and administration; these need a separate budget. Standalone Lolly does not need the organisation service. Cloudinary: US$30k-150k, credit-based; enterprise contracts commonly sit near US$82k. |
$0 | $0 | $400k | $500k | $250k+ | $150k | $250k | $60k |
Kelengkapan kapabilitas di antara alat kreatif hari ini, diteliti Agustus 2026. Penilaian: 0 tidak ada, 25 tingkat akal-akalan, 50 nyata tetapi terbatas atau parsial, 75 kuat dengan catatan, 100 kompetensi inti.
signed by Lollypositioning-comparison.htmlHTMLpixels, not shapes40 KBAI generatedgenerated by GPT-6Periksa sendiriAmbil file bertanda tanganKesenjangannya jelas: tidak ada yang tersedia hari ini yang memberi kami output constraints-first, mampu offline, keterampilan rendah, dan dapat diakses secara internal. Lolly bahkan menyertakan kanvas terbuka - Design - di mana warna, tipografi dan aset menaati brand global, sehingga penataan bebas tetap constraints-first. Yang bukan ini adalah suite desain tanpa batasan: desainer tetap memakai Illustrator dan Figma untuk karya unggulan custom. Permutasi dapat dirakit dengan alat ini.
signed by Lollyvector SVG367 paths~62k nodes773 groups3 images1.453 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG367 paths~62k nodes776 groups3 images1.454 KBPeriksa sendiriAmbil file bertanda tangan
Gunakan untuk: Pembuatan cepat aset kreatif operasional - ubin acara, badge nama, tanda tangan, peringatan CVE, kode QR, kartu sosial, label konsinyasi, laporan terstruktur.
Jangan gunakan untuk: Konten unggulan custom.
Siklus hidup sebuah kampanye
Cara paling jelas untuk melihat apa itu Lolly bukanlah daftar fitur - melainkan mengikuti satu aset saat berpindah dari tangan ke tangan. Amati satu kartu kampanye yang dilokalkan bergerak melalui organisasi:
- Sang kreatif menetapkan aturan. Seorang desainer menyusun template dasar di alat Design, menetapkan tipografi dan variabel warna brand secara hard-coded. Mereka bukan membuat satu kartu - mereka melakukan pekerjaan fondasi sekali agar tidak pernah perlu melokalkan secara manual lagi.
- Sang developer menskalakannya. Template yang sama dihubungkan ke pipeline malam hari lewat CLI, sehingga chart segar atau varian bahasa baru dihasilkan secara otomatis - tidak ada desainer yang membuka ulang file.
- Sang produser tinggal memakainya. Seorang sales rep, offline di pesawat, membuka alat yang sama dan menghasilkan deck yang sepenuhnya on-brand untuk pertemuan klien. Tanpa keterampilan desain, tanpa jaringan, tanpa menunggu.
"Chart segar" pada langkah kedua adalah render seperti ini, dihasilkan dari sebuah string data dan segenggam parameter tanpa seorang pun membuka file desain:
signed by Lollyvector SVG15 paths~1.3k nodes4 groups20 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG15 paths~1.3k nodes4 groups20 KBPeriksa sendiriAmbil file bertanda tangan
Intinya bukan bahwa Lolly bagus untuk desainer dan bagus untuk developer dan bagus untuk sales, masing-masing dalam ruang hampa. Ini adalah lomba estafet: pekerjaan awal sang kreatif diskalakan oleh developer, yang pada gilirannya memberdayakan produser. Pengalaman tanpa hambatan bagi sales rep non-teknis di pesawat itu hanya mungkin karena kedisiplinan yang ditetapkan desainer dan diterapkan developer.
Itulah pengganda kekuatannya. Lolly bukan laci berisi alat-alat terpisah untuk peran-peran terpisah - ini satu siklus hidup aset deterministik yang disentuh setiap peran, dan setiap tangan yang dilaluinya melipatgandakan nilai tangan sebelumnya.
Satu alat, banyak output
Aturan brand ada di dalam alat, bukan di setiap file yang dibuatnya (lihat Bagaimana Lolly dibandingkan). Buat alatnya benar sekali, dan setiap output mewarisi jenis huruf, warna dan spasi yang sama, baik itu satu kartu atau spreadsheet berisi banyak baris dalam belasan bahasa. Bagaimana Anda memeriksa pekerjaan Anda, dan siapa yang melakukannya, tetap urusan Anda; Lolly membuat hal yang layak diperiksa menjadi lebih kecil dan outputnya lebih cepat dibuat.
Alat deterministik yang sama mencapai skala itu dengan tiga cara, semuanya menghasilkan output yang identik:
- Seseorang, di dalam aplikasi. Grid batch
/pro: tempel atau impor barisnya, dapatkan satu aset jadi per baris, unduh zip-nya. Tanpa keterampilan desain, tanpa menunggu. - Seorang developer, dari baris perintah. CLI menjalankan engine yang sama dan jalur render yang sama secara headless, sehingga alat itu bisa dijalankan berurutan di setiap baris dalam sebuah skrip atau pipeline malam hari. Panggilan
lolly <tool> --field=…dalam sebuah loop adalah keseluruhan integrasinya. - Sebuah sistem atau agen AI, lewat MCP. Alat yang sama dijalankan secara programatik, dengan fidelitas yang sama, untuk sebanyak apa pun baris yang dimiliki pekerjaan tersebut.
signed by Lollyvector SVG133 paths~15k nodes185 groups1 image195 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG133 paths~15k nodes185 groups1 image195 KBPeriksa sendiriAmbil file bertanda tangan
Satu set batasan brand, ditetapkan sekali oleh seorang desainer; tiga rute menuju output yang identik.
Gambaran besar: bagaimana lapisan-lapisannya menyatu
Semua yang ada dari sini ke bawah adalah arsitektur. Diagramnya adalah seluruh sistem dalam satu pandangan: alat adalah data di bagian atas, engine di tengah tidak mengetahui apa pun tentang platform mana pun, shell di bawahnya mengimplementasikan satu kontrak, dan katalog memasok kontennya.
┌─────────────────────────────────────────────┐
│ Tools (data, not code) │
│ tool.json + template.html + hooks.js? │
└─────────────────────────────────────────────┘
▲
│ talks to via Capability Bridge v1
▼
┌─────────────────────────────────────────────┐
│ Engine │
│ loader · validator · runtime · template │
│ inputs · url-mode │
│ PLATFORM AGNOSTIC. Knows nothing of DOM, │
│ filesystem, or You. │
└─────────────────────────────────────────────┘
▲
│ implements HostV1
▼
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ Web Shell │ Tauri Desktop│ Tauri Mobile │ CLI Shell │
│ (PWA) │ │ │ │
└──────────────┴──────────────┴──────────────┴──────────────┘
▲
│ fetches from
▼
┌─────────────────────────────────────────────┐
│ Catalogs │
│ catalog/tools/index.json + tool dirs │
│ catalog/assets/index.json + asset files │
└─────────────────────────────────────────────┘Tata letak repositori
Lolly adalah satu repositori. engine/, schemas/, scripts/, tests/, api/, docs/, community/, brands/lolly-start/, setiap shells/ dan kedua services/ adalah direktori biasa di dalamnya. Satu-satunya pengecualian adalah brands/suse, sebuah submodul git privat yang menyimpan paket alat SUSE dan katalognya, bersifat opt-in dan tidak ada pada clone publik. Paket mana yang dibaca oleh build tertentu ditentukan oleh profil konten (profiles.json), yang diresolusi per proses, bukan dialihkan secara global. Lihat Build Guide » Getting the source untuk perintah clone dan cara sebuah perubahan di dalam paket privat dikomit.
lolly/
├── engine/ # Platform-agnostic core. Open source (MPL-2.0).
│ └── src/
│ ├── index.ts # public surface - loader, runtime, template, inputs, url-mode
│ ├── loader.ts # fetches and validates tool files
│ ├── runtime.ts # orchestrates the 5-step lifecycle
│ ├── template.ts # Handlebars hydration + annotateTemplate
│ ├── inputs.ts # manifest → runtime input model
│ ├── url-mode.ts # URL ↔ input state round-trip
│ ├── validate.ts # JSON Schema validation of manifests
│ ├── compose.ts # resolve nested tool renders (composes)
│ ├── embed.ts # parse portable lolly.tools embed URLs
│ └── bridge/
│ └── host-v1.ts # type re-export of the @lolly-tools/core contract
│
├── shells/
│ ├── web/ # PWA - hosted online; primary distribution
│ │ └── src/
│ │ ├── main.ts # boot, routing
│ │ ├── theme.ts # theme apply/persist (FOUC prevention)
│ │ ├── bridge/ # web implementations of HostV1 APIs
│ │ │ ├── index.ts # compose all bridge pieces
│ │ │ ├── db.ts # IndexedDB setup
│ │ │ ├── state.ts # host.state - saved edits
│ │ │ ├── profile.ts # host.profile - user details
│ │ │ ├── assets.ts # host.assets - catalog + user uploads
│ │ │ ├── clipboard.ts # host.clipboard
│ │ │ ├── export.ts # host.export - rasterise/serialize
│ │ │ ├── net.ts # host.net - allowlisted fetch
│ │ │ └── media.ts # host.media - live camera frames (onFrame)
│ │ ├── catalog/
│ │ │ └── sync.ts # boot-time catalog sync + offline cache
│ │ ├── styles/ # app-wide CSS (app.css, picker.css, tokens.css)
│ │ └── views/
│ │ ├── gallery.ts # tool library listing + saved-state cards
│ │ ├── tool.ts # mounts one tool (inputs + canvas + actions)
│ │ ├── picker.ts # asset picker UI (invoked by host.assets)
│ │ ├── profile.ts # user details editor
│ │ ├── projects.ts # /p - folders of saved sessions (nested; folder/selection export)
│ │ └── free-canvas.ts # free-canvas editor overlay for render.layout:"editor" tools
│ │
│ ├── cli/ # Node.js CLI - same engine, headless jsdom
│ │ ├── bin/lolly.ts
│ │ └── src/
│ │ ├── run.ts # loadTool → createRuntime → export → write file
│ │ └── bridge.ts # CLI implementation of HostV1
│ │
│ ├── tui/ # Interactive terminal shell (Ink) - reuses the CLI bridge
│ │ └── src/
│ │ ├── main.tsx # full-screen app: Gallery / Projects / Profile / ToolView
│ │ └── bridge.ts # CLI bridge + on-disk state under ~/.lolly
│ │
│ ├── tauri-desktop/ # downloadable desktop app
│ └── tauri-mobile/ # iOS/Android app
│
├── community/ # the brand-agnostic tool pack - data, not code. Public (MPL-2.0).
│ # A SELECTION follows; a profile mounts these plus whatever
│ # tools the active brand pack carries of its own.
│ ├── qr-code/
│ ├── snippet/
│ ├── countdown-timer/
│ ├── color-palette/
│ ├── street-map/ # offline vector city-block maps
│ ├── url-shot/ # "URL Screenshot" (capture capability)
│ ├── strip-data/ # on-device metadata strip - JPEG/PNG/SVG/PDF (file in → clean file out)
│ ├── compress-pdf/ # on-device PDF compressor - recompresses images (file in → smaller file out)
│ ├── chart/ # SVG charts from structured data
│ ├── filter/ # photo effects in one tool - halftone/scanline/posterize/voronoi (vector), duotone/pixel-stretch/imperfections (raster)
│ ├── meeting-planner/ # global timezone meeting scheduler
│ ├── calendar-ics/ # event → .ics calendar file plus a card
│ ├── wayfinding-signage/ # event signage; directions blocks auto-fit label text
│ ├── text-helper/ # on-device text workbench (format/decode/hash/de-identify)
│ ├── design/ # "Design" - freeform WYSIWYG editor canvas (render.layout: editor)
│ ├── multi-page-pdf/ # multi-page PDF document - cover, flowing content blocks, back page
│ ├── diagram-builder/ # org / layercake / process / cycle / pyramid diagrams
│ ├── logo-wall/ # many logos → auto-packed grid
│ ├── icon/ # favicon .ico / png / svg from text + colours
│ └── lottie-digi-ad/ # animated Lottie ad banners
│
├── brands/ # brand packs - a catalog each, and optionally tools of their own
│ ├── lolly-start/ # the blank starter brand, owned here
│ │ └── catalog/
│ │ ├── tools/index.json # tool registry, generated per brand
│ │ └── assets/
│ │ ├── index.json # asset registry
│ │ └── lolly/... # logo, palette, tokens
│ └── suse/ # PRIVATE submodule - the SUSE tools and the SUSE catalog
│
├── schemas/ # JSON Schema for tool.json, asset entries, AssetRef
├── scripts/ # build-catalog-index.ts, checksum-assets.ts, validate-catalog.ts
├── tests/ # engine tests
└── docs/ # this file + authoring guides + positioningModel pengiriman platform
Platform ini berjalan di berbagai permukaan - web PWA, Tauri desktop/mobile, CLI yang bisa diskrip dan TUI interaktif. Semuanya memakai engine yang sama dan file alat yang sama.
Web (PWA) - distribusi utama
Di-hosting di URL yang dikendalikan SUSE. Bekerja secara offline setelah service worker menyimpan cache alat dan aset. Di sinilah sebagian besar karyawan, vendor dan mitra akan memakai platform ini. Tidak perlu akun - status disimpan di IndexedDB per perangkat.
Shell web bersifat responsif dari satu tata letak. Di desktop, sebuah alat adalah sidebar kontrol yang dapat diubah ukurannya di samping panggung pratinjau dengan navigasi kanvas asli-trackpad (roda Cmd/Ctrl atau cubit untuk zoom di sekitar kursor, seret Space atau tombol tengah untuk pan, tombol 0/1/+/− dan HUD Fit/%). Di mobile (≤640px) kontrol menjadi sheet berlabuh di atas dengan grip seret yang mengunci ke peek/half/full (ketuk untuk beralih) di atas pratinjau layar penuh statis, dan tombol Render mengambang membuka kontrol Export di popup bottom-sheet. Sentuhan mendapat pinch-zoom dan drag-pan pada pratinjau. Jalur render dan kontrol ekspor identik di keduanya - hanya chrome-nya yang menyesuaikan.
signed by Lollyvector SVG131 paths~6.1k nodes158 groups1 image142 KBPeriksa sendiriAmbil file bertanda tangan
Tool yang sama pada lebar ponsel, tanpa layout kedua yang perlu dipelihara: kontrol menjadi sheet di bagian atas, preview memenuhi seluruh layar dan pill render mengambang di atasnya.
signed by Lollyvector SVG97 paths~3.3k nodes113 groups99 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG97 paths~3.3k nodes113 groups100 KBPeriksa sendiriAmbil file bertanda tangan
Mode batch (/pro). Web shell juga menyediakan grid batch bergaya spreadsheet (shells/web/src/pro/) yang me-render banyak baris sekaligus di satu atau banyak tool. Ia melakukan round-trip CSV/TSV plus tempel spreadsheet, template/format/ukuran/unit/dpi per baris, panel samping blocks-editor dengan preview langsung, kolom ekspor yang bisa dilipat, bar tag "relevance" per baris, susun ulang baris dengan drag-handle di kiri, konfirmasi hapus dua langkah, sesi batch tersimpan dan unduhan .zip. Inilah permukaan satu-ke-banyak di balik positioning "mass content generation".
Tauri desktop / mobile
Aplikasi native yang dikemas (footprint kecil via Tauri). Menyediakan ketersediaan offline penuh, akses filesystem untuk tool yang bergantung pada CLI (PDF Smasher, Font Outliner) dan akses kamera. Dijadwalkan untuk peningkatan tooling pertengahan 2026.
CLI
lolly <tool-id> [--input=value ...] --output=file.png
Pengguna desktop dapat menjalankan banyak tool dari terminal. CLI shell memuat engine yang sama, membuat DOM jsdom, menjalankan render path yang sama dan menulis file. URL mode adalah transportnya - CLI bukan implementasi terpisah. Ini menjamin output CLI dan GUI identik.
lolly qr-code --url=https://suse.com --output=qr.svg
lolly quotes --quote="Ship it." --output=quote.png
lolly # lists available tools
lolly qr-code # lists inputs for that toolTUI
pnpm run tui
Rekan interaktif dari CLI: aplikasi terminal full-screen yang mengutamakan keyboard (dibangun di atas Ink) untuk menjelajahi tool, mengisi input, menyimpan proyek dan mengekspor - semua tanpa GUI. Host bridge-nya menggunakan kembali implementasi CLI untuk format bebas-DOM (SVG/EMF/EPS/HTML + text/data), dan menambahkan state on-disk di bawah ~/.lolly plus preview inline opsional. Selain itu ia memiliki tier render browser: Chromium headless terbatas (yang sama dengan yang diinstal server MCP) yang menghasilkan raster/PDF/video dan capture URL langsung sesuai permintaan - menjalankan salinan web shell yang sudah dibuat sehingga output identik, dan hanya diluncurkan saat pertama kali Anda mengekspor format semacam itu. Jadi url-shot (dengan crop + recolor + vector PDF/SVG) dan setiap tool raster/pdf juga berjalan di terminal. Lihat panduan TUI.
Di permukaan mana pun Anda berada, tab Capabilities pada dashboard adalah peta lengkap dari apa yang dinyatakan mampu dilakukan platform, dikelompokkan dan mudah dibaca tanpa membuka satu tool pun.
Kategori tool
Tool diberi tag category di manifest-nya untuk pengelompokan galeri.
Baris didaftar sesuai urutan bagian galeri. Bagian utility selalu dirender terakhir di galeri (setelah setiap kategori lain, termasuk yang akan datang) - itulah laci "Offline Utilities" on-device.
| Kategori | Contoh | Direncanakan |
|---|---|---|
everyone | QR Code Generator, Quote Card, Email Signature, Logo, Wordmark, Audiogram, Battlecards, Sequence, Record | Employee Image Stationery |
designer | Brand Lockup, Design, Chart, Darkroom, Filter, Pose Geeko, Booklet | Font Outliner |
event | Meeting Planner, Event Name Badge, Wayfinding Signage, Calendar ICS, Booth Studio | Event Stationery, Bulk Name Badges, Room Agenda Cards |
product | - | CVE Alert, Product Release Announcement, Blog OG Image |
utility | Strip Hidden Data, Text, Compress PDF, Convert Image, Convert Font, Redact, Run Web Code, Screen Capture, URL Screenshot | Unit/format converters, more on-device privacy utilities |
Sel-sel tersebut adalah contoh, bukan inventaris. Tool apa saja yang ada adalah properti dari profil yang Anda pasang, bukan dari halaman ini: sebuah brand pack menambahkan miliknya sendiri, dan dapat mengecualikan tool community yang tidak ingin dikirimkannya. catalog/tools/index.json - dihasilkan dari manifest, dan registry yang sebenarnya dibaca galeri - adalah daftar otoritatif; untuk menghitung apa yang dipasang sebuah profil, hitung manifest-nya (ls community//tool.json brands//tools/*/tool.json) daripada mempercayai angka yang tertulis di sini. (Sebuah id tool yang ada di dua pack hanya terpasang sekali, dari pack yang menang.)
Tool juga diklasifikasikan menurut status: official (disetujui brand, tanpa watermark), community (kontribusi eksternal), experimental (ekspor berwatermark). Sebagian besar library berstatus official; studio yang lebih baru dan tool capture cenderung berada di community atau experimental selagi menetap. Setiap permukaan menampilkan badge, sehingga pembaca tahu apa yang mereka ambil sebelum membukanya - dan, seperti sel kategori di atas, keanggotaan per-status bergerak terlalu cepat untuk didaftar di sini. Baca dari galeri atau index yang dihasilkan.
Design adalah tool pertama yang dibangun di atas mode free-canvas render.layout: "editor" - permukaan direct-manipulation tanpa chrome tempat Anda menyeret, mengubah ukuran, memutar dan menempelkan (snap) kotak teks, bentuk dan gambar, lalu mengekspor melalui render path yang sama seperti setiap tool lainnya.
Strip Hidden Data adalah utilitas on-device pertama (privacy: "on-device"): alat transformasi konten yang mengambil berkas yang Anda berikan, memprosesnya sepenuhnya di browser dan mengembalikan salinan yang bersih - tidak pernah diunggah, tidak pernah diberi watermark, tidak ada provenance yang dicap. Text adalah yang kedua - ruang kerja on-device untuk pekerjaan sehari-hari yang biasa ditempel ke situs web (format JSON, decode JWT, Base64, encode/decode URL, hashing SHA). Compress PDF adalah yang ketiga - mengecilkan ukuran PDF dengan mengompresi ulang gambar di dalamnya, sekali lagi sepenuhnya on-device. Penanda dan teks lencananya "Runs on your device - nothing is uploaded" kini mencakup seluruh kumpulan transformasi: Strip Hidden Data, Text, Compress PDF, Convert Image (HEIC/TIFF/AVIF → WebP/JPG/PNG), Convert Font, Redact (menghancurkan area gambar, SVG atau PDF), Prompt Card dan Rebrand (mengubah tema .pptx di tempat) di mana profil memasangnya. Ini adalah kategori utilitas privasi yang menggantikan penyerahan berkas rahasia ke situs web bertujuan tunggal.
signed by Lollyvector SVG124 paths~29k nodes324 groups395 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG124 paths~29k nodes324 groups396 KBPeriksa sendiriAmbil file bertanda tangan
Catatan:
categorydanstatusdidenormalisasi kecatalog/tools/index.json(registri yang dibaca oleh galeri) dari setiaptool.json. Manifes adalah sumber kebenaran - indeks ini dihasilkan olehpnpm run build:catalogdanpnpm run validate:catalogakan menggagalkan CI jika indeks yang dikomit menyimpang dari manifes.
Komitmen arsitektural
Keputusan-keputusan ini sudah final. Mengubah salah satunya adalah upaya besar - keputusan ini membentuk setiap keputusan lain dalam codebase.
1. Tool deklaratif, dengan jalan keluar imperatif
Sebuah tool adalah manifest (tool.json) + template (template.html) + hooks.js opsional.
Manifest mendeklarasikan input. Bukan template. Input tidak disimpulkan dari token Handlebars. Manifest adalah kontraknya; template mengonsumsi variabel bernama melalui {{id}}.
signed by Lollyvector SVG39 paths~2.6k nodes54 groups2 images43 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG39 paths~2.6k nodes54 groups2 images43 KBPeriksa sendiriAmbil file bertanda tangan
Hooks bersifat opsional. Sebagian besar tool sepenuhnya deklaratif - manifest + template sudah cukup. Tool yang membutuhkan nilai terhitung (encoding QR, pembentukan data chart) menyediakan hooks.js yang mengekspos fungsi lifecycle bernama (onInit, onInput, onFrame - hook live-camera per-frame untuk tool motion-reactive - onLevel, beforeExport, afterExport, exportFile - jalur transformasi file-in/file-out yang digunakan utilitas on-device seperti Strip Hidden Data - dan exportStill, untuk tool yang memiliki raster mendalamnya sendiri). Host memuat hooks melalui new Function('host', …) dengan capability bridge disuntikkan sebagai closure scope. Ini adalah kontrak portabilitas, bukan sandbox keamanan: hooks tetap berjalan dalam realm halaman dan dapat menjangkau window/fetch/document di browser shell - host. adalah permukaan portabel yang didukung, bukan batas yang dipaksakan. Hasil hook async dibatasi waktu (onInit 5s, onInput 2s, beforeExport/afterExport 5s, exportFile/exportStill 10s) dan hasil yang terlambat dibuang; hook sinkron* yang lepas kendali tidak dapat dihentikan paksa. Karena itu, kode hook pihak ketiga yang tidak tepercaya belum aman dijalankan sampai isolasi Worker hadir.
Ini penting karena: tool deklaratif dapat dibuat oleh non-developer. Jika setiap tool adalah aplikasi web, catatan risiko "keterbatasan skill untuk membuat/memelihara template workhorse" menjadi bottleneck permanen.
2. Tool dan asset adalah data, bukan kode yang dibundel
Aplikasi web dan Tauri mengambil katalog tool dan asset dari URL yang diketahui saat boot, menyimpannya secara lokal (cache) dan beroperasi dengan apa pun yang ada di sana. Menambahkan tile event baru atau asset musiman tidak memerlukan rilis aplikasi.
Byte asset di-checksum dengan SHA-256 untuk mencegah CDN poisoning. id + version asset menggerakkan invalidasi cache.
3. Capability Bridge adalah satu-satunya API yang dilihat tool
Tool tidak pernah menyentuh DOM di luar area template-nya, tidak pernah memanggil fetch secara langsung, tidak pernah membaca filesystem. Mereka memanggil metode host.* yang berversi. Definisi kanonis kontraknya adalah packages/core/src/host-v1.ts - SDK tool-author @lolly-tools/core, sehingga pihak ketiga dapat membangun di atasnya tanpa bergantung pada engine; engine/src/bridge/host-v1.ts adalah re-export tipe darinya, dan kode engine/shell tetap mengimpor dari path tersebut tanpa perubahan:
| Bridge API | Apa yang dilakukannya |
|---|---|
host.profile | Nama depan, email, headshot, kota pengguna, dll. Mengisi input di awal via bindToProfile. |
host.assets | Query katalog, resolusi asset, UI picker yang disediakan host. |
host.state | Simpan / muat slot input. IndexedDB di web, filesystem di Tauri, memory di CLI. |
host.clipboard | Menulis teks atau gambar ke clipboard (dengan fallback platform). |
host.export | Merasterisasi atau menserialisasi target render. Menerapkan watermark untuk tool experimental. |
host.net | Fetch yang di-allowlist - hanya tersedia jika tool mendeklarasikan capability "network". (Belum ada tool yang dirilis menggunakannya saat ini.) |
Permukaan opsional yang bersifat aditif hanya muncul saat shell menyediakannya. Sebagian bersifat capability-gated - hanya diekspos saat tool mendeklarasikan flag yang sesuai: host.compose (menyematkan render tool lain - compose), host.capture (capture halaman untuk URL Screenshot - capture) dan host.recorder (capture mic/kamera/display untuk tool recording - microphone / camera / screen). Sisanya bersifat feature-detected - hadir kapan pun shell dapat menyediakannya, dengan tool tetap memiliki fallback untuk shell yang tidak bisa.
Beberapa permukaan utama, untuk menunjukkan cakupannya - Host API mendokumentasikan setiap satu, dan packages/core/src/host-v1.ts adalah kontraknya sendiri:
| Surface | Sejak | Apa yang ditambahkannya |
|---|---|---|
host.tokens | 1.0 | Token desain DTCG - primitif milik brand sendiri |
host.text | 1.0 | Text-to-path lewat HarfBuzz WASM (kapabilitas wasm menandai alat yang bergantung padanya) |
host.media | 1.4 | Frame kamera live yang menggerakkan hook onFrame. Progressive enhancement, sengaja tidak di-gate oleh flag camera - alat semacam itu tetap berfungsi sebagai alat still-image biasa |
host.color | 1.40 | Matematika warna perseptual: ΔEOK, kontras WCAG + APCA, ramp OKLab, class-break, palet kategorikal, skema harmoni (1.60), pencampuran CSS Color 4 dan gradient baking (1.68). Murni dan sinkron - shell menyambungkan makeColorApi() milik engine, bukan mengimplementasikan apa pun sendiri, jadi tidak bisa melenceng |
host.images | 1.60 | Decode / resize / re-encode byte di perangkat - jalur konversi (HEIC → JPEG, kompres ke WebP, downscale). Dikirim di web shell sebagai lazy facade, jadi decoder HEIC tidak pernah masuk ke boot chunk |
host.geom | 1.64 | Geometri vektor presisi: boolean path, offsetting, stroke-to-fill, spline lowering, penyederhanaan, hit testing. Juga murni, sinkron dan tersambung dari engine (makeGeomApi()); kegagalan dikembalikan, tidak pernah di-throw |
Sisanya mengikuti aturan yang sama dan didokumentasikan bersamanya: pdf (1.8) dan pptx (1.58) untuk operasi dokumen on-device, audio (1.71) dan speech (1.96) untuk analisis klip dan TTS/transkripsi on-device, viz (1.72) untuk kontrak placeholder MilkDrop, codec (1.100) dan layers (1.102) untuk output deep-bit dan layered-bitmap, upscale (1.101) dan matte (1.103) untuk model on-device, raster (1.105) untuk hook yang melakukan pekerjaan pixel sendiri, connectors (1.106) untuk panah yang aman diekspor dan c2pa (1.85) untuk menandatangani byte yang sudah jadi. Jumlahnya bertambah; aturannya tidak.
Capability yang dapat dideklarasikan adalah: network, filesystem, clipboard, camera, microphone, screen, ffmpeg, wasm, capture, compose. (screen, ditambahkan di 1.54, adalah capture display via host.recorder - pengguna memilih layar/window/tab di UI native browser; berbeda dari capture, yang merasterisasi URL yang ditentukan tool itu sendiri.)
Tool yang sama berjalan di browser, Tauri dan CLI headless karena setiap shell mengimplementasikan interface ini - tool tidak pernah tahu ia berada di mana.
Bridge ini berversi. Menambahkan metode adalah minor version. Menghapus atau mengubah signature adalah major version bump. Saat v2 dirilis, v1 harus tetap berfungsi.
4. ID asset berlaku selamanya
suse/logo/primary adalah kontrak. Setelah dipublikasikan:
- ID tidak pernah berubah, tidak pernah digunakan ulang.
- Perubahan byte → naikkan
versiondi manifest. - Digantikan oleh asset baru → set
deprecated: truedan opsionalreplacedBy. - Referensi yang sudah ada selalu ter-resolve.
Ini membuat state tool tersimpan dan link yang dibagikan via URL tahan lama selama bertahun-tahun.
5. URL mode bersifat first-class
Setiap input harus dapat diekspresikan sebagai parameter URL:
lolly.tools/#/tool/qr-code?url=https://suse.com&ecl=H signed by Lollyvector SVG55 paths~2.6k nodes38 groups60 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG55 paths~2.6k nodes38 groups61 KBPeriksa sendiriAmbil file bertanda tangan
Mode CLI adalah URL mode dengan transport yang berbeda - CLI shell membangun objek URL-state dari argv dan menjalankan pipeline engine yang sama. Hanya ada satu render path. CLI tidak bisa menyimpang dari GUI karena ia bukan implementasi terpisah.
url-mode.ts menangani round-trip (parse dan serialize). Sekumpulan parameter reserved tidak pernah diteruskan ke tool sebagai input: kontrol output (format, export, copy, filename, width/w, height/h, unit, dpi), dial print dan provenance (bleed, marks, profile, password, c2pa, imprint, durable, meta, hdr, depth, cuts) dan pembawa state (template, z - token terpaket "Shortest link" - dan zx, versi terenkripsi dengan password yang sama). Set RESERVED di engine/src/url-mode.ts adalah otoritasnya dan dipatok oleh sebuah test; URL Mode mendokumentasikan setiap satu darinya, termasuk beberapa yang tidak tercantum di sini. Input asset dalam URL mode diserialisasi menurut id-nya; runtime me-resolve-nya via host.assets.get() sebelum hidrasi. width/height adalah nilai dalam unit (default px, juga mm/cm/in/pt/pc); dengan unit fisik, dpi menetapkan resolusi raster. Keduanya menetapkan ukuran dokumen canvas dan mengisi di awal panel dimensi ekspor.
Karena setiap input berpindah dalam link, perubahan parameter berarti asset jadi yang berbeda. Seluruh palet ini adalah satu warna seed, satu harmoni dan satu jumlah step:
signed by Lollyvector SVG10 groups25 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG10 groups25 KBPeriksa sendiriAmbil file bertanda tangan
6. Penyimpanan lewat bridge, bukan langsung
Web shell: IndexedDB. Tauri: filesystem. CLI: in-memory. Tools hanya melihat host.state.save(slot, data) dan host.state.load(slot). localStorage tidak digunakan - terlalu kecil dan tidak bisa menyimpan blob.
Pengguna dapat menyimpan beberapa slot edit bernama per tool dan kembali ke tiap sesi nanti. Tidak perlu membuat akun; state bersifat per perangkat. Karena bridge adalah satu-satunya titik sambung, state per perangkat itu juga portabel: shells/web/src/data-transfer.ts membaca kembali semuanya lewat host.profile/host.state/host.assets menjadi satu zip lolly-backup yang bisa diimpor di instalasi lain - jawaban offline untuk "pindah ke perangkat baru" yang tidak butuh server (spesifikasi lengkap: docs/data-transfer.md). Sinkronisasi multi-perangkat sudah berjalan di atas mekanisme ini, mengirim bundel yang sama ke penyimpanan pilihan pengguna (docs/sync.md).
7. Tag maturity menyatakan apa itu sebuah tool
Setiap tool mendeklarasikan status: official | community | experimental dalam manifesnya. Galeri diurutkan berdasarkan status. Tool experimental otomatis membubuhkan watermark pada ekspornya - watermark diterapkan oleh host.export.render, bukan oleh tool, sehingga tidak bisa dinonaktifkan oleh penulis tool non-official.
Ini adalah jawaban struktural atas risiko persepsi bahwa setiap tool di galeri membawa bobot yang sama. Proses apa pun yang diterapkan sebuah tim di sekitar katalog melapis di atasnya.
8. Input tool ditipekan lewat manifes, termasuk aset
Input mendeklarasikan type: text, longtext, number, boolean, color, select, asset, date, time, datetime-local, url, blocks, vector, table dan file. Host merender kontrol generik per tipe dari manifes - tool tidak menulis kode kontrol sama sekali. (Pra-isi dari profil pengguna bukan tipe - input apa pun bisa membawa bindToProfile.) Tiga di antaranya membawa bobot lebih dari yang lain:
asset(denganfilterdanallowUpload) adalah jembatan ke sistem aset global;allowUpload: falseadalah tuas penegakan brand untuk hal seperti logo ubin sponsor yang hanya boleh berupa aset pustaka. Unggahan pengguna memakai bentukAssetRefyang sama dengan aset pustaka, jadi tool memperlakukannya secara identik.blocksadalah grup field berulang - mini-tabel di dalam satu input, diedit di panel samping, dengan menu tambah yang bertipe/terdiskriminasi dan field aset per blok. Mengklik blok yang dirender di kanvas memfokuskan baris blok itu. Dipakai olehmeeting-planner,chart-creator,event-name-badge,wayfinding-signage,color-blockdandigi-ad.vectormengelompokkan sekumpulan angka tetap (misalnya sebuah transform) menjadi satu kontrol majemuk;filemenyimpan file milik pengguna sendiri sebagai byte di memori untuk utilitas transformasi on-device (misalnyastrip-datadancompress-pdf).
9. Template tanpa logika (Handlebars, bukan EJS)
Handlebars dipilih dibanding EJS secara sengaja:
- Tanpa logika. Template bisa ditulis oleh non-developer.
- Aman secara default.
{{x}}melakukan HTML-escape;{{{x}}}bersifat raw opt-in. - Tidak ada JS bebas dalam template berarti tidak ada permukaan audit XSS per template.
Logika berada di hooks.js tempat ia eksplisit dan bisa direview. Helper Handlebars yang tersedia: {{default}}, {{upper}}, {{lower}}, {{eq}}, {{markdown}}, {{asset ref}}, {{asset ref "property"}} (ditambah helper format data icsStamp/rfcText/csvCell yang dipakai oleh template .ics/.vcf/.csv sejenis).
10. Tool menyusun tool
Satu tool bisa menyematkan render tool lain tanpa impor antar-tool - komposisi diselesaikan oleh engine, tidak pernah oleh kode tool. Ada dua permukaan:
- Manifes deklaratif -
composes: [{ id, tool, inputs, format?, width?, height? }]. Engine merender anak yang disebutkan dan menempatkan hasilnya di template tanpa logika sebagai{{asset <id>}}.event-name-badgemenyusunqr-codesebagai SVG saat ini. - URL sematan portabel -
<img src="https://lolly.tools/tool/<id>.<ext>?<inputs>">. Shell merender anak itu secara lokal (piksel placeholder tampil sampai render lokal selesai); tidak ada yang pernah diambil darilolly.tools.
Menyusun render tool apa pun: anak SVG tetap menjadi vektor sejati saat induk diekspor ke SVG atau PDF, dan dirasterisasi dengan tajam untuk PNG; anak PNG/JPG/WEBP disematkan sebagai gambar. Memerlukan kapabilitas compose. Anak hasil komposisi adalah perantara - tidak pernah diberi watermark atau cap provenans - dan komposisi terdegradasi secara wajar: shell yang tidak bisa merender anak cukup mengosongkan slotnya dan induk tetap dirender.
Apa yang secara sengaja tidak kami lakukan
- Tanpa EJS / tanpa JS arbitrer dalam template. Permukaan XSS-nya nol. Logika berada di
hooks.js. - Tanpa CMS aset wajib. Setiap individu mengingest berkas kreatif mereka sendiri langsung ke Aset di dalam aplikasi (Aset dan Brand Studio) - tanpa server, tanpa konsol admin. Pekerjaan diteruskan sebagai sebuah session: sebuah tautan share membawa input dan pengaturannya (berkas yang diunggah berpindah dalam sebuah
.lolly), dan session yang sama berpindah dalam sebuah backup atau melalui sebuah sesi kolaborasi. Siapa pun yang mengontrol deployment kemudian dapat mengunci sebuah session bersama sebagai sebuah template - buka tautannya, catat nilai-nilainya sebagai sebuah entri template di direktori alat tersebut dalam brand pack, lalu commit - setelah itu template tersebut muncul di pemilih "New from template" pada alat itu dan dapat di-deep-link sebagai?template=<id>. Git adalah langkah penguncian milik pemilik deployment, bukan milik pembuatnya. Untuk sebuah katalog yang dibagikan dan diatur (governed), sebuah organisasi dapat mengelola direktori aset dengan cara yang sama dan menjaga pembaruan melalui review PR - sebuah model governance yang tersedia, bukan sebuah keharusan dari aplikasi. - Tanpa RBAC yang dipaksakan. Aplikasi terbuka ini bersifat public-access secara default; risiko brand dikelola melalui tag maturity + watermark. Sebuah organisasi yang menginginkan kontrol lebih ketat melapiskan auth-nya sendiri dan katalog yang di-review lewat git di atas.
- Tanpa database terpusat. Semua state pengguna bersifat per perangkat; sync opsional menyalinnya ke penyimpanan pilihan pengguna, tidak pernah ke database Lolly.
- Tanpa jalur kode tools/engine bersama. Engine ini open source, begitu pula alat-alat brand-agnostic di
community/; sebuah brand pack sepertibrands/suse/yang privat membawa alat dan katalognya sendiri dengan persyaratannya sendiri. Bagaimanapun juga, pemisahan ini ditegakkan (tanpa cross-import dariengine/ke konten alat) sehingga pemisahannya tetap bersih.
Siklus hidup satu render
Seorang pengguna membuka lolly.tools/#/tool/qr-code?url=https://suse.com&ecl=H:
- Boot. Web shell membuka IndexedDB, membangun capability bridge, menyinkronkan katalog alat dan aset (atau memuat dari cache saat offline).
- Route. URL hash → tampilan
tool, denganqr-codedan parameter URL diekstraksi. - Load.
loadTool('qr-code', fetchFile)mengambiltool.json, memvalidasinya terhadap JSON Schema, mengambil sumbertemplate.html,styles.cssdanhooks.js. - Parse URL state.
parseUrlStatemenerjemahkan parameter URL menjadi nilai input awal. Referensi aset (?logo=suse/logo/primary) diuraikan sebagai objek ringan{ id, _unresolved: true }. - Runtime.
createRuntime(tool, host, initialValues)membangun model input (menggabungkan data profil, nilai default dan nilai awal), meresolusi referensi aset melaluihost.assets.get(), memuat hooks (hostdengan closure-scoped, bukan disandbox), memanggilhooks.onInit. - Render. Shell berlangganan ke runtime; pada setiap perubahan state ia menerima
{ model, hydrated }. Ia merender kontrol input dari model dan menulis HTML template yang telah dihidrasi ke#tool-canvas. - Interact. Pengguna mengetik pada sebuah input →
runtime.setInput(id, value)→ constraint diterapkan →hooks.onInputdipanggil → hidrasi ulang → render ulang. Kanvas diperbarui secara langsung. - Export. Pengguna mengklik Download(PNG) →
runtime.export(canvasNode, 'png')→host.export.render(merasterisasi melalui dom-to-image-more; SVG/PDF melalui vectoriser khusus yang menelusuri DOM) → blob →host.export.download. Rentang format yang dapat dipilih sebuah alat cukup luas, dan enumrender.formatsdischemas/tool.schema.jsonadalah otoritas untuk itu - raster dan raster mengambang, vektor dan berkas potong, cetak/CMYK, gerak, dokumen yang dapat diedit (pptx,docx,odt), palet dan keluaran data/teks, berkas audio dan font. URL Mode menyebutkan setiap id dan apa yang dihasilkannya. Audio ada dalam enum tersebut seperti yang lain (wav,mp3,m4a,opus, dideklarasikan oleh audiogram dan alat perekaman); secara terpisah, moderender.capturesebuah alat perekaman menjalankanhost.recorder, yang hasil rekamannya tiba sebagai Blob jadi dalam wadah apa pun yang direkam oleh browser. (Alat yang menyetelrender.export: false- misalnya Color Palette, Countdown Timer, Strip Hidden Data, Text, Compress PDF - menyembunyikan kontrol download/format/dimensi.) Unit fisik dikonversi per format di sini (PDF → titik halaman sebenarnya, raster → piksel pada DPI dengan chunkpHYs). Metadata kepenulisan/provenance (author, tool, source - dibangun olehengine/src/metadata.ts) disematkan per format: PNG iTXt, JPEG EXIF, dictionary info PDF,<metadata>SVG, komentar GIF. Alat eksperimental mendapatkan watermark yang disisipkan oleh host, bukan oleh alat itu sendiri.
signed by Lollyvector SVG77 paths~6.0k nodes87 groups3 images88 KBPeriksa sendiriAmbil file bertanda tangan
signed by Lollyvector SVG77 paths~6.0k nodes87 groups3 images88 KBPeriksa sendiriAmbil file bertanda tangan
Siklus hidup yang sama di Tauri. Siklus hidup yang sama di CLI - jsdom menyediakan DOM headless; keluaran menuju file atau stdout.
Status open source
Kode berlisensi MPL-2.0. engine/, shells/, services/, schemas/ dan docs/*.ts adalah open source di bawah MPL-2.0 - platform scaffolding netral vendor untuk tooling brand, semuanya dalam satu repositori publik, lolly-tools/lolly.
Konten alat dikirim sebagai paket brand (brand pack), masing-masing dengan ketentuannya sendiri (lihat NOTICE.md paket tersebut). community/ adalah direktori dari repositori ini dan alat-alatnya yang agnostik terhadap brand juga berlisensi MPL-2.0. brands/suse/ adalah paket privat suse-lolly, satu-satunya submodul: alat SUSE dan katalog SUSE, milik eksklusif SUSE, termasuk musik PremiumBeat yang dilisensikannya. brands/lolly-start/ adalah brand starter kosong yang dimiliki oleh repositori ini. Font dikirim di dalam sebuah paket di bawah SIL Open Font License 1.1 - paket SUSE membawa typeface SUSE dan SUSE Mono.
Tidak ada direktori tools/ atau catalog/ di root repositori. packages/node-shell/src/content-roots.ts menjawab "di mana alat <id> berada" dan "di mana letak katalog" dari profiles.json pada saat pembacaan, sehingga sebuah profil adalah jawaban per proses dan tidak ada pohon direktori yang perlu dirakit terlebih dahulu. Pasangan tools/ + catalog/ yang sebenarnya hanya ditulis ke dalam output build - dist/, payload RPM, image container - karena browser mengambil kedua jalur tersebut melalui HTTP.
Pemisahan ini ditegakkan - tidak ada cross-import dari engine/ ke konten alat - sehingga batas antara platform dan konten tetap bersih.
Di mana engine berakhir dan host dimulai
Jika bisa dideskripsikan dalam data murni + Handlebars → engine. Jika menyentuh DOM, filesystem, jaringan atau API browser/OS apa pun → host.
Garis batas ini tajam dengan sengaja. Engine adalah bagian open source. Segala sesuatu yang mengetahui tentang SUSE, platform tertentu atau lingkungan runtime tetap di luarnya.
Untuk level detail berikutnya, engine/README.md mencantumkan setiap modul engine dan apa tanggung jawabnya, dan Threat Model & Trust Boundaries mencatat di mana garis yang sama itu sekaligus menjadi batas kepercayaan.