{"_id":"claude-artifact-framework","_rev":"39-93b5a3213468628ca9c333f307358154","name":"claude-artifact-framework","dist-tags":{"latest":"0.22.1"},"versions":{"0.1.0":{"name":"claude-artifact-framework","version":"0.1.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.1.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"7871586e65789fa29a1e53f2e62421cfa6aa3e7c","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.1.0.tgz","fileCount":8,"integrity":"sha512-SADFGtp4CEmngQgPCMU60mnagnNSfc2aFrK0iJ7uwVMEduRjwoxiCrGbBioYx9zSPxib1VoAj+xC8aFFEVnFCA==","signatures":[{"sig":"MEUCIEgtg+1LvoNzSTjpjS8AaFECl/d/t2TKeCjCdXaXHu4hAiEA5qTshM6EXTIhK0XOp0F4x7sTYZ8cuKtRxpXcAk+c3Fs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16398},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"d3d2e8a40443dbca3ba19eb7388bbcb8ee6e83bc","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.1.0_1784779579215_0.30716076195335296","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"claude-artifact-framework","version":"0.2.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.2.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"23dfc7f7930f6010ddc4ce98548222024260ae3b","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.2.0.tgz","fileCount":9,"integrity":"sha512-5QXq5n4o4DYezyNMsVqzKx/lbMgPbsaoGktMIgYXo+5S6J1wvsD76nIETPeJmQ20DJtIjxT6p8cb2ssvrv7NEQ==","signatures":[{"sig":"MEUCIQCbHzbsaPkNA6rd/hinvMAib/IyS3/RtiT74E8RwJHaPwIgaRC0uarUYff6j2KUpKdIVOQ8yjaHQMyI2i6InroQoCE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30034},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"ee567d04de6b665145cdc5814120f2d0e03c983f","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.2.0_1784781081795_0.9898277787753074","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"claude-artifact-framework","version":"0.2.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.2.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"2723acb6c60535d086db375addc3b5c41ff39af3","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.2.1.tgz","fileCount":10,"integrity":"sha512-6x9H7oXA2eECIZRmdcwF0X0qFJsZT8EkhljXOlKdJFplJF5vUD+XWK6NFIO5ys3mTyGRvbmXObEOC19bzM0a3w==","signatures":[{"sig":"MEUCIQDeETZYl6i4s3xrUAj9ahOTkFN8i07wljCFd0wpLH4RFAIgWcvqT1ilK8X/rAiTvW/lOjj1+dNevP9pnYQIkapp5NA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33098},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"a96b46ce3ec7ae54a0068c62043dbcf3a946720f","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.2.1_1784817425933_0.4082141183730388","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"claude-artifact-framework","version":"0.3.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.3.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"5d7337a005d2e3d2951b8d5c3d987e96774d2367","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.3.0.tgz","fileCount":16,"integrity":"sha512-SjfIhNBLRbI8ug2ZdsCsPc2BlQq54GAkkagnVoN4Nt3k2SC+u7XOI0/ZCwKPlwYUttPSkbfP3JRyyzf3IyvRTg==","signatures":[{"sig":"MEQCIDCMIDdNZ+/74NDpvruSCPTARmiaw2YkxqinsAx0/a1lAiBj/amU0CWPRy8DnxAAH3IOSHgJ18HDJQylKKwiLAHSRg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":233516},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"a498666457394d087038a7027ca8ee7fb7720b0f","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.3.0_1784940415710_0.24373178092652048","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"claude-artifact-framework","version":"0.4.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.4.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"906ee80b0080a3c74a284d71e6ebc618186ae130","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.4.0.tgz","fileCount":17,"integrity":"sha512-ZNaIoNDE4ZY6cWA4groH0uVIqYFJsxFQUsUExov9cR7mGbHrkwmqBaRSQsLZFHvn7o2jnn2RLTuSFcrD6JlMMQ==","signatures":[{"sig":"MEYCIQCAhFe/BjqViKTARx8HnVO/qdbUwUau672wgycV4sHuIAIhAIEGZT9uthID9bwesfPS1WjvyvqOSIzZ+MLnmWINBrWg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":322040},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"7b93d015cd8ea7b8f3f2eedf5058e9810c6b8960","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.4.0_1784950769030_0.0942408686097469","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"claude-artifact-framework","version":"0.5.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.5.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"a8e4a4c8d04af9a27f69a8a24a684b79b1cb006b","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.5.0.tgz","fileCount":18,"integrity":"sha512-o5LHGTEJzzpKM7mzai+3bicKh1iqvtmb9Zn55ow3HqrTC0YpBUeIt6XL/Blrv4ySftoZpzzPl5tpdq7aDNnmrg==","signatures":[{"sig":"MEUCIGY3dhoZCJFkYWy1QQ04xsVdBF8lspe8fP3ypt69LYgRAiEAhnWEbHPIp2xOSW5fnceZtJdiSTDBVB5EUfoujt7Lv8g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":417196},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"b2e1155af00fec3d8e04b447ff46de8d50e768db","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.5.0_1784955672048_0.6161228352444375","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"claude-artifact-framework","version":"0.5.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.5.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"ff296e95769f10d55e50b01570a5f87e64536cbc","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.5.1.tgz","fileCount":18,"integrity":"sha512-od+NfzZR3YVpEo4Jx0COjRb1mmSMpcNsu9BXUdeDScfvFYOp6XoNTcwlLY1QY3UTX2irl4SxAfwfynjdlbiefg==","signatures":[{"sig":"MEYCIQCc8g9zXjMIIuUE6sL+zIfVBWzPfsxLjb9mAPfFno6J/wIhANX7voqSbHL6j+ViG63ous37H24q1BpYVkB56n52mjcn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":427677},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"822e77d5c6db4234fff4d5733322ee3a5f920159","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.5.1_1784956525729_0.4994629763017855","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"name":"claude-artifact-framework","version":"0.5.2","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.5.2","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"193ae215abdeacfcccb772da84d963b887390540","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.5.2.tgz","fileCount":18,"integrity":"sha512-nlEQifVQ7YvOPco6blLoWLQY4pshguvWTrgqPRZlwUdBXg3tSRtmJMEJgr9nAjJp9VMSRgUi0vjTlVUVymU3fA==","signatures":[{"sig":"MEUCIQDqi0Lzm4B4EUBXE6HVDmqwXzO68b6QnQ2IYQUFS7x/RwIgMr71QC5io7dHMiHpNJgL3fPhxwgU8cZ3O68vhIsa5Zo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":429784},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"becffac129250a90ccef6900e6b8a84fc15c1c4e","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.5.2_1784956900092_0.9666560897783985","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"claude-artifact-framework","version":"0.6.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.6.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"f3a6848d9917bf543261e58bd6efbde38593f432","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.6.0.tgz","fileCount":18,"integrity":"sha512-KEUZ1px5WCTIIlmiFQqeH+9ZO0jYQWgxpvLQTOMtYZA6wErxCl9EsdHfJIX4Zb183KcdYNeA/k07mo1FYkVwSg==","signatures":[{"sig":"MEYCIQCLpVdHlFigKGK3aP2+YSd1uta+7qPZfryKZ8pLu0xBRgIhAPUuYTQUf9nESNmbUbwDB5V6rPM/XjZuF0vG1Cv0wOAz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":483265},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"7677f23061e25e80f32723f5ff973aef267e38ee","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.6.0_1784957528430_0.38749160809561745","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"claude-artifact-framework","version":"0.7.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.7.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"3a1c5c190e38b52af037cd4017f89024a84040a3","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.7.0.tgz","fileCount":18,"integrity":"sha512-zi4imolaIiq/0jzKcSLsbm3bShfciGAfiYPaWOCpN7PV/b4IMFwD/5llDVe/3CXgltWl9ZAOMc9XWYYyo07IMQ==","signatures":[{"sig":"MEUCIH5vZXcrOtZGRdZyGrNQs6uBgF9E4BEqInt9R5kgy5wKAiEAm7nJ485ZLM8nW7nDtHgLQ0yyxDHnCjmY7B1oJpfO2c0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":489332},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"b6babfc38c2dea4929d01b471b266fed647654c4","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.7.0_1784980740886_0.588707606386996","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"name":"claude-artifact-framework","version":"0.7.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.7.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"a6f4d528b85ae8e5ba6cd968a6a0945752ae689b","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.7.1.tgz","fileCount":18,"integrity":"sha512-RSngcioElwSX6UEdrlO1+jZ6N/z/WsucNPIBUqAzE+FF/Ol4gb2Wn0rJgVSPSwH+1vQSndMmToH4quy9x2968g==","signatures":[{"sig":"MEUCIQCsV9NdVM5e6vyVq4ybGAZnSH3c172geTZTlORWzz4YtQIgRCtmdBs+I0DG9NCO/6VN7jLxFJ8x/nj+s8B4GaRyhCk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":506409},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"2e4521c7d6533c4dc7cbae4cb2af324ecd8bd847","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.7.1_1784985416840_0.5465768449678907","host":"s3://npm-registry-packages-npm-production"}},"0.7.2":{"name":"claude-artifact-framework","version":"0.7.2","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.7.2","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"38f6307975f78bb87376cdb83c67b5171c1eeeee","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.7.2.tgz","fileCount":18,"integrity":"sha512-O5MxcdeezURt0a12PAqrTNZyw+YSqzhB7iqtyQLa90koRhek0amqIgpiolAQO/LkmRDgY4UIf4cSnEwBiw7Zqg==","signatures":[{"sig":"MEUCIAxM32xpTAII6SdEx/75cmlxVJwgrscGsqjhUvFPLDpmAiEAnmOge6dNYRB61zIiPpB+VFeMeS9t2Xl0D/HmcEGbtq4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":537145},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"d26fce6c4ec3c1ea9876dc2f595f9663d9a87b80","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.7.2_1784989085003_0.9378200916561521","host":"s3://npm-registry-packages-npm-production"}},"0.7.3":{"name":"claude-artifact-framework","version":"0.7.3","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.7.3","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"6078de4b4f88d39cf6d57c2a60db7c3b643d3be5","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.7.3.tgz","fileCount":18,"integrity":"sha512-5g7Rd0j7ishKxzru/47Fsxp9OiTTson84zGjk+YDU1hHo8mGmTks7gn5L0RACjZ9OTvwIwnbwTJAtgoHRmqwcA==","signatures":[{"sig":"MEUCIDg/tRahqpDdNO+HDTyLrgIeMmsT0hMPlyonVBMDktlwAiEA9bOLSrisd10Sf+OLWErRxziX6W/q0H/8XvtWxwIxFtg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":538191},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"41cfabed4d5bb20e218ee39e18dfb28cb6355399","scripts":{"build":"node scripts/build.mjs","release":"bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.7.3_1784989329396_0.0306359590145151","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"claude-artifact-framework","version":"0.8.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.8.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"791c5984728d1774728d88a97dc65dbff6eebaf9","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.8.0.tgz","fileCount":18,"integrity":"sha512-C8NW5N7cmQiSxuAgV2r7y8oF7f3eRN3ZrHURoV2pu4qlQy5faX9hGlngC63/SX4LpQ6KX7bh576LHSYt1n0KcQ==","signatures":[{"sig":"MEYCIQCiVl/E5MdqFwnX71bcNUg7vG1tDQdRXo41F5gE83wjsQIhANcOs2w6Yr2d2Sa0DacTkVGkFwtY23E2ujURrjvc6nwE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":567291},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"5904359b47bb708db597f833bfb6def915d63a9b","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.8.0_1784989960176_0.7067447118912404","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"claude-artifact-framework","version":"0.8.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.8.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"8e3b422659cf4ede8808fd210b7aba1fe3d9f6fb","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.8.1.tgz","fileCount":18,"integrity":"sha512-yV0AMGJ3E7Epf/tFEWJA9ROu1qTkSyILCwrEmlvzyRHy3KPZRaV0oXnIW2WD2WT8e3n25fYdFWP3tcskq+Nhbg==","signatures":[{"sig":"MEUCIB3pNCpjCf6+SvKb+pKQ4SS4vRs4ExUkzyzhgaRdN9wpAiEAqepqSsWraO6qMZoFFELGgvBjX8V34a4G4rGFOnM3hHY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":569430},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"2dea2175b4b1c9bb3ad5cc5a7dac6cbb5d62227f","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.8.1_1784991190191_0.4491670906288181","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"claude-artifact-framework","version":"0.9.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.9.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"a0aafe0c9267c86dbb3d6a756b027c6db2f6d013","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.9.0.tgz","fileCount":18,"integrity":"sha512-ouhrSlbg+aJabdFDYWXEiNzQOsJXc/kUIZhyMhJNA2lNnp/qdqFHLHxI5RzIBdCK5rY+veHkglira4M+himCQQ==","signatures":[{"sig":"MEYCIQDwqPzyG3CIeckMkLqjdsDmHiSe+eVNr93UEXTI2cmMegIhALmPBg3Cf0H55yIVEaW77m2rD3mvR3/bMNFX4HZcLEJ5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":584787},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"0c105ede8c7192733949d03a0464511ad2338ece","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.9.0_1784995950407_0.6449833892747936","host":"s3://npm-registry-packages-npm-production"}},"0.9.1":{"name":"claude-artifact-framework","version":"0.9.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.9.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"3b3a45bd6eb62afb7020c3b0697765e1e730b876","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.9.1.tgz","fileCount":18,"integrity":"sha512-A8xn8Bk/H9UNL5Ah0y96CAQwjANPhjmYVpul/wX0jx9CISdLXvO5JMCEY2oc0n5z8jK7+jM5HJp8ioiTHLHxFw==","signatures":[{"sig":"MEUCIQCuPVUWVYx9rMHSZ1XoDFUzAFFvvBtbovjTlO+EG6WX+wIgFrO88hy2TPC1NWS1zHiGUYnJbNpmGr3Tb53go3z4i+g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588963},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"f297d6e2a454866a969d99fe67b8e540406c2180","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.9.1_1784996702730_0.28929007748358915","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"claude-artifact-framework","version":"0.10.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.10.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"559675a0e97c0188aac71d4f0443e7ea50d94ed3","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.10.0.tgz","fileCount":18,"integrity":"sha512-aHnzGo8ADAybXl3oNY+pNylAH13pjmgFYiShgWgo9F7sK9v6Bd9s8iobU2v/d0Mrz5smkuil5XvfgVe+3nZekQ==","signatures":[{"sig":"MEUCIQDjj5jlSQUf0f5b0wGxMo+EtP+oWk7WUY7ecw27ElFFlgIgA3ECOoWCVuJdKfILFNQEVZCeb1L4qrbNHHQBAjEukgY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":628622},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"df9f1a6414ad728afe097a118ab4bdfc42247902","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.10.0_1784997396075_0.027489033506443272","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"claude-artifact-framework","version":"0.11.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.11.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"57cda245121f1e5858f19dd63190a958c925f748","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.11.0.tgz","fileCount":18,"integrity":"sha512-uQoRrorpMZL+Buia5gsyKbtYW7U9uEVNueOvdAsuHWHSjQ4u1jZGTPE9tHrbODFustBbA4pphk6akeaLGXh6wA==","signatures":[{"sig":"MEUCIQCPqdEVL0UosKLiRpX/7OuvdzcP8ZP0Teg93+uJSgM8BQIgc75Q1i4tQMI95KDu3HkQFV55FgDRg8exFEo4LrcV9TM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":630839},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"bc3807e5a5bb9797f57094d543b8f71209991b20","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.11.0_1784998605999_0.8210710409967974","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"claude-artifact-framework","version":"0.12.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.12.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"13becad482ecf4df678be9a9d12b4601668c8feb","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.12.0.tgz","fileCount":18,"integrity":"sha512-kPhtN9hhTtzfxhSGM/jBATJnoq5/6HBpCsWg93XYdNh2PT7yekWXAIij02oXOz8nx95uEdiT7UPJyTLDQEOvbw==","signatures":[{"sig":"MEUCIQDwI0J6JmiEZr4UrWq3YZzssKQ4IZPAVbxrYTKhpUEzmwIgKVphFwIlrRUkgiE4+2jQ0EQfN6er58c48Pf2oEdF+Pc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":657138},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"c08e50688b5da362e3d0fee67abe8f5431523d07","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.12.0_1785003645831_0.8361759125292374","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"claude-artifact-framework","version":"0.13.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.13.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"356bca445cdeadf7c1c996f0af9a3010c34abbcb","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.13.0.tgz","fileCount":18,"integrity":"sha512-s9wNT+sjIJXOFw92c2v/zBNUR/0aYX5WPhjmnyPkYHkFFW7Guky8irrxViaUEbcYCmeIDpKpCe+RaiXgX+kCmA==","signatures":[{"sig":"MEQCIF/nblqs9I8ffYMco1PZvUomtQ+7JULfQBWLKK86b2baAiANzrXETXFm/AmJDuOd3mS0qszD1AUKv5h+HnUB4AfLFQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":683735},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"1f5351d6948148f9f3d8cdd89cfc116134ee84a9","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.13.0_1785006988005_0.01412528290179238","host":"s3://npm-registry-packages-npm-production"}},"0.13.1":{"name":"claude-artifact-framework","version":"0.13.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.13.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"a20729e1036644431e6e1dbd4a589458f7af0366","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.13.1.tgz","fileCount":18,"integrity":"sha512-lfxOTvg7kgLMVKYRiJtNOA8nXQqRwzpplR/Q4+35YW4v5Lf+YS5WjkeDFXGprzo0ioBjIMggkcV4QcMgeCldnQ==","signatures":[{"sig":"MEQCIAsh2daQVkPE/SfZZslDx6hDSkNIaqwGMKfuZUNS0WqMAiB7FTiUojOeTJ8EGl69QZOvs+7ch/WV1o82KvV0r+N8GQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":684102},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"1f1c7e04c8716cfc8d30bfc834adeac63b9a238a","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.13.1_1785007196879_0.5305844146438214","host":"s3://npm-registry-packages-npm-production"}},"0.14.0":{"name":"claude-artifact-framework","version":"0.14.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.14.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"ec8875ffa16daceb55692f336686aa0e0f7f118e","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.14.0.tgz","fileCount":18,"integrity":"sha512-wMB8wFdcrSAr2Pm/ivb9F2rcLW7wufUvyo9R6giR0uxg4rL3DnlLNC2Kyn7e9Hu7eE6xoZ4SGNqAmF+28HYGSQ==","signatures":[{"sig":"MEYCIQCqYwA23gM3FS0Q4jn/isgJQ8fqX8swuVovfS7D+zn5oAIhANcvwF/Npk9qlZ7sekACUQZpMYsy6QBOlEFqAi05zrKO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":735221},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"f4f08e1abd7a8842a9c632e966aa64078a129c34","scripts":{"build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.14.0_1785015722350_0.5307391651167235","host":"s3://npm-registry-packages-npm-production"}},"0.14.1":{"name":"claude-artifact-framework","version":"0.14.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.14.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"e698ed5504d2deb6ee6c46dc5ba40045e342fce2","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.14.1.tgz","fileCount":19,"integrity":"sha512-pRRFeR3yGjHrXdvuPKGVW+EQFy2yneBM/FY6Al7QXbW72g3LomymhxhfqRzZ8aa27qCHG+tGi8X7Y74Vrtw6UA==","signatures":[{"sig":"MEQCIF8pDmqFZy/7a6C/u0Z9+EtgEtc2JDihECJM8o/dPIWOAiBkFT1QMgGrudLPiZOfDNPobDMIu34GE0PPcHPQUNAfDQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":741825},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"4bb4fb67d1fd0849699cea3b7feb504aeb388635","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.14.1_1785017907686_0.9372834236345267","host":"s3://npm-registry-packages-npm-production"}},"0.15.0":{"name":"claude-artifact-framework","version":"0.15.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.15.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"e465f78bfdec35a511d2b8447dbdfe3c3cd0d883","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.15.0.tgz","fileCount":19,"integrity":"sha512-zOEAUY/sxjhR+si1mgifCYAjxgOT9MThSUEOwuz3dvDTwV07azTWjqLuuSUDbegEfY0WpPb/yZsQKM6RnTmi5g==","signatures":[{"sig":"MEUCICbmTGeAaleB66+zy2YQmXkfileR95tKOO3pIIAXqaumAiEA13+i3sjtHKkZBVwehMUegk1OeedOYHTXzzVCFw0G9Ss=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":788206},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"81d7ca948d6dcef95db4c853191cca507eda3297","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.15.0_1785020983895_0.9761873322532224","host":"s3://npm-registry-packages-npm-production"}},"0.16.0":{"name":"claude-artifact-framework","version":"0.16.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.16.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"ce3ce20149909e8b05dfecd198153befdcafb21e","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.16.0.tgz","fileCount":19,"integrity":"sha512-WCfFnhXw4yQkRtaoQhv30qSm7fY9iZeS3gHE66fcCEtlkSU2fWcry6WS84b3Qu07Qwfi13J99f4mtXz+B9v9xQ==","signatures":[{"sig":"MEQCIBpV+m2s5QEMZs19Rkg8HZQW2G25C2obHR9jNs/Mb4LZAiBpw6jUL4KefgUlnptn99buQeQpk81yExPgq4hQyHWllg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":795830},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"47ca7c98b5b46c83b2bea2ca0f21032506669a73","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.16.0_1785022382040_0.479996581152244","host":"s3://npm-registry-packages-npm-production"}},"0.17.0":{"name":"claude-artifact-framework","version":"0.17.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.17.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"82483273409bbb14cdf59fa65ae9f634d5aea089","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.17.0.tgz","fileCount":19,"integrity":"sha512-v0fzKr3V+bh5J69XM+p3Q3IYvKc/DpCKIOxttoXya4IJWzlVAk5hGxwkWlBO9G/hMdp+fue90AwPKTw77IhzOA==","signatures":[{"sig":"MEUCIGW+L5MKC/IQ3d2gFtHkQ28vwpEKnfC8XjA7M2xtoQegAiEAhrHI8r77cETVPlv2mBe30FmG4LM8upDR+SAFShZgBDY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":814877},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"b9b05061792b1170d63b05d3fd310af444097acb","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.17.0_1785023845691_0.4412452544707848","host":"s3://npm-registry-packages-npm-production"}},"0.18.0":{"name":"claude-artifact-framework","version":"0.18.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.18.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"1fb4daa7646d11ac8f749b43162040e26e0145c6","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.18.0.tgz","fileCount":19,"integrity":"sha512-ZR7wHoamp+rUY1cEUEm3kNnuGCOdAQCO4Xjus2cqym7vuofiw1/ITrMUWKhQ1FAQR1Pa9FbWdntLXxu0jrEHkQ==","signatures":[{"sig":"MEQCIGPO4+yWVrw0d5y+yAg9AStK1z5/LvB643AIADNhq1poAiBd2nd4MrtPebcjA18DgAd5YlqyekNonmsu2MIlNfPPNw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":828866},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"ef3c01e34d51b64bd7fca617b5240878d6746e7a","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.18.0_1785029112171_0.10389406093850151","host":"s3://npm-registry-packages-npm-production"}},"0.19.0":{"name":"claude-artifact-framework","version":"0.19.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.19.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"f6e09fcad17b08c3bc4eb6781f1be8787452042d","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.19.0.tgz","fileCount":19,"integrity":"sha512-pj2IiVeUxCSUjx98fWxOJk3WGuXkKUZ637V7l5e17Vg0zKgIUaRiBs5VvZQWXV/Dv1rbAh/em4Cwucx8CHGjGg==","signatures":[{"sig":"MEYCIQDFLOAnxJMUKXnd4v/Z4L9wuIlqowKYImDnx43lY5wzIAIhAMfB7/S7zt6XeXORMM8wQniwdg6qsZr5D/hbA1Axv/U5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":841189},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"74a1c99dc7a9099c4083e946a20568584ca4d423","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.19.0_1785030908132_0.5243402618436701","host":"s3://npm-registry-packages-npm-production"}},"0.19.1":{"name":"claude-artifact-framework","version":"0.19.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.19.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"396874758b4794cf99efeff132f00c140dd8e576","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.19.1.tgz","fileCount":19,"integrity":"sha512-KnbpA0kySxjRTWy5QKZZ6aBJYXMUlY5nci4g1Hd+MD3ng297nqYO0oXonKE/gWuh1p3UUSH34wR1YWq6Y+dL8Q==","signatures":[{"sig":"MEUCIDO73YBkgzFxV5ZZMADkAMTLvujQfSOZkvEMIibrtQ6cAiEA24bHQrjGp/xwQ8VyMXChbFHUpYW4KMxnti1R3+H/biw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":844073},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"db27f12261d7eacbded27d5907788b180a1c4db2","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.19.1_1785032151244_0.7233242504047439","host":"s3://npm-registry-packages-npm-production"}},"0.19.2":{"name":"claude-artifact-framework","version":"0.19.2","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.19.2","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"4fb0885fe3bb856e02a51c2fec76b0fba7a5f437","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.19.2.tgz","fileCount":19,"integrity":"sha512-ZIaqazDILTnzxULaUy2fGUsbG8SPMTYpFKVMzvjFkUHFWVF8oa872q3f1DxvdGnzyH3H/VseW2MT78hMWUKj+w==","signatures":[{"sig":"MEUCIQDU8i/ZbrSlvMT0eZO6RJK0OATRH750jHzcBfQ89AtANQIgEgwDOyIpPSfG/CxFOErE0ZMIXpB7h/vhZm2YQNn4fAA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":839901},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"0685016c9e85d7860f9d2798f600dee48afbce7e","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.19.2_1785036061287_0.45511021910976024","host":"s3://npm-registry-packages-npm-production"}},"0.20.0":{"name":"claude-artifact-framework","version":"0.20.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.20.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"87b7f588457e073b46c44d58754a797affc7a460","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.20.0.tgz","fileCount":19,"integrity":"sha512-npKoNA0ib7o70OpFhtIgX81bPjMY/PzxPTzUrV9yZwffZnGhIBghOHuzv3fDl8IcuWrTejZ8k+DBVih5N1ydoQ==","signatures":[{"sig":"MEYCIQC7ohOB+BNicJWuob/18xr+Y4CmKxQm+QBgBubnUNFkQgIhAJSBH8WRkUL4Fgr0D6g3pCEb6p4nAGZwBo3QypmKdkhw","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":873902},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"934230dd6db74cdef6ae6c4ebeac39f3df6f4cdf","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.20.0_1785037164337_0.9249139982357679","host":"s3://npm-registry-packages-npm-production"}},"0.20.1":{"name":"claude-artifact-framework","version":"0.20.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.20.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"b5781295ef229a9ae798296ed5faf9461972fa52","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.20.1.tgz","fileCount":19,"integrity":"sha512-t+Qi7JoMvMXlf5sAYC1Q1Bd0oIrRKFmtQYbEzZLOlihp4b3vWYB14JQie+JDhoPky1ylVcHN5JGhzjLzLWpcNg==","signatures":[{"sig":"MEUCIQDAGSrqBNadqcv0lrxDd8T5BlZ3/ESPbIXfd9EH2NaW6AIgUFaGOmORd3I0TbbRaGP6cMwQAyvseN2sOKr9FLrCbcY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":878846},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"14158057f715c37fb5c9ebbe19fbc3d09334a99e","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","release":"node scripts/check-docs.mjs && npm test && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.20.1_1785045218586_0.7059952987545655","host":"s3://npm-registry-packages-npm-production"}},"0.20.2":{"name":"claude-artifact-framework","version":"0.20.2","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.20.2","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"58806499815bca6be6c28882cb7ffdd58d82e4c6","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.20.2.tgz","fileCount":19,"integrity":"sha512-LfyjEMQ9ghIh+1sUUI/NBQL2ldUDvqrNMm3bnsdOE+WJO5GDu+djndTbKO36vb68rU0xYOPsf7nRNsE/KjT//w==","signatures":[{"sig":"MEQCIAMfwv4mYOBCJc8RRPSNdOfTFaxzrh7KJXW3DXaGrS3YAiB0VRJjHkWUo4PwZquz+i6P6W72RU1mrWjQnohOzeeDHg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":883417},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"5adb0d0d964b438e4f39ae217e3965c0a7b69e44","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","quality":"node test/tools/quality-scan.mjs","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","axe-core":"^4.12.1","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.20.2_1785087960127_0.33607984310061045","host":"s3://npm-registry-packages-npm-production"}},"0.21.0":{"name":"claude-artifact-framework","version":"0.21.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.21.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"6693cb00e69196cff2734eec2fe42589f412abb0","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.21.0.tgz","fileCount":21,"integrity":"sha512-Cw0Vhtk0fgWqqzfDno1s7HhqLQI14lMEr53UNjV4w6nZtKW2SLrHZnxRadSLmBlH/rEoxdeCJYQ4yLEYUqH/Zw==","signatures":[{"sig":"MEUCIEQgOskVYXWJWwmeB6NwnS+epuB2z0CRWiD9cCl8kuYjAiEAssnG8JzPJiSh/SVZFulfdjsRDXpZVCE89iD+v9ZxqLU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":977857},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"dc9b5639cd2caeeefa2f35d4778f70c646ef2aa3","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","quality":"node test/tools/quality-scan.mjs","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","axe-core":"^4.12.1","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.21.0_1785090757645_0.38176451884749096","host":"s3://npm-registry-packages-npm-production"}},"0.21.1":{"name":"claude-artifact-framework","version":"0.21.1","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.21.1","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"e110f508be6ec0fe85cb80e637abd886a946426c","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.21.1.tgz","fileCount":21,"integrity":"sha512-frdPbOHFAlPfo2QSKaRnqb2nOmqgbllSUwsm3bKB7MClLnY3mRp9wTqz7MzdDNHp/joGPKbUpVyQtQvYtpZxXg==","signatures":[{"sig":"MEUCIQDClln7pEh/N7QyKMQNAuMk1CHjDwp+lUq9yA670yiKlgIgOeT9kMffBR8Gugy8pMgomklQQL9q78P1ytJvuLxwPCo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1002897},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"c59ebe2b64d8ee8eb9b764dd134ad4c0d3be9c7a","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","quality":"node test/tools/quality-scan.mjs","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","axe-core":"^4.12.1","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.21.1_1785099318908_0.39551810503925267","host":"s3://npm-registry-packages-npm-production"}},"0.21.2":{"name":"claude-artifact-framework","version":"0.21.2","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.21.2","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"2f85a1658898b70be5e70a6b7ccf0d483315f5db","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.21.2.tgz","fileCount":21,"integrity":"sha512-e1HY6F2k8s6bVfgPFvbqZqeVH2IT29M3xiXqrnAYdbfgp2oXBwOBUfs+fQ1p/VvWK00XrNi1Rqb6oCDxOyxiMg==","signatures":[{"sig":"MEUCIAjm7BU6t47zl8KRjd190X0cG6prI/k1iHaKyNEHcg4YAiEAuTBF88S6HyDCvMEQBLb0jF4RaMQqqyGe+eCnQb/BMtU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1007721},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"1f94d29d0a36d2cdb7d80a75eb35c57b95b539bb","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","quality":"node test/tools/quality-scan.mjs","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","axe-core":"^4.12.1","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.21.2_1785100440663_0.12918151739246775","host":"s3://npm-registry-packages-npm-production"}},"0.22.0":{"name":"claude-artifact-framework","version":"0.22.0","author":{"name":"Alejandro Cuartas"},"license":"MIT","_id":"claude-artifact-framework@0.22.0","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"dist":{"shasum":"828606607089e7ede7b877d0dcad8846e70351e2","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.22.0.tgz","fileCount":21,"integrity":"sha512-hGw6Y2ha8cEh89yUresqflGmaZMYcR7FCxOKm9RNYXbZwhUJnvYG9zZNRmEivTvg4ZqnLXQuSNGLeA3QKgZlqw==","signatures":[{"sig":"MEYCIQDYGzjPqM+ob/mqvLxjf2q0Rq6J3ojiIDoNRa3Ix3U4YAIhANOl/cGzy83/3qdIDa1AYA8FBuv4WmNloIMet717VMyr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1034063},"main":"./dist/index.esm.js","type":"module","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"gitHead":"a1cbead16280f4ab09fbfff76d956aac790ad3e3","scripts":{"test":"npm run build && node test/e2e.mjs","build":"node scripts/build.mjs","quality":"node test/tools/quality-scan.mjs","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh","a1-replay":"node test/tools/a1-replay.mjs","build:watch":"node scripts/build.mjs --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"repository":{"url":"git+https://github.com/alejoair/claude-artifact-framework.git","type":"git"},"_npmVersion":"10.9.7","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.0","esbuild":"^0.25.0","axe-core":"^4.12.1","react-dom":"^18.3.0","playwright-core":"^1.45.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-artifact-framework_0.22.0_1785102450155_0.9436134625462498","host":"s3://npm-registry-packages-npm-production"}},"0.22.1":{"name":"claude-artifact-framework","version":"0.22.1","description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","type":"module","main":"./dist/index.esm.js","module":"./dist/index.esm.js","exports":{".":{"import":"./dist/index.esm.js"}},"scripts":{"build":"node scripts/build.mjs","build:watch":"node scripts/build.mjs --watch","test":"npm run build && node test/e2e.mjs","quality":"node test/tools/quality-scan.mjs","a1-replay":"node test/tools/a1-replay.mjs","prepublishOnly":"npm run build","release":"node scripts/check-docs.mjs && npm test && npm run quality && bash scripts/publish.sh"},"devDependencies":{"axe-core":"^4.12.1","esbuild":"^0.25.0","playwright-core":"^1.45.0","react":"^18.3.0","react-dom":"^18.3.0"},"license":"MIT","author":{"name":"Alejandro Cuartas"},"repository":{"type":"git","url":"git+https://github.com/alejoair/claude-artifact-framework.git"},"_id":"claude-artifact-framework@0.22.1","gitHead":"c1a83879545a825b7d3ce34964f49f7833abc28d","bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"homepage":"https://github.com/alejoair/claude-artifact-framework#readme","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-U9JGsPW+N//fjpmK0Py4OljPc20UxZsnoiXCPAc2nDYIR4INFQ1zYrFe6eHN2jza8x8Vug/5OW1/1MN2DXFzOw==","shasum":"bde2177be1c88e5d14d7170a111224e549de76b9","tarball":"https://registry.npmjs.org/claude-artifact-framework/-/claude-artifact-framework-0.22.1.tgz","fileCount":21,"unpackedSize":1043193,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGxg5T8Ipt6aEuZIF7oGRkv9CFh51FwiMUAVJ46bmjQoAiEAgSMlgszoVBWITJ4ffTI7xNCvqsH3bnWqMnIyS3rDoLw="}]},"_npmUser":{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"},"directories":{},"maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/claude-artifact-framework_0.22.1_1785108104620_0.8685404360871929"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-23T04:06:19.075Z","modified":"2026-07-26T23:21:44.954Z","0.1.0":"2026-07-23T04:06:19.349Z","0.2.0":"2026-07-23T04:31:21.947Z","0.2.1":"2026-07-23T14:37:06.086Z","0.3.0":"2026-07-25T00:46:55.878Z","0.4.0":"2026-07-25T03:39:29.217Z","0.5.0":"2026-07-25T05:01:12.178Z","0.5.1":"2026-07-25T05:15:25.892Z","0.5.2":"2026-07-25T05:21:40.235Z","0.6.0":"2026-07-25T05:32:08.586Z","0.7.0":"2026-07-25T11:59:01.042Z","0.7.1":"2026-07-25T13:16:57.026Z","0.7.2":"2026-07-25T14:18:05.173Z","0.7.3":"2026-07-25T14:22:09.618Z","0.8.0":"2026-07-25T14:32:40.352Z","0.8.1":"2026-07-25T14:53:10.328Z","0.9.0":"2026-07-25T16:12:30.583Z","0.9.1":"2026-07-25T16:25:02.895Z","0.10.0":"2026-07-25T16:36:36.271Z","0.11.0":"2026-07-25T16:56:46.167Z","0.12.0":"2026-07-25T18:20:45.969Z","0.13.0":"2026-07-25T19:16:28.176Z","0.13.1":"2026-07-25T19:19:57.110Z","0.14.0":"2026-07-25T21:42:02.509Z","0.14.1":"2026-07-25T22:18:27.846Z","0.15.0":"2026-07-25T23:09:44.103Z","0.16.0":"2026-07-25T23:33:02.239Z","0.17.0":"2026-07-25T23:57:25.833Z","0.18.0":"2026-07-26T01:25:12.333Z","0.19.0":"2026-07-26T01:55:08.288Z","0.19.1":"2026-07-26T02:15:51.401Z","0.19.2":"2026-07-26T03:21:01.495Z","0.20.0":"2026-07-26T03:39:24.502Z","0.20.1":"2026-07-26T05:53:38.762Z","0.20.2":"2026-07-26T17:46:00.317Z","0.21.0":"2026-07-26T18:32:37.784Z","0.21.1":"2026-07-26T20:55:19.081Z","0.21.2":"2026-07-26T21:14:00.833Z","0.22.0":"2026-07-26T21:47:30.302Z","0.22.1":"2026-07-26T23:21:44.780Z"},"bugs":{"url":"https://github.com/alejoair/claude-artifact-framework/issues"},"author":{"name":"Alejandro Cuartas"},"license":"MIT","homepage":"https://github.com/alejoair/claude-artifact-framework#readme","repository":{"type":"git","url":"git+https://github.com/alejoair/claude-artifact-framework.git"},"description":"Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.","maintainers":[{"name":"sirarthur","email":"alejandro.cuartas@yahoo.com"}],"readme":"# claude-artifact-framework\n\nA declarative framework for building apps inside Claude Artifacts: declare\nwhat the app **is** — fields, records, steps, a chat with tools, a workspace\nwith a copilot — and the framework owns how it works. Persistence, hydration,\nvalidation, empty/loading/error states, light+dark theming, navigation, and\nthe Claude tool loop are construction guarantees, not authoring tasks.\n\nFive layouts (`panel`, `records`, `steps`, `chat`, `workspace`), ten block\ntypes, tabs/conditional/collapsible composition, shared multi-viewer data,\nand a `custom` escape hatch that keeps every framework service. Zero\ndependencies, no build step — load it straight from a CDN. The decisions and\nthe evidence behind them live in [DESIGN.md](./DESIGN.md).\n\n## Usage via CDN\n\nEverything is served through [jsDelivr](https://www.jsdelivr.com/), which\nmirrors npm packages automatically.\n\n### As a global script (`<script>` tag)\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.8.1/dist/index.global.js\"></script>\n<script>\n  ArtifactKit.useReact(React); // hand over the page's React once\n  const App = ArtifactKit.createApp({ title: \"Mi app\", blocks: [ /* ... */ ] });\n  // lower-level utilities are also exported:\n  const { storage, createStore, createPersistedStore, createSharedStore } = ArtifactKit;\n</script>\n```\n\n### As an ES module\n\n```html\n<script type=\"module\">\n  import {\n    storage,\n    createStore,\n    createPersistedStore,\n    createSharedStore,\n  } from \"https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.8.1/dist/index.esm.js\";\n</script>\n```\n\nPin a version (`@0.8.1`) for reproducible artifacts, or drop the version\n(`claude-artifact-framework/dist/...`) to always get the latest release.\n\n### Inside a React artifact\n\nA React artifact loads external code the same way any artifact does — by\ninjecting a classic `<script>` tag, not by importing a module URL. Hand the\nframework the React the artifact already imported, so there is only ever one\nReact on the page:\n\n```jsx\nimport React, { useState, useEffect } from \"react\";\n\nconst KIT = \"https://cdn.jsdelivr.net/npm/claude-artifact-framework/dist/index.global.js\";\n\nfunction load(src) {\n  return new Promise((resolve, reject) => {\n    if (document.querySelector(`script[src=\"${src}\"]`)) return resolve();\n    const tag = document.createElement(\"script\");\n    tag.src = src;\n    tag.onload = resolve;\n    tag.onerror = reject;\n    document.head.appendChild(tag);\n  });\n}\n\nexport default function Artifact() {\n  const [App, setApp] = useState(null);\n\n  useEffect(() => {\n    load(KIT).then(() => {\n      ArtifactKit.useReact(React);\n      setApp(() => ArtifactKit.createApp({\n        title: \"Mortgage calculator\",\n        theme: { seed: \"#0c8b8d\" },\n        blocks: [\n          { fields: [\n            { key: \"amount\", label: \"Amount\",   type: \"money\",   value: 300000 },\n            { key: \"rate\",   label: \"Rate\",     type: \"percent\", value: 5.5 },\n            { key: \"years\",  label: \"Term\",     type: \"number\",  value: 30, min: 1, max: 40 },\n          ]},\n          { output: (d) => {\n            const i = d.rate / 100 / 12, n = d.years * 12;\n            const payment = d.amount * i / (1 - Math.pow(1 + i, -n));\n            return [{ label: \"Monthly payment\", value: payment, format: \"money\", big: true }];\n          }},\n        ],\n      }));\n    });\n  }, []);\n\n  return App ? <App /> : null;\n}\n```\n\n`useReact` is the one thing the framework asks for, and only because a runtime\nmay keep React in a private module registry the bundle can't reach. If React is\nalready on `globalThis`, it is picked up automatically and the call is a no-op.\n\n> **Write the spec indented, never minified.** Specs nest deep (`types` →\n> `blocks` → `records` → `fields`), and the only syntax errors ever measured\n> in generated specs came from single-line minified output — a dropped or\n> extra closing brace at the tail. Indented, multi-line specs have never\n> produced one. Format like every example in this document.\n\n> **Don't hand-build empty, loading, or error states.** Every block that can\n> be empty (`output`, `chart`, `list`, `records`) shows a named empty state\n> by itself; hydration shows a loading screen; a block that throws shows a\n> named error in its own slot. Code like `if (!d.items.length) return \"No\n> hay datos\"` duplicates what the framework already guarantees.\n\n### The `records` layout — a full CRUD app from a declaration\n\nFor \"list of things\" apps (expenses, habits, notes, todos), declare what a\nrecord is and the whole lifecycle — list, add, edit, delete, empty state,\nselection, persistence — is framework-owned:\n\n```js\nArtifactKit.createApp({\n  title: \"Gastos\",\n  theme: { seed: \"#c2410c\" },\n  layout: \"records\",\n  records: {\n    label: \"expense\",\n    fields: [\n      { key: \"concepto\",  label: \"Concepto\",  type: \"text\", required: true },\n      { key: \"monto\",     label: \"Monto\",     type: \"money\", value: 0, min: 0 },\n      { key: \"categoria\", label: \"Categoría\", type: \"select\", options: [\"comida\", \"transporte\", \"otros\"] },\n    ],\n    subtitle: (r) => r.categoria || \"sin categoría\",\n    summary: (all) => [\n      { label: \"Total\",  value: all.reduce((s, r) => s + (Number(r.monto) || 0), 0), format: \"money\", big: true },\n      { label: \"Gastos\", value: all.length, format: \"number\" },\n    ],\n  },\n});\n```\n\n\"Add\" creates the record from field defaults and opens it (no draft object to\nlose); detail fields edit the record in place through the same debounced\npersistence path as everything else. `id` is assigned by the framework and\nreserved. Optional: `title(r)` / `subtitle(r)` for rows, `sort(a, b)`,\n`summary(records)` for stats above the list, `empty` for the empty-state text.\n\n### The `steps` layout — wizards, quizzes, staged calculators\n\nDeclare the sequence; next/back/progress/result are framework-owned. Step\nfields write into the same flat `data` pool, so the result step is just a\nfunction of data. Next is gated on the current step's validation; the current\nstep survives a reload.\n\n```js\nArtifactKit.createApp({\n  title: \"Quiz de riesgo\",\n  layout: \"steps\",\n  steps: [\n    { title: \"Tu edad\",   fields: [{ key: \"edad\", type: \"number\", required: true, min: 18 }] },\n    { title: \"Tu perfil\", fields: [{ key: \"perfil\", type: \"select\", required: true, options: [\"conservador\", \"moderado\", \"agresivo\"] }] },\n    { title: \"Resultado\", result: (d) => [{ label: \"Puntaje\", value: score(d), big: true }] },\n  ],\n});\n```\n\nField keys must be unique across all steps (they share one data pool); a\nduplicate throws at creation, as does an unknown step key.\n\nA result step can end on more than stats: give it `blocks` and any block\nset (a chart of the answers, explanatory text, a list) renders under the\nresult grid:\n\n```js\n{ title: \"Resultado\",\n  result: (d) => [{ label: \"Libre por mes\", value: libre(d), format: \"money\", big: true }],\n  blocks: [{ title: \"Distribución\", chart: (d) => ({ type: \"donut\", format: \"money\", items: porRubro(d) }) }] }\n```\n\n`blocks` on a non-result step throws.\n\n### The `chart` block — bar, line, donut\n\nSame vocabulary as `output` (items of `{ label, value }` plus an optional\n`format`), so declaring one teaches nothing new. Colors derive from the theme\nseed by golden-angle rotation — a chart can't clash with the app it lives in.\n\n```js\nblocks: [\n  { chart: (d) => ({ type: \"bar\", format: \"money\", items: monthlyTotals(d) }), title: \"Ventas\", wide: true },\n  { chart: { type: \"donut\", items: [{ label: \"Comida\", value: 45 }, { label: \"Otros\", value: 55 }] } },\n]\n```\n\n### The `timer` block — countdowns that persist their effects\n\nThe interval is framework-owned and cleaned up on unmount (a leaked\n`setInterval` is a classic half-built artifact bug). The countdown itself is\ndeliberately ephemeral; what you declare is what happens when it finishes —\n`onDone` runs through `update()`, so its effects persist like any other change.\n\n```js\nblocks: [\n  { timer: { minutes: 25, label: \"Focus\", onDone: (d) => { d.completados = (d.completados || 0) + 1; } } },\n  { output: (d) => [{ label: \"Pomodoros\", value: d.completados || 0, big: true }] },\n]\n```\n\n`timer` takes `minutes` and/or `seconds` (`{ seconds: 90 }` for a rest timer),\nplus optional `label` and `doneText`.\n\n`text` blocks also accept a function of data — `{ text: (d) => \"Hola \" + d.nombre }` —\nwith the same contract as `output`.\n\n### The `chat` layout — apps that talk to Claude\n\nTutors, advisors, generators, roleplay. Every piece of the network contract is\ncopied from code proven inside the real artifact runtime: the artifact fetches\n`https://api.anthropic.com/v1/messages` directly with **no API key** (the\nruntime proxies the call and injects auth), `stream: true` works, and tools\nare prompted (the proxy does not support native function calling).\n\nThe author declares the system prompt and, optionally, tools that operate on\nthe app's data — a chat that can drive the app. The framework owns message\nstate, live streaming, the busy state, the tool loop, and errors as visible\nbubbles. The conversation persists and survives reload.\n\n```js\nArtifactKit.createApp({\n  title: \"Asistente de gastos\",\n  theme: { seed: \"#0f766e\" },\n  layout: \"chat\",\n  chat: {\n    system: (d) => \"Eres un asistente de gastos. Total actual: \" + (d.total || 0),\n    greeting: \"¡Hola! Contame tus gastos.\",\n    tools: {\n      agregar_gasto: {\n        description: \"Agrega un gasto\",\n        input: { concepto: \"string\", monto: \"number\" },\n        run: (input, ctx) => {\n          ctx.update((d) => { d.total = (d.total || 0) + Number(input.monto); });\n          return { ok: true };\n        },\n      },\n    },\n  },\n});\n```\n\n`system` is a string or a function of data. Tool `run(input, ctx)` returns a\nJSON-serializable result that is fed back to the model; an unknown tool name\nis answered in-band so the model corrects itself. Optional: `greeting`,\n`placeholder`, `model` (default `claude-sonnet-4-6`, proven through the\nproxy), `maxTokens`.\n\n**The copilot can already operate the whole app — declare tools only for\nwhat the UI can't do.** Every chat automatically carries two built-in tools:\n`app_state` (reads the current screen: fields with values, actions, tabs,\nrecord collections AND their `items` child collections) and `app_act` (sets\nfields, runs actions, switches tabs, adds/updates/deletes records AND their\nitems, moves steps, fires machine events — through the same paths a tap\ntakes). So \"add X to the list\", \"add an activity to day 2\", \"mark Y as done\",\n\"switch to the expenses tab\" work with **zero** `tools` declared. Write a\ncustom tool only for domain logic that isn't a UI affordance (calling out to a\ncomputation, bulk transforms, summaries with judgment). Author tools win on a\nname clash.\n\n### Analytics — every app is instrumented by construction\n\nBecause all interaction flows through the framework's primitives, every app\nemits structured usage events with zero author code: `action_run`,\n`record_add`, `record_update`, `record_delete`, `item_add`, `item_update`,\n`item_delete`, `tab_switch`, `view_go`, `step_go`, `machine_event`,\n`chat_send`, `field_set` (operations performed by the chat copilot carry\n`agent: true`). Two sinks, both optional:\n\n- **`window.gtag`** — if the hosting page carries the GA4 / Firebase\n  Analytics snippet (self-hosted apps), events flow to Google Analytics\n  automatically. Inside a Claude artifact there is no gtag and the CSP blocks\n  the network: a clean no-op, nothing to configure.\n- **`caf:event`** — a `CustomEvent` on `window`, always dispatched:\n  `window.addEventListener(\"caf:event\", (e) => ... e.detail.name,\n  e.detail.params)` for custom sinks or tests.\n\n### Search, computed fields, and shared data\n\nThree record-app multipliers, all declarative:\n\n```js\nArtifactKit.createApp({\n  title: \"Inventario del club\",\n  layout: \"records\",\n  shared: true,                 // one copy of the data for every viewer\n  records: {\n    search: true,               // search box over all field values\n    fields: [\n      { key: \"nombre\",   type: \"text\", required: true },\n      { key: \"cantidad\", type: \"number\", value: 1, min: 0 },\n      { key: \"precio\",   type: \"money\", value: 0, min: 0 },\n    ],\n    compute: {                  // derived per record, never stored\n      subtotal: { label: \"Subtotal\", format: \"money\", value: (r) => r.cantidad * r.precio },\n    },\n    summary: (all) => [\n      { label: \"Valor total\", value: all.reduce((s, r) => s + r.subtotal, 0), format: \"money\", big: true },\n    ],\n  },\n});\n```\n\n- `search: true` adds a filter box over every field's value; the count shows\n  \"n of total\" while filtering.\n- `compute` entries are functions of the record (or `{ label, format, value }`).\n  Computed values appear read-only in the detail screen and are available to\n  `title` / `subtitle` / `sort` / `summary` as if they were fields. A compute\n  key that collides with a field key throws.\n- `shared: true` (top level) stores the app's data in the shared scope: every\n  viewer of the published artifact converges on the same data via polling.\n  Conflict handling is last-write-wins; a poll never overwrites local edits\n  that haven't been persisted yet. View state (which screen is open) stays\n  personal per viewer. **Design for last-write-wins**: two viewers writing\n  within the same couple of seconds means one write can be lost — prefer\n  per-viewer marks in arrays (`votantes: [...viewerIds]`, like the voting\n  pattern) over several people editing the same field, and don't build\n  anything where a lost write really hurts (money, bookings). Measured in\n  practice: appending to your own mark converges; racing on one value\n  doesn't.\n\n### `items` — a child collection per record\n\nFor \"a thing with parts\": invoices with line items, recipes with\ningredients, projects with tasks. One level deep by design; children edit\ninline on the parent's detail screen (they're for small rows, not records\nthat deserve their own screen). The collection lives at `r.items` and is\navailable to `compute` / `title` / `subtitle` / `summary`:\n\n```js\nrecords: {\n  label: \"factura\",\n  fields: [{ key: \"cliente\", type: \"text\", required: true }],\n  items: {\n    label: \"ítem\",\n    fields: [\n      { key: \"concepto\", type: \"text\" },\n      { key: \"cantidad\", type: \"number\", value: 1, min: 0 },\n      { key: \"precio\",   type: \"money\", value: 0, min: 0 },\n    ],\n  },\n  compute: {\n    total: { label: \"Total c/IVA\", format: \"money\",\n             value: (r) => (r.items || []).reduce((s, i) => s + i.cantidad * i.precio, 0) * 1.21 },\n  },\n}\n```\n\n`items` keys: `label`, `fields`, `empty`. Each child gets a framework\n`id`; a parent field can't be named `items`. The smell this replaces:\n**never ask the user to type JSON (or comma-separated rows) into a\n`textarea`** — if a record has parts, declare `items` and each part gets\nreal fields, validation, and its own remove button.\n\n### `actions` — one-tap buttons that mutate data\n\nOn records rows (mark done, +1, vote — without opening the record):\n\n```js\nrecords: {\n  fields: [{ key: \"nombre\", type: \"text\" }, { key: \"veces\", type: \"number\", value: 0 }],\n  actions: [\n    { label: \"Hecho hoy\", run: (r) => { r.veces = (r.veces || 0) + 1; } },\n    { label: \"Reset\", kind: \"danger\", when: (r) => r.veces > 0, run: (r) => { r.veces = 0; } },\n  ],\n}\n```\n\nAnd as a block in `panel` (quick counters) — `{ output, actions }` renders\nthe buttons as the stat card's own footer, the same way `{ fields,\nactions }` owns its submit button:\n\n```js\nblocks: [\n  { output: (d) => [{ label: \"Agua hoy\", value: d.agua || 0, big: true }],\n    actions: [{ label: \"+1 vaso de agua\", kind: \"primary\", run: (d) => { d.agua = (d.agua || 0) + 1; } }] },\n]\n```\n\nAction keys: `label`, `run`, optional `when` (hides the button when false)\nand `kind` (`\"primary\"` / `\"danger\"`). Row actions — `when` and `run`\nalike — receive `(record, data, viewerId)`; block actions\n`(data, viewerId)`. Stopping early is fine (`run: (r) => ...`), and the\nframework matches the viewer id **by name**: a second parameter literally\nnamed `viewerId` receives the viewer id even though `data` was skipped —\n`run: (r, viewerId) => ...` works as written. Still, prefer the full\norder: `run: (r, d, viewerId)`. Changes persist like any other update.\nGive the constructive action `kind: \"primary\"` — a \"Vote\"/\"Add\"/\"Done\" left\nas the neutral default reads weaker than a `\"danger\"` next to it. And a\nsmell to avoid: **a number that changes by pressing is an `action`, not an\neditable `number` field** — votes, counters, and streaks as editable inputs\ninvite typos and lie about intent.\n\nChat bubbles render the assistant's **markdown** (bold, code, lists,\nheadings) automatically — HTML is escaped first, so model output can't\ninject markup.\n\n### The `workspace` layout — content + copilot\n\nA full-width main column and a sidebar, for apps where content and an\nassistant live side by side: an editor with a writing copilot, a dashboard\nwith an analyst, a viewer with an annotator. `chat` is available as a block,\nso the copilot's tools can drive the main content:\n\n```js\nArtifactKit.createApp({\n  title: \"Editor con copiloto\",\n  layout: \"workspace\",\n  main: [\n    { fields: [{ key: \"nota\", type: \"textarea\", rows: 8 }], title: \"Documento\" },\n    { output: (d) => [{ label: \"Palabras\", value: countWords(d.nota), big: true }] },\n  ],\n  sidebar: [\n    { title: \"Asistente\",\n      chat: {\n        system: (d) => \"Sos un copiloto de escritura. Nota actual: \" + (d.nota || \"\"),\n        tools: {\n          reescribir_nota: {\n            description: \"Reemplaza el texto de la nota\",\n            input: { texto: \"string\" },\n            run: (input, ctx) => { ctx.update((d) => { d.nota = input.texto; }); },\n          },\n        },\n    }},\n  ],\n})\n```\n\nGive the chat block a `title` (like every other block) — a chat card that\nopens straight into a bubble is the one block on screen without a heading.\n\n`main` is required; `sidebar` is optional. Both take the same blocks as\n`panel`. The panes sit side by side and stack on narrow screens. One chat\nblock per app — the conversation persists under `data.chat` and there is\nexactly one.\n\n### Tabs, conditional blocks, and accordions\n\nThree in-screen navigation primitives, usable in `panel`, `workspace`, and\nbelow a `records` list alike:\n\n```js\nblocks: [\n  { tabs: [\n    { label: \"Registrar\", blocks: [{ fields: [...] }] },\n    { label: \"Resumen\",   blocks: [{ output: (d) => [...] }, { chart: (d) => ({...}) }] },\n  ], wide: true },\n\n  // `when` hides any block until the condition holds\n  { output: (d) => [...], when: (d) => d.records.length > 0 },\n\n  // `collapsible` needs a title; `\"collapsed\"` starts closed\n  { text: \"Instrucciones…\", title: \"Ayuda\", collapsible: \"collapsed\" },\n]\n```\n\nThe active tab and each accordion's open/closed state are framework-owned\nview state — they survive reload, per viewer. Tabs cannot nest inside tabs;\n`when` must be a function; both throw otherwise.\n\n**When tabs ARE the app** — one tabs block as the whole UI, 4-5 sections\nthe user hops between on a phone — declare bottom navigation:\n\n```js\nArtifactKit.createApp({\n  title: \"Mi Gym\",\n  mobile: { nav: \"bottom\" },\n  blocks: [\n    { tabs: [\n      { label: \"Hoy\", icon: \"💪\", blocks: [...] },\n      { label: \"Progreso\", icon: \"📈\", blocks: [...] },\n      // ...up to ~5 sections\n    ], wide: true },\n  ],\n})\n```\n\nOn a phone the first top-level tabs block's bar pins to the bottom of the\nscreen (icons above labels, every section visible and thumb-reachable);\non desktop nothing changes. Measured reason to bother: a top tab bar with\n5 sections overflows sideways at phone width and silently hides the last\nsections behind a scroll nobody sees. Declaring `mobile: { nav: \"bottom\" }`\nwithout a top-level tabs block throws.\n\n### The `machine` — declared phases instead of hand-rolled state logic\n\nIf your app has **phases** — a game (choosing → comparing → won), a turn\ncycle, a multi-stage process — never track them by hand with flags and\n`setTimeout`s: that is the single most measured source of broken apps\n(a memory game died because its compare logic fired in the wrong phase).\nDeclare the machine instead:\n\n```js\nArtifactKit.createApp({\n  title: \"Memoria\",\n  machine: {\n    key: \"fase\",                    // d.fase holds the current state — persisted\n    initial: \"eligiendo\",\n    states: {\n      eligiendo: {},\n      comparando: {                 // timed transition, framework-owned timer\n        after: { seconds: 1, then: \"eligiendo\", do: (d) => { d.reveladas = []; } },\n      },\n      ganado: {},\n    },\n    events: {\n      elegir: {\n        from: [\"eligiendo\"],        // ONLY legal here — elsewhere it's a no-op\n        do: (d, carta) => { d.reveladas = [...d.reveladas, carta]; },\n        then: (d) => d.pares === d.total ? \"ganado\" : d.reveladas.length === 2 ? \"comparando\" : \"eligiendo\",\n      },\n      reiniciar: { from: \"*\", do: (d) => { d.reveladas = []; d.pares = 0; }, then: \"eligiendo\" },\n    },\n  },\n  blocks: [\n    { custom: (ctx) => /* cards call ctx.send(\"elegir\", i) */ null },\n    { text: \"¡Ganaste!\", state: \"ganado\" },   // block exists only in that phase\n  ],\n})\n```\n\nThe contract:\n\n- **`ctx.send(event, payload)` is the only door.** An unknown event throws\n  naming the valid ones; a legal event sent from the wrong phase is a\n  silent no-op — a user mashing buttons is normal, not a bug. Never write\n  `d.fase = ...` yourself.\n- `do` mutates data (it receives `(d, payload)`), `then` names the next\n  state — a string, or a function of data returning one. Omit `then` to\n  stay in the same state.\n- `after: { seconds, then, do }` on a state is a **framework-owned timer**:\n  armed on entry, cancelled on leaving the state, cleaned up on unmount.\n  No `setTimeout` to forget.\n- The current state lives in `data` under `machine.key` (default `\"fase\"`),\n  so it **persists and resumes** — reloading mid-game continues the phase.\n- Blocks take `state: \"nombre\"` as sugar for \"visible only in that phase\";\n  `when:` still works for anything more complex.\n- Machine keys: `key`, `initial`, `states`, `events`. Event keys: `from`\n  (state, array, or `\"*\"`), `do`, `then`. One machine per app, app-wide\n  (inside `documents` it is NOT per-document).\n\n### `records` as a block — a CRUD collection inside any screen\n\nThe full records machinery (list, add-then-edit, detail, search, summary,\ncompute, items, row actions) is also a **block**, embeddable wherever panel\nblocks go — a workspace pane, a document, a tab. Declare it with the same\n`records: {...}` spec plus one extra key: **`key`**, naming where the\ncollection lives in the enclosing data pool (default `\"records\"`; two\nrecords blocks need distinct keys).\n\n```js\n// A task list per project: records INSIDE documents — each document gets\n// its own independent collection automatically.\nArtifactKit.createApp({\n  title: \"Proyectos\",\n  layout: \"documents\",\n  documents: {\n    label: \"proyecto\",\n    title: (d) => d.nombre || \"Sin nombre\",\n    blocks: [\n      { fields: [{ key: \"nombre\", label: \"Proyecto\", type: \"text\" }] },\n      { records: {\n          key: \"tareas\",\n          label: \"tarea\",\n          fields: [\n            { key: \"titulo\", label: \"Título\", type: \"text\", required: true },\n            { key: \"hecha\", label: \"Hecha\", type: \"check\" },\n          ],\n          summary: (all) => [{ label: \"Pendientes\", value: all.filter((t) => !t.hecha).length, big: true }],\n      }},\n    ],\n  },\n})\n```\n\nInside a `documents` layout the collection is per document; in `panel` or\n`workspace` it lives in the flat pool under `key`, where `output`/`chart`\nblocks and chat tools can read and write it (`d.tareas`). Which record is\nopen is framework-owned view state per collection — it survives reload,\nand a deleted open record falls back to the list. A records block below a\nrecords *layout* throws (the layout already owns the collection).\n\n### The `documents` layout — parallel documents, one per top tab\n\n`tabs` are views over ONE shared data pool. When the ask is \"several\ndocuments, each with its own state\" — a multi-note editor, one budget per\ntrip, one character sheet per player — that is the `documents` layout:\ndeclare the blocks once, and every document gets its own private copy of\ntheir data.\n\n```js\nArtifactKit.createApp({\n  title: \"Editor multi-documento\",\n  layout: \"documents\",\n  documents: {\n    label: \"documento\",\n    title: (d) => d.nombre || \"Sin título\",   // tab label, live from the doc's data\n    blocks: [\n      { fields: [\n        { key: \"nombre\", label: \"Nombre\", type: \"text\" },\n        { key: \"contenido\", label: \"Contenido\", type: \"textarea\", rows: 14 },\n      ]},\n      { output: (d) => [{ label: \"Palabras\", value: (d.contenido || \"\").split(/\\s+/).filter(Boolean).length }] },\n    ],\n  },\n})\n```\n\nThe framework owns the whole document lifecycle: the top tab bar (one tab\nper document, live-labelled, plus a **+** tab that creates and opens a new\ndocument — no draft to lose, it already exists), the **✕** on each tab to\nclose it (closing the open document falls back to a neighbour, never a\nblank pane), the per-document data pools (`d` inside any block, `output`,\n`custom`, or `when` is THAT document's data; `ctx.update` writes there),\nthe empty state, and persistence — all documents and which one is open\nsurvive reload. Documents keys: `label`, `title`, `blocks`, `empty`,\n`types`.\n\n**Typed documents** — when tabs are not all the same kind of thing, declare\n`types` instead of `blocks` (one or the other, not both). Each type has its\nown `label`, optional `title` function, and its own `blocks`; the **+** tab\nasks which kind to create when there is more than one. Each document\nremembers its type forever; an untitled document shows its type label in\nthe tab.\n\n```js\nArtifactKit.createApp({\n  title: \"Cuaderno\",\n  layout: \"documents\",\n  documents: {\n    label: \"página\",\n    types: {\n      nota: {\n        label: \"Nota\",\n        title: (d) => d.titulo || \"\",\n        blocks: [{ fields: [\n          { key: \"titulo\", label: \"Título\", type: \"text\" },\n          { key: \"texto\", label: \"Texto\", type: \"textarea\", rows: 12 },\n        ]}],\n      },\n      compras: {\n        label: \"Lista de compras\",\n        blocks: [\n          { records: { key: \"items\", label: \"producto\", fields: [\n            { key: \"producto\", label: \"Producto\", type: \"text\", required: true },\n            { key: \"comprado\", label: \"Comprado\", type: \"check\" },\n          ]}},\n        ],\n      },\n    },\n  },\n})\n```\n\nWhen the variation is smaller than \"a different kind of document\" — the\nsame document showing or hiding sections by its own state — prefer one\n`blocks` set with `when:` conditions (`when: (d) => d.modo === \"avanzado\"`)\nover `types`: one schema with conditional blocks keeps every document\nmigratable and searchable as the same shape.\n\nInside `documents`, blocks work as in `panel` — **including `chat` and\n`file`, which become per-document**:\n\n- A `chat` block inside `documents` gives **each document its own\n  conversation**, persisted with that document (`data.chat` is scoped). Its\n  `system` function receives the document's data, so the copilot talks\n  about THIS document. One chat block per document (a second throws).\n- A `file` field inside `documents` scopes `ctx.files[key]` to the active\n  document — two documents never collide on the same field key. As\n  everywhere, the live `File` is memory-only: metadata survives reload,\n  the file is re-picked per document.\n\nThat combination — one file plus one conversation per tab — is the\nmulti-document annotator shape (PDFs, images, CSVs) declared in full:\n\n```js\nArtifactKit.createApp({\n  title: \"Anotador de archivos\",\n  layout: \"documents\",\n  documents: {\n    label: \"archivo\",\n    title: (d) => (d.archivo && d.archivo.name) || \"Sin archivo\",\n    blocks: [\n      { fields: [{ key: \"archivo\", label: \"Archivo\", type: \"file\" }] },\n      { custom: (ctx) => { /* render ctx.files.archivo */ }, fill: true },\n      { title: \"Copiloto\", chat: {\n          system: (d) => \"Ayudás con el archivo \" + ((d.archivo && d.archivo.name) || \"(ninguno)\"),\n      }},\n    ],\n  },\n})\n```\n\n### Brand — logo, banner, images, icons, avatars\n\nIdentity without uploads. Artifacts can't persist real image files (the\n~5MB pool), so every brand element is **zero-asset-first**: it works with\nnothing, and a real asset is an optional upgrade.\n\n```js\nArtifactKit.createApp({\n  title: \"Napoli Pizzas\",\n  subtitle: \"Del horno a tu mesa\",\n  theme: { seed: \"#c2410c\" },\n  brand: {\n    // the logo ladder: omit → automatic monogram (initials over the accent);\n    // an emoji; an inline <svg>...</svg> (best: you can WRITE one); or an https URL\n    logo: '<svg viewBox=\"0 0 24 24\">...</svg>',\n    footer: \"Napoli Pizzas — pedidos al 11-5555-5555\",\n  },\n  blocks: [\n    // full-width hero; with no image it paints a gradient derived from the seed\n    { banner: { title: \"Promo de julio\", subtitle: \"2x1 los martes\", image: \"https://...\" } },\n    { image: { src: \"https://... o un <svg> inline\", caption: \"El local\", fit: \"cover\" } },\n    { text: \"...\", title: \"Horarios\", icon: \"🕐\" },   // icon prefixes any block title\n  ],\n})\n```\n\n- **`brand.logo`** renders beside the title; **`brand.footer`** closes the\n  page. Banner keys: `image`, `title`, `subtitle`. Image keys: `src`,\n  `caption`, `fit` (`cover`/`contain`), `height`.\n- **`icon` (an emoji) goes on any block, any tab, and any document type** —\n  emoji are zero bytes, work in both themes, and read as a consistent icon\n  set. Don't mix emoji icons with image icons in one app.\n- **`avatar: true` on records** draws an initials circle per row, colored\n  deterministically from the row title through the theme palette — a CRM or\n  ranking looks finished with no images at all.\n- Prefer inline SVG over URLs for logos and small graphics: no network, no\n  broken-image state, theme-controllable. Reserve URLs for real photos.\n\n### External libraries, uploaded files, full-bleed custom, viewer identity\n\nFour primitives for the custom-heavy end of the spectrum (document viewers,\ncanvases, analyzers):\n\n```js\nArtifactKit.createApp({\n  title: \"Visor de PDF\",\n  layout: \"workspace\",\n  libs: [\"https://cdn.jsdelivr.net/npm/pdfjs-dist@3.11.174/build/pdf.min.js\"],\n  main: [\n    { fields: [{ key: \"doc\", label: \"Documento\", type: \"file\", accept: \"application/pdf\" }] },\n    { custom: (ctx) => renderPdf(ctx.files.doc), fill: true },\n  ],\n  sidebar: [ { chat: { system: \"Sos un asistente de lectura.\" } } ],\n})\n```\n\n- **`libs: [\"https://...\"]`** loads external scripts before the app mounts,\n  deduped by URL, with a \"Loading libraries…\" state and a named error block\n  if one fails. No hand-written `loadScript` in custom code.\n- **Call the library's method, not its global.** Modern CDN builds expose a\n  *namespace object*, and APIs you remember may have moved: `marked` v5+ is\n  an object (`marked.parse(text)` works, `marked(text)` throws \"marked is\n  not a function\"). When unsure, prefer the method form — `marked.parse(md)`,\n  `Papa.parse(csv)`, `QRCode.toCanvas(...)` or `new QRCode(el, ...)`\n  depending on the lib — and pin the version in the URL so the API can't\n  drift under you.\n- **Unsure of the file path? Use the bare package URL.** jsDelivr serves the\n  package's default build at `https://cdn.jsdelivr.net/npm/<pkg>@<version>`\n  with no file path — guessed inner paths (`/marked.umd.js`,\n  `/dist/foo.min.js`) 404 more often than versions do. If a full path you\n  wrote does 404, the framework retries the bare package URL once before\n  showing the error.\n- **`type: \"file\"`** fields hand the live `File` to your code at\n  `ctx.files[key]` (in memory only — the 5MB/key storage limit makes real\n  files unpersistable); `data[key]` gets serializable metadata\n  (`{ name, size, type }`) that survives reload, after which the file must\n  be picked again. `accept` filters the picker. File fields live in the flat\n  data pool (panel blocks or steps) — declaring one inside records/items\n  throws.\n- **`fill: true`** on a `custom` block drops the card chrome so the block\n  owns a large scrollable surface — the workspace main-area case.\n- **`ctx.viewerId`** is a stable anonymous id per viewer, always in the\n  personal scope. In a `shared` app it expresses \"one vote per person\" and\n  \"added by\" with no account system. It is available on the `ctx` that\n  `custom` blocks and chat tools receive; row/block actions receive it as a\n  third argument:\n\n```js\nrecords: {\n  fields: [{ key: \"nombre\", type: \"text\" }],\n  actions: [{\n    label: \"Votar\",\n    when: (r, viewerId) => !(r.votantes || []).includes(viewerId),\n    run: (r, d, viewerId) => { r.votantes = [...(r.votantes || []), viewerId]; },\n  }],\n  subtitle: (r) => (r.votantes || []).length + \" votos\",\n}\n```\n\n### Writing `custom` blocks that work\n\n`custom: (ctx) => ...` runs **during React render**. The rules below come\nfrom measured failures — each one is a way a model has actually broken a\ncustom block:\n\n- **Return a string or a React element — never a DOM element.**\n  `document.createElement(...)` as a return value is not renderable (React\n  error #31, contained in the block). To use a library that *writes into*\n  an element (QRCode, pdf.js, chart libs), give it a ref:\n\n```js\ncustom: (ctx) => {\n  const ref = React.useRef(null);\n  React.useEffect(() => {\n    if (!ref.current || !ctx.data.texto) return;\n    ref.current.innerHTML = \"\";\n    new QRCode(ref.current, { text: ctx.data.texto, width: 220, height: 220 });\n  }, [ctx.data.texto]);\n  return React.createElement(\"div\", { ref });\n}\n```\n\n- **React hooks are allowed** inside custom (`React.useState`,\n  `React.useEffect`, `React.useRef`) — it runs in a component's render, and\n  `React` is available as a global.\n- **State has exactly two homes.** Persistent or visible to other blocks →\n  `ctx.update((d) => { d.x = ... })` (the whole app re-renders and it's\n  saved). Ephemeral UI state → `React.useState`. **Never `createStore` for\n  UI state** — stores do not re-render the app; a parse result stored there\n  will compute correctly and never appear on screen.\n- **Async work over an uploaded file**: an effect keyed on the file, local\n  state for the result:\n\n```js\ncustom: (ctx) => {\n  const file = ctx.files.archivo;\n  const [rows, setRows] = React.useState(null);\n  React.useEffect(() => {\n    if (!file) { setRows(null); return; }\n    file.text().then((t) => setRows(t.trim().split(\"\\n\").map((l) => l.split(\",\"))));\n  }, [file]);\n  if (!file) return \"Subí un archivo para analizarlo.\";\n  if (!rows) return \"Analizando…\";\n  return React.createElement(/* tu tabla */);\n}\n```\n\n- **Never render a `<form>`.** The published-artifact iframe sandbox lacks\n  `allow-forms`: a form that works in preview dies on the phone. Inputs +\n  a button with `onClick` (plus Enter via `onKeyDown` if you want it) do\n  the same job — that is why every framework block is formless.\n- **Use the theme, not hardcoded colors.** The app ships a light AND dark\n  palette; a custom block painted with `#fff` backgrounds or `#dc2626`\n  reds looks broken the moment the viewer is in dark mode. Use the CSS\n  variables — `var(--caf-text)`, `var(--caf-muted)`, `var(--caf-accent)`,\n  `var(--caf-surface)`, `var(--caf-sunken)`, `var(--caf-border)`,\n  `var(--caf-danger)` — and `ctx.colors(n)` for chart-like series:\n\n```js\ncustom: (ctx) => React.createElement(\"div\", {\n  style: { background: \"var(--caf-sunken)\", color: \"var(--caf-text)\",\n           border: \"1px solid var(--caf-border)\", borderRadius: \"7px\", padding: \"0.6rem\" }\n}, \"se ve bien en ambos temas\")\n```\n\n- **Never write big strings into `data`.** Storage allows ~5MB per key and\n  the whole pool is one key: a data-URL preview of a photo written to\n  `d.preview` can kill persistence for the entire app. Big things (data\n  URLs, file contents, parse results) live in `React.useState` or come from\n  `ctx.files`; `data` holds what is small and serializable.\n- **Column grids ask `ctx.viewport`.** Half of artifact viewers are on a\n  phone. `ctx.viewport` is `\"mobile\"` (< 720px) or `\"desktop\"`, and the\n  block re-renders when it changes. A layout that lays columns side by side\n  (kanban boards, week calendars, dashboards of mini-cards) must stack or\n  reduce them on `\"mobile\"` — 3 columns squeezed into 390px are ~90px each\n  and unreadable:\n\n```js\ncustom: (ctx) => {\n  const cols = ctx.viewport === \"mobile\" ? \"1fr\" : \"repeat(3, 1fr)\";\n  return React.createElement(\"div\",\n    { style: { display: \"grid\", gridTemplateColumns: cols, gap: \"0.6rem\" } },\n    /* ...columnas... */);\n}\n```\n\n  As a safety net the framework never clips: custom content wider than the\n  screen scrolls horizontally instead of disappearing. But scrolling a\n  squeezed board is the fallback, not the design — branch on `ctx.viewport`.\n- Custom re-renders whenever `data` or `view` change; it receives the full\n  `ctx` (`data`, `update`, `view`, `files`, `viewerId`, `colors`,\n  `viewport`, `go`, `back`) and lives inside the block error boundary — a\n  bug in your custom code shows a named error in its slot, never a blank\n  app.\n\n## API reference\n\nEverything an app can declare, in one place.\n\n**Top-level keys**: `title`, `subtitle`, `theme: { seed }`, `layout`, `blocks`,\n`records`, `steps`, `chat`, `main`, `sidebar` (workspace panes), `documents`,\n`data`, `shared`, `libs`, `machine`, `brand`, `mobile: { nav: \"bottom\" }`.\nAnything else throws.\n\n**Layouts** (`layout:`): `panel` (default — grid of blocks), `records` (CRUD\nlist), `steps` (wizard), `chat` (conversation with Claude), `workspace`\n(main column + sidebar), `documents` (parallel documents in top tabs).\nEach requires its matching key (`blocks` / `records` / `steps` / `chat` /\n`main`+`sidebar` / `documents`).\n\n**Block types** (entries of `blocks`, `main`, `sidebar`, or a document's\n`blocks`): `fields`, `output`, `text`, `list`, `chart`, `timer`, `actions`,\n`chat`, `tabs`, `records`, `custom`. Any block also accepts `when: (d) => bool` (conditional\nvisibility) and `collapsible: true | \"collapsed\"` (accordion; needs `title`).\nOn every block `title` is the heading string; `list` additionally accepts a\nfunction as `title`, used as the per-row title (rows fall back to\n`r.title ?? r.name ?? r.label ?? r.text`). One type per entry, plus optional `title`, `empty`,\n`wide`. In the `records` layout, `blocks` render below the list (never on the\ndetail screen); their functions receive the same `data` object as everywhere\nelse — the collection lives at `d.records`.\n\n**Field types** (`type:` on any field): `text` (default), `textarea`,\n`number`, `money`, `percent`, `check` (checkbox), `date`, `select` (needs\n`options` — an array, or `(d) => [...]` for choices that come from the\napp's data, e.g. a \"who paid\" select fed by a user-entered group). Other field keys: `key` (required), `label`, `value` (initial),\n`required`, `min`, `max`, `step`, `placeholder`, `hint`, `rows`, `options`.\nAn unknown `type` throws naming the valid ones.\n\n**`records` keys**: `label`, `fields`, `title(r)`, `subtitle(r)`, `sort(a,b)`,\n`summary(all)`, `empty`, `search`, `compute`, `items`, `actions`. `id` is\nframework-assigned and reserved on records and items alike.\n\n**`steps` keys** (per step): `title`, `text`, `fields`, `result(d)`. Field\nkeys must be unique across steps.\n\n**`chat` keys**: `system` (string or `(d) => string`), `greeting`,\n`placeholder`, `tools`, `model`, `maxTokens`. Each tool:\n`{ description, input, run(input, ctx) }`.\n\n**Formats** (`format:` on output/chart/compute items): `money`, `percent`,\n`number`, `date`, `text` (explicit no-op). Anything else throws, contained\nto the block. `percent` expects 0–100 (pass `ratio * 100`, not the raw\nratio); a computed `NaN`/`Infinity` renders as \"—\", never as \"NaN\".\n`big: true` renders an item at hero size AND promotes its block to\nthe screen's one feature surface (accent-tinted card) — reserve it for the\nONE number that is the screen's main result (a total, a final score), not\nfor every stat; more than one hero per screen means no hero at all.\n\n**Quick-add pattern** — a lightweight alternative to `records` when you just\nneed \"type something, press a button, it lands in a list\". Put the action\nIN the fields block — it renders as the card's footer, visually owned by\nthe inputs it submits (a submit button in its own separate block is an\norphan card):\n\n```js\nblocks: [\n  { title: \"Agregar persona\",\n    fields: [{ key: \"nueva\", label: \"Persona\", type: \"text\" }],\n    actions: [{ label: \"Agregar\", kind: \"primary\", run: (d) => {\n      if (d.nueva && d.nueva.trim()) { d.personas = [...(d.personas || []), d.nueva.trim()]; d.nueva = \"\"; }\n    }}] },\n  { text: (d) => (d.personas || []).join(\", \") || \"Sin personas todavía\" },\n]\n```\n\n`{ fields, actions }` and `{ output, actions }` are the two legal\nblock-type pairs — actions render as that block's own footer, visibly\nowned by what they submit or control; any other combination still throws.\n\n## `storage`\n\nThin wrapper over `window.storage`, the persistence API Claude injects into a\n**published** Chat Artifact. Values are JSON-serialized for you. Two scopes:\npersonal (`storage.*`, one copy per viewer) and shared (`storage.shared.*`,\none copy for every viewer of the artifact).\n\n```js\nawait storage.set(\"theme\", \"dark\");\nawait storage.get(\"theme\", \"light\"); // \"dark\" — second arg is the fallback\nawait storage.list();                // [\"theme\", ...]\nawait storage.delete(\"theme\");\n\nawait storage.shared.set(\"board\", { count: 0 });\nawait storage.shared.get(\"board\", null);\n\nstorage.available(); // false in draft mode / outside a Chat Artifact\n```\n\n## `createStore(initialState)`\n\nIn-memory reactive store. No persistence.\n\n```js\nconst counter = createStore(0);\ncounter.subscribe((value) => console.log(\"count is now\", value));\ncounter.set((n) => n + 1);\ncounter.get(); // 1\n```\n\n## `createPersistedStore(key, initialState, options?)`\n\nSame as `createStore`, but loads from `storage` once on creation and saves\n(debounced) on every change. Personal scope only.\n\n```js\nconst prefs = createPersistedStore(\"prefs\", { theme: \"light\" });\nawait prefs.ready;           // resolves once the initial load finishes\nprefs.set({ theme: \"dark\" }); // persisted automatically\n```\n\n`options.debounceMs` (default `300`) controls how long to wait after the last\nchange before writing to storage.\n\n## `createSharedStore(key, initialState, options?)`\n\nSame as `createPersistedStore`, but backed by `storage.shared` and polled on\nan interval, so every viewer of a published artifact converges on the same\nstate.\n\n```js\nconst board = createSharedStore(\"board\", { count: 0 }, { pollMs: 2000 });\nawait board.ready;\nboard.set({ count: board.get().count + 1 }); // pushed to every viewer\nboard.stop(); // stop polling, e.g. on teardown\n```\n\nConflict handling is last-write-wins: if two viewers change the same key\nwithin one poll window, whichever write reaches storage last overwrites the\nother. There is no merge/CRDT logic.\n\n**Teammates' changes are visible by construction.** When another viewer's\nchange arrives, rows they added or edited in any records list flash the\naccent once — nothing to declare. For custom blocks, `ctx.remote` is\n`{ keys, at }` for the last remote change (`keys` = the top-level data\nkeys it touched, `at` = a `Date.now()` timestamp), or `null` before any:\n\n```js\ncustom: (ctx) => {\n  const fresh = ctx.remote && Date.now() - ctx.remote.at < 4000 && ctx.remote.keys.includes(\"tarjetas\");\n  return React.createElement(\"div\", { className: fresh ? \"mi-tablero pulso\" : \"mi-tablero\" }, /* ... */);\n}\n```\n\n## Design principles — composing a screen that reads\n\nThe framework owns the CSS, but whether a screen has visual hierarchy is\ndecided by choices only the SPEC can make. Every beautiful app follows\nthese; every generic-looking one breaks at least two:\n\n1. **One dominant element per screen.** Exactly one `big: true` stat — the\n   screen's answer (the total, the score, the net). It automatically\n   becomes the highlighted feature card. Zero heroes reads flat; two\n   heroes read as none.\n2. **Order blocks by importance, not by data model.** First what the user\n   DOES most (the quick-add, the main fields), then the hero result, then\n   breakdowns and charts, then history. Configuration, branding text, and\n   help go LAST — or inside `collapsible: \"collapsed\"` — never first.\n3. **Icons: all siblings or none.** If one tab/section gets an `icon`,\n   every tab/section in that same set gets one, same style (all emoji). A\n   half-iconed set reads as an accident. Don't use emoji as bullet points\n   inside stat labels or titles that already live in an iconed set.\n4. **Pick a mid-tone, saturated seed that names the domain** — warm\n   orange/red for food, teal/blue for finance, green for health. Grays and\n   near-blacks kill the entire accent system; neons burn it.\n5. **Never duplicate what the framework already renders.** No text block\n   repeating the app's own title (the header shows it), no hand-built\n   totals when `summary`/`output` computes them, no \"empty list\" messages.\n6. **Group; don't multiply cards.** Related inputs belong in ONE `fields`\n   block with one title, and their submit button belongs INSIDE it —\n   `{ fields: [...], actions: [...] }` renders the actions as the card's\n   footer. Secondary content goes into `tabs` or a collapsible. A first\n   screen with more than ~5 cards has no hierarchy left.\n7. **Say state with `when`, not with more blocks.** Hide what doesn't\n   apply right now instead of stacking every possibility on screen.\n8. **Charts are support, not wallpaper.** At most two per screen; `wide:\n   true` for time series; donuts only up to ~5 slices.\n\n## Hard rules — the short list\n\nThe rules that decide whether a generated app works, all in one place\n(each is explained in its section above):\n\n1. **Indented, never minified** — the only measured syntax errors came from\n   single-line output.\n2. **Theme variables, never hardcoded hex** — `var(--caf-text)`,\n   `var(--caf-surface)`, `var(--caf-accent)`, `var(--caf-border)`,\n   `var(--caf-sunken)`, `var(--caf-muted)`, `var(--caf-danger)`, and\n   `ctx.colors(n)` for series. A custom block painted with `#fff` or\n   `#ef4444` breaks in dark mode.\n3. **Never render a `<form>`** — the published sandbox lacks `allow-forms`;\n   use inputs plus a button with `onClick`.\n4. **Never write big strings into `data`** (data URLs, file contents) —\n   the whole pool shares one ~5MB key; big things live in `React.useState`\n   or `ctx.files`.\n5. **Phases belong to the `machine`** — never track game/process phases\n   with hand-rolled flags and `setTimeout`; `ctx.send` is the only door.\n6. **Row callbacks are `(record, data, viewerId)`** — `when` and `run`\n   alike. Prefer the full order; a second parameter literally named\n   `viewerId` is matched by name and still gets the viewer id.\n7. **One `big: true` per screen** — it marks THE result, not every stat.\n8. **The constructive action takes `kind: \"primary\"`**; a counter changed\n   by pressing is an `action`, not an editable `number` field.\n9. **Parts of a record are `items`** — never JSON in a `textarea`.\n10. **Don't hand-build empty/loading/error states** — the framework owns\n    them.\n11. **CDN libs: call the method, not the global** (`marked.parse`, not\n    `marked(...)`); pin versions; when unsure of the file path use the bare\n    package URL.\n12. **Framework ids are strings** — never `Number(record.id)`.\n13. **Brand is zero-asset-first** — monogram/gradient/emoji defaults before\n    URLs; inline `<svg>` over remote images; one icon style per app\n    (emoji-first); `avatar: true` instead of hand-built initials circles.\n14. **Column grids in `custom` branch on `ctx.viewport`** — stack kanban\n    columns / week grids when it says `\"mobile\"`; half the viewers are on\n    a phone.\n","readmeFilename":"README.md"}