[{"data":1,"prerenderedAt":2136},["ShallowReactive",2],{"navigation-landing-en":3,"navigation-nuxt-auto-en":180,"navigation-nuxt-protokit-en":365,"navigation-nuxt-cookie-consent-en":507,"\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fdocument-size-and-gc-en":549,"\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fdocument-size-and-gc-surround-en":2131},[4,8,13,28,41,51,64,77,94,110,134,150,157,172],{"title":5,"path":6,"stem":7},"Overview","\u002Fdocs\u002Flanding","0.docs\u002F1.landing\u002F001.index",{"title":9,"path":10,"stem":11,"badge":12},"Built-in Features","\u002Fdocs\u002Flanding\u002Fbuilt-in-features","0.docs\u002F1.landing\u002F002.built-in-features","New",{"title":14,"path":15,"stem":16,"children":17,"icon":27},"Content Foundation","\u002Fdocs\u002Flanding\u002Fcontent","0.docs\u002F1.landing\u002F02.content\u002F1.index",[18,19,23],{"title":5,"path":15,"stem":16},{"title":20,"path":21,"stem":22},"Details","\u002Fdocs\u002Flanding\u002Fcontent\u002Fdetails","0.docs\u002F1.landing\u002F02.content\u002F2.details",{"title":24,"path":25,"stem":26},"Technical","\u002Fdocs\u002Flanding\u002Fcontent\u002Ftechnical","0.docs\u002F1.landing\u002F02.content\u002F4.technical","i-heroicons-document-text",{"title":29,"path":30,"stem":31,"children":32,"icon":40},"Regional Content","\u002Fdocs\u002Flanding\u002Fregional","0.docs\u002F1.landing\u002F03.regional\u002F1.index",[33,34,37],{"title":5,"path":30,"stem":31},{"title":20,"path":35,"stem":36},"\u002Fdocs\u002Flanding\u002Fregional\u002Fdetails","0.docs\u002F1.landing\u002F03.regional\u002F2.details",{"title":24,"path":38,"stem":39},"\u002Fdocs\u002Flanding\u002Fregional\u002Ftechnical","0.docs\u002F1.landing\u002F03.regional\u002F4.technical","i-heroicons-globe-alt",{"title":42,"path":43,"stem":44,"children":45,"icon":50},"Multi-language","\u002Fdocs\u002Flanding\u002Fmultilang","0.docs\u002F1.landing\u002F04.multilang\u002F1.index",[46,47],{"title":5,"path":43,"stem":44},{"title":20,"path":48,"stem":49},"\u002Fdocs\u002Flanding\u002Fmultilang\u002Fdetails","0.docs\u002F1.landing\u002F04.multilang\u002F2.details","i-heroicons-language",{"title":52,"path":53,"stem":54,"children":55,"icon":63},"Blog","\u002Fdocs\u002Flanding\u002Fblog","0.docs\u002F1.landing\u002F05.blog\u002F1.index",[56,57,60],{"title":5,"path":53,"stem":54},{"title":20,"path":58,"stem":59},"\u002Fdocs\u002Flanding\u002Fblog\u002Fdetails","0.docs\u002F1.landing\u002F05.blog\u002F2.details",{"title":24,"path":61,"stem":62},"\u002Fdocs\u002Flanding\u002Fblog\u002Ftechnical","0.docs\u002F1.landing\u002F05.blog\u002F4.technical","i-heroicons-pencil-square",{"title":65,"path":66,"stem":67,"children":68,"icon":76},"Documentation","\u002Fdocs\u002Flanding\u002Fdocs","0.docs\u002F1.landing\u002F06.docs\u002F1.index",[69,70,73],{"title":5,"path":66,"stem":67},{"title":20,"path":71,"stem":72},"\u002Fdocs\u002Flanding\u002Fdocs\u002Fdetails","0.docs\u002F1.landing\u002F06.docs\u002F2.details",{"title":24,"path":74,"stem":75},"\u002Fdocs\u002Flanding\u002Fdocs\u002Ftechnical","0.docs\u002F1.landing\u002F06.docs\u002F4.technical","i-heroicons-book-open",{"title":78,"path":79,"stem":80,"children":81,"icon":93},"Forms","\u002Fdocs\u002Flanding\u002Fforms","0.docs\u002F1.landing\u002F07.forms\u002F1.index",[82,83,86,90],{"title":5,"path":79,"stem":80},{"title":20,"path":84,"stem":85},"\u002Fdocs\u002Flanding\u002Fforms\u002Fdetails","0.docs\u002F1.landing\u002F07.forms\u002F2.details",{"title":87,"path":88,"stem":89},"Admin","\u002Fdocs\u002Flanding\u002Fforms\u002Fadmin","0.docs\u002F1.landing\u002F07.forms\u002F3.admin",{"title":24,"path":91,"stem":92},"\u002Fdocs\u002Flanding\u002Fforms\u002Ftechnical","0.docs\u002F1.landing\u002F07.forms\u002F4.technical","i-heroicons-clipboard-document-list",{"title":95,"path":96,"stem":97,"children":98,"icon":109},"Email","\u002Fdocs\u002Flanding\u002Femail","0.docs\u002F1.landing\u002F08.email\u002F1.index",[99,100,103,106],{"title":5,"path":96,"stem":97},{"title":20,"path":101,"stem":102},"\u002Fdocs\u002Flanding\u002Femail\u002Fdetails","0.docs\u002F1.landing\u002F08.email\u002F2.details",{"title":87,"path":104,"stem":105},"\u002Fdocs\u002Flanding\u002Femail\u002Fadmin","0.docs\u002F1.landing\u002F08.email\u002F3.admin",{"title":24,"path":107,"stem":108},"\u002Fdocs\u002Flanding\u002Femail\u002Ftechnical","0.docs\u002F1.landing\u002F08.email\u002F4.technical","i-heroicons-envelope",{"title":111,"path":112,"stem":113,"children":114,"icon":133},"Feedback Platform","\u002Fdocs\u002Flanding\u002Ffeedback","0.docs\u002F1.landing\u002F09.feedback\u002F1.index",[115,116,119,122,125,129],{"title":5,"path":112,"stem":113},{"title":20,"path":117,"stem":118},"\u002Fdocs\u002Flanding\u002Ffeedback\u002Fdetails","0.docs\u002F1.landing\u002F09.feedback\u002F2.details",{"title":87,"path":120,"stem":121},"\u002Fdocs\u002Flanding\u002Ffeedback\u002Fadmin","0.docs\u002F1.landing\u002F09.feedback\u002F3.admin",{"title":24,"path":123,"stem":124},"\u002Fdocs\u002Flanding\u002Ffeedback\u002Ftechnical","0.docs\u002F1.landing\u002F09.feedback\u002F4.technical",{"title":126,"path":127,"stem":128},"Compare vs SaaS","\u002Fdocs\u002Flanding\u002Ffeedback\u002Fcompare","0.docs\u002F1.landing\u002F09.feedback\u002F5.compare",{"title":130,"path":131,"stem":132},"FAQ","\u002Fdocs\u002Flanding\u002Ffeedback\u002Ffaq","0.docs\u002F1.landing\u002F09.feedback\u002F6.faq","i-heroicons-chat-bubble-left-right",{"title":135,"path":136,"stem":137,"children":138,"icon":149},"Storage","\u002Fdocs\u002Flanding\u002Fstorage","0.docs\u002F1.landing\u002F10.storage\u002F1.index",[139,140,143,146],{"title":5,"path":136,"stem":137},{"title":20,"path":141,"stem":142},"\u002Fdocs\u002Flanding\u002Fstorage\u002Fdetails","0.docs\u002F1.landing\u002F10.storage\u002F2.details",{"title":87,"path":144,"stem":145},"\u002Fdocs\u002Flanding\u002Fstorage\u002Fadmin","0.docs\u002F1.landing\u002F10.storage\u002F3.admin",{"title":24,"path":147,"stem":148},"\u002Fdocs\u002Flanding\u002Fstorage\u002Ftechnical","0.docs\u002F1.landing\u002F10.storage\u002F4.technical","i-heroicons-circle-stack",{"title":151,"path":152,"stem":153,"children":154,"icon":156},"Offline First","\u002Fdocs\u002Flanding\u002Foffline-first","0.docs\u002F1.landing\u002F11.offline-first\u002F1.index",[155],{"title":151,"path":152,"stem":153},"i-heroicons-users",{"title":158,"path":159,"stem":160,"children":161,"icon":156},"Yjs Sync","\u002Fdocs\u002Flanding\u002Fyjs-sync","0.docs\u002F1.landing\u002F12.yjs-sync\u002F1.index",[162,163,166,169],{"title":5,"path":159,"stem":160},{"title":20,"path":164,"stem":165},"\u002Fdocs\u002Flanding\u002Fyjs-sync\u002Fdetails","0.docs\u002F1.landing\u002F12.yjs-sync\u002F2.details",{"title":87,"path":167,"stem":168},"\u002Fdocs\u002Flanding\u002Fyjs-sync\u002Fadmin","0.docs\u002F1.landing\u002F12.yjs-sync\u002F3.admin",{"title":24,"path":170,"stem":171},"\u002Fdocs\u002Flanding\u002Fyjs-sync\u002Ftechnical","0.docs\u002F1.landing\u002F12.yjs-sync\u002F4.technical",{"title":173,"path":174,"stem":175,"children":176,"badge":178,"icon":179},"Newsletter","\u002Fdocs\u002Flanding\u002Fnewsletter","0.docs\u002F1.landing\u002F13.newsletter\u002Findex",[177],{"title":173,"path":174,"stem":175,"badge":178},"Coming Soon","i-lucide-send",[181,184,202,318,358],{"title":5,"path":182,"stem":183},"\u002Fdocs\u002Fnuxt-auto","0.docs\u002F3.nuxt-auto\u002Findex",{"title":185,"path":186,"stem":187,"children":188,"page":201},"Getting Started","\u002Fdocs\u002Fnuxt-auto\u002Fgetting-started","0.docs\u002F3.nuxt-auto\u002F1.getting-started",[189,193,197],{"title":190,"path":191,"stem":192},"Introduction","\u002Fdocs\u002Fnuxt-auto\u002Fgetting-started\u002Fintroduction","0.docs\u002F3.nuxt-auto\u002F1.getting-started\u002F1.introduction",{"title":194,"path":195,"stem":196},"Installation","\u002Fdocs\u002Fnuxt-auto\u002Fgetting-started\u002Finstallation","0.docs\u002F3.nuxt-auto\u002F1.getting-started\u002F2.installation",{"title":198,"path":199,"stem":200},"Quick Start","\u002Fdocs\u002Fnuxt-auto\u002Fgetting-started\u002Fquick-start","0.docs\u002F3.nuxt-auto\u002F1.getting-started\u002F3.quick-start",false,{"title":203,"path":204,"stem":205,"children":206,"page":201},"Auto API","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api","0.docs\u002F3.nuxt-auto\u002F2.auto-api",[207,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,286,290,294,298,302,306,310,314],{"title":185,"path":208,"stem":209},"\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fgetting-started","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F1.getting-started",{"title":211,"path":212,"stem":213},"Aggregations","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Faggregations","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F10.aggregations",{"title":215,"path":216,"stem":217},"Lifecycle Hooks","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Flifecycle-hooks","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F11.lifecycle-hooks",{"title":219,"path":220,"stem":221},"Many-to-Many (M2M) Relationships","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fm2m-relationships","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F12.m2m-relationships",{"title":223,"path":224,"stem":225},"Plugin System","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fplugin-system","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F13.plugin-system",{"title":227,"path":228,"stem":229},"Database Adapters","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fdatabase-adapters","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F14.database-adapters",{"title":231,"path":232,"stem":233},"Custom Endpoints","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fcustom-endpoints","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F15.custom-endpoints",{"title":235,"path":236,"stem":237},"Multi-Tenancy","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fmulti-tenancy","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F16.multi-tenancy",{"title":239,"path":240,"stem":241},"Schema Presets (Cross-engine)","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fschema-presets","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F17.schema-presets",{"title":243,"path":244,"stem":245},"Permissions Cookbook","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fpermissions-cookbook","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F18.permissions-cookbook",{"title":247,"path":248,"stem":249},"Billing & Plan Gating","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fbilling","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F19.billing",{"title":251,"path":252,"stem":253},"Validation","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fvalidation","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F2.validation",{"title":255,"path":256,"stem":257},"Rate Limiting","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Frate-limiting","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F20.rate-limiting",{"title":259,"path":260,"stem":261},"Request Metadata Plugin","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Frequest-metadata","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F21.request-metadata",{"title":263,"path":264,"stem":265},"Plugin Catalog","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fplugin-catalog","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F22.plugin-catalog",{"title":267,"path":268,"stem":269},"Configuration Reference","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fconfiguration","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F23.configuration",{"title":271,"path":272,"stem":273},"Handler Overrides","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fhandler-overrides","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F3.handler-overrides",{"title":275,"path":276,"stem":277},"Cloudflare D1","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fcloudflare-d1","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F30.cloudflare-d1",{"title":279,"path":280,"stem":281},"SQLite to D1 Migration","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fmigration-sqlite-d1","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F31.migration-sqlite-d1",{"title":283,"path":284,"stem":285},"Frontend Composables","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Ffrontend-composables","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F32.frontend-composables",{"title":287,"path":288,"stem":289},"Testing","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Ftesting","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F33.testing",{"title":291,"path":292,"stem":293},"Pagination","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fpagination","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F4.pagination",{"title":295,"path":296,"stem":297},"Upgrading","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fupgrading","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F40.upgrading",{"title":299,"path":300,"stem":301},"Soft Deletes","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fsoft-deletes","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F5.soft-deletes",{"title":303,"path":304,"stem":305},"Authentication & Authorization","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fauthentication-authorization","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F6.authentication-authorization",{"title":307,"path":308,"stem":309},"Better-Auth Integration","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fbetter-auth","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F7.better-auth",{"title":311,"path":312,"stem":313},"Nested Relations","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fnested-relationships","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F8.nested-relationships",{"title":315,"path":316,"stem":317},"Bulk Operations","\u002Fdocs\u002Fnuxt-auto\u002Fauto-api\u002Fbulk-operations","0.docs\u002F3.nuxt-auto\u002F2.auto-api\u002F9.bulk-operations",{"title":319,"path":320,"stem":321,"children":322,"page":201},"Auto Admin","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin","0.docs\u002F3.nuxt-auto\u002F3.auto-admin",[323,326,330,334,338,342,346,350,354],{"title":185,"path":324,"stem":325},"\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fgetting-started","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F1.getting-started",{"title":327,"path":328,"stem":329},"Configuration & Theming","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fconfiguration-theming","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F2.configuration-theming",{"title":331,"path":332,"stem":333},"Resource Configuration","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fresource-configuration","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F3.resource-configuration",{"title":335,"path":336,"stem":337},"Form Fields & Widgets","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fform-fields-widgets","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F4.form-fields-widgets",{"title":339,"path":340,"stem":341},"Permissions","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fpermissions","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F5.permissions",{"title":343,"path":344,"stem":345},"Custom Pages","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fcustom-pages","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F6.custom-pages",{"title":347,"path":348,"stem":349},"M2M Relationships","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fm2m-relationships","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F7.m2m-relationships",{"title":351,"path":352,"stem":353},"Custom Actions","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fcustom-actions","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F8.custom-actions",{"title":355,"path":356,"stem":357},"Composables","\u002Fdocs\u002Fnuxt-auto\u002Fauto-admin\u002Fcomposables","0.docs\u002F3.nuxt-auto\u002F3.auto-admin\u002F9.composables",{"title":359,"path":360,"stem":361,"children":362,"icon":364},"Claude Code Skills","\u002Fdocs\u002Fnuxt-auto\u002Fclaude-code-skills","0.docs\u002F3.nuxt-auto\u002F4.claude-code-skills\u002F1.index",[363],{"title":5,"path":360,"stem":361},"i-lucide-bot",[366,369,382,409,427,450,472,502],{"title":5,"path":367,"stem":368},"\u002Fdocs\u002Fnuxt-protokit","0.docs\u002F4.nuxt-protokit\u002Findex",{"title":185,"path":370,"stem":371,"children":372,"icon":381},"\u002Fdocs\u002Fnuxt-protokit\u002Fgetting-started","0.docs\u002F4.nuxt-protokit\u002F1.getting-started\u002F1.index",[373,374,378],{"title":190,"path":370,"stem":371},{"title":375,"path":376,"stem":377},"Core Concepts","\u002Fdocs\u002Fnuxt-protokit\u002Fgetting-started\u002Fconcepts","0.docs\u002F4.nuxt-protokit\u002F1.getting-started\u002F2.concepts",{"title":198,"path":379,"stem":380},"\u002Fdocs\u002Fnuxt-protokit\u002Fgetting-started\u002Fquick-start","0.docs\u002F4.nuxt-protokit\u002F1.getting-started\u002F3.quick-start","i-lucide-rocket",{"title":383,"path":384,"stem":385,"children":386,"icon":408},"Schemas","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F1.index",[387,388,392,396,400,404],{"title":5,"path":384,"stem":385},{"title":389,"path":390,"stem":391},"Field Types","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas\u002Ffields","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F2.fields",{"title":393,"path":394,"stem":395},"Collections","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas\u002Fcollections","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F3.collections",{"title":397,"path":398,"stem":399},"Derived & Computed","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas\u002Fderived-computed","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F4.derived-computed",{"title":401,"path":402,"stem":403},"Connections","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas\u002Fconnections","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F5.connections",{"title":405,"path":406,"stem":407},"Visualizations & Layouts","\u002Fdocs\u002Fnuxt-protokit\u002Fschemas\u002Fvisualizations","0.docs\u002F4.nuxt-protokit\u002F2.schemas\u002F6.visualizations","i-lucide-file-code",{"title":355,"path":410,"stem":411,"children":412,"icon":426},"\u002Fdocs\u002Fnuxt-protokit\u002Fcomposables","0.docs\u002F4.nuxt-protokit\u002F3.composables\u002F1.index",[413,414,418,422],{"title":5,"path":410,"stem":411},{"title":415,"path":416,"stem":417},"usePrototype","\u002Fdocs\u002Fnuxt-protokit\u002Fcomposables\u002Fuse-prototype","0.docs\u002F4.nuxt-protokit\u002F3.composables\u002F2.use-prototype",{"title":419,"path":420,"stem":421},"useProtoDoc","\u002Fdocs\u002Fnuxt-protokit\u002Fcomposables\u002Fuse-proto-doc","0.docs\u002F4.nuxt-protokit\u002F3.composables\u002F3.use-proto-doc",{"title":423,"path":424,"stem":425},"useProtoCollection","\u002Fdocs\u002Fnuxt-protokit\u002Fcomposables\u002Fuse-proto-collection","0.docs\u002F4.nuxt-protokit\u002F3.composables\u002F4.use-proto-collection","i-lucide-layers",{"title":428,"path":429,"stem":430,"children":431,"icon":449},"Components","\u002Fdocs\u002Fnuxt-protokit\u002Fcomponents","0.docs\u002F4.nuxt-protokit\u002F4.components\u002F1.index",[432,433,437,441,445],{"title":5,"path":429,"stem":430},{"title":434,"path":435,"stem":436},"ProtoTool","\u002Fdocs\u002Fnuxt-protokit\u002Fcomponents\u002Fproto-tool","0.docs\u002F4.nuxt-protokit\u002F4.components\u002F2.proto-tool",{"title":438,"path":439,"stem":440},"ProtoCrudModal","\u002Fdocs\u002Fnuxt-protokit\u002Fcomponents\u002Fproto-crud-modal","0.docs\u002F4.nuxt-protokit\u002F4.components\u002F3.proto-crud-modal",{"title":442,"path":443,"stem":444},"ProtoCalendar","\u002Fdocs\u002Fnuxt-protokit\u002Fcomponents\u002Fproto-calendar","0.docs\u002F4.nuxt-protokit\u002F4.components\u002F4.proto-calendar",{"title":446,"path":447,"stem":448},"ProtoItemPanel variants","\u002Fdocs\u002Fnuxt-protokit\u002Fcomponents\u002Fproto-item-panels","0.docs\u002F4.nuxt-protokit\u002F4.components\u002F5.proto-item-panels","i-lucide-puzzle",{"title":151,"path":451,"stem":452,"children":453,"icon":471},"\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first","0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F1.index",[454,455,459,463,467],{"title":151,"path":451,"stem":452},{"title":456,"path":457,"stem":458},"Corruption Recovery","\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fcorruption-recovery","0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F2.corruption-recovery",{"title":460,"path":461,"stem":462},"Size & GC","\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fdocument-size-and-gc","0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F3.document-size-and-gc",{"title":464,"path":465,"stem":466},"Multi-tenant Isolation","\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fmulti-tenant-isolation","0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F4.multi-tenant-isolation",{"title":468,"path":469,"stem":470},"Encryption at Rest","\u002Fdocs\u002Fnuxt-protokit\u002Foffline-first\u002Fencryption","0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F5.encryption","i-lucide-wifi-off",{"title":473,"icon":474,"path":475,"stem":476,"children":477},"Advanced","i-lucide-graduation-cap","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F1.index",[478,479,483,487,491,494,498],{"title":5,"path":475,"stem":476},{"title":480,"path":481,"stem":482},"Multi-Tool Apps","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fbuilding-a-toolkit","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F1.building-a-toolkit",{"title":484,"path":485,"stem":486},"Schema Patterns","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fcustom-schema-patterns","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F2.custom-schema-patterns",{"title":488,"path":489,"stem":490},"Custom Fields & Viz","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fextensibility","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F3.extensibility",{"title":339,"path":492,"stem":493},"\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fpermissions","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F4.permissions",{"title":495,"path":496,"stem":497},"Business Logic Guards","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fpermissions-business-logic","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F5.permissions-business-logic",{"title":499,"path":500,"stem":501},"Headless Mode","\u002Fdocs\u002Fnuxt-protokit\u002Fadvanced\u002Fheadless-mode","0.docs\u002F4.nuxt-protokit\u002F6.advanced\u002F6.headless-mode",{"title":359,"path":503,"stem":504,"children":505,"icon":364},"\u002Fdocs\u002Fnuxt-protokit\u002Fclaude-code-skills","0.docs\u002F4.nuxt-protokit\u002F7.claude-code-skills\u002F1.index",[506],{"title":5,"path":503,"stem":504},[508,511],{"title":5,"path":509,"stem":510},"\u002Fdocs\u002Fnuxt-cookie-consent","0.docs\u002F5.nuxt-cookie-consent\u002Findex",{"title":512,"icon":513,"path":514,"stem":515,"children":516,"page":201},"Guide","i-lucide-book-open","\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide",[517,521,525,530,535,539,544],{"title":190,"path":518,"stem":519,"icon":520},"\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fintroduction","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F1.introduction","i-lucide-info",{"title":194,"path":522,"stem":523,"icon":524},"\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Finstallation","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F2.installation","i-lucide-download",{"title":526,"path":527,"stem":528,"icon":529},"Configuration","\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fconfiguration","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F3.configuration","i-lucide-settings-2",{"title":531,"path":532,"stem":533,"icon":534},"Usage","\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fusage","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F4.usage","i-lucide-play",{"title":355,"path":536,"stem":537,"icon":538},"\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fcomposables","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F5.composables","i-lucide-function-square",{"title":540,"path":541,"stem":542,"icon":543},"Components & overriding","\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fcomponents","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F6.components","i-lucide-component",{"title":545,"path":546,"stem":547,"icon":548},"Internationalization","\u002Fdocs\u002Fnuxt-cookie-consent\u002Fguide\u002Fi18n","0.docs\u002F5.nuxt-cookie-consent\u002F1.guide\u002F7.i18n","i-lucide-languages",{"page":550,"fallbackPage":2126},{"id":551,"title":552,"body":553,"description":2124,"extension":2125,"links":2126,"meta":2127,"navigation":2128,"ogImage":2126,"path":461,"seo":2129,"stem":462,"__hash__":2130},"nuxt_protokit\u002F0.docs\u002F4.nuxt-protokit\u002F5.offline-first\u002F3.document-size-and-gc.md","Document Size & Garbage Collection",{"type":554,"value":555,"toc":2092},"minimark",[556,561,565,570,591,598,608,619,623,634,639,673,677,688,694,698,705,709,763,766,770,776,780,809,815,819,830,879,883,893,897,900,958,962,965,1011,1015,1018,1100,1106,1110,1113,1173,1180,1184,1194,1201,1205,1208,1334,1347,1350,1356,1359,1363,1372,1488,1491,1514,1532,1536,1544,1547,1573,1577,1765,1769,1778,1784,1790,1794,1797,1849,1852,1856,1859,1869,1884,1887,1893,1897,1900,1934,1948,1952,1955,1974,1977,2088],[557,558,560],"h1",{"id":559},"document-size-and-garbage-collection","Document Size and Garbage Collection",[562,563,564],"p",{},"Y.js documents grow with every edit — not just the current state, but the full history of changes. Garbage collection, struct merging, and IndexedDB compaction keep that growth under control automatically.",[566,567,569],"h2",{"id":568},"how-yjs-stores-changes","How Y.js stores changes",[562,571,572,573,577,578,581,582,585,586,590],{},"Every ",[574,575,576],"code",{},"Y.Map.set()",", ",[574,579,580],{},"Y.Array.push()",", or ",[574,583,584],{},"Y.Text.insert()"," creates an internal ",[587,588,589],"strong",{},"Item"," struct. Y.js never discards these structs outright because they carry metadata that other clients need for conflict-free sync.",[562,592,593,594,597],{},"When you overwrite a map key 100 times, the document contains 100 Items for that key — one per write. The current value is the latest Item; previous Items are marked ",[587,595,596],{},"deleted",".",[599,600,605],"pre",{"className":601,"code":603,"language":604},[602],"language-text","map.set('title', 'Draft')     →  Item { id: (1,0), content: \"Draft\" }\nmap.set('title', 'Final')     →  Item { id: (1,1), content: \"Final\" }\n                                  Item { id: (1,0), content: DELETED }\n","text",[574,606,603],{"__ignoreMap":607},"",[562,609,610,611,614,615,618],{},"The deleted Item retains its ",[574,612,613],{},"id"," (client + clock) so that other peers can reference it during sync. The actual string ",[574,616,617],{},"\"Draft\""," is garbage collected — only a compact metadata stub remains.",[566,620,622],{"id":621},"garbage-collection","Garbage collection",[562,624,625,626,629,630,633],{},"Y.js runs garbage collection automatically after every transaction when ",[574,627,628],{},"gc: true"," (the default). GC replaces the ",[587,631,632],{},"content"," of deleted Items with a lightweight marker.",[635,636,638],"h3",{"id":637},"what-gc-does","What GC does",[640,641,642,653,663],"ol",{},[643,644,645,648,649,652],"li",{},[587,646,647],{},"Content removal"," — deleted Item content becomes ",[574,650,651],{},"ContentDeleted(length)",", a fixed-size struct regardless of original value size.",[643,654,655,658,659,662],{},[587,656,657],{},"Struct merging"," — adjacent deleted Items from the same client collapse into a single ",[574,660,661],{},"GC"," struct. Ten consecutive deletions become one struct.",[643,664,665,668,669,672],{},[587,666,667],{},"Adjacent merge"," — consecutive insertions from the same client merge their content. Typing \"hello\" in five keystrokes produces one Item with content ",[574,670,671],{},"\"hello\"",", not five separate Items.",[635,674,676],{"id":675},"when-gc-runs","When GC runs",[562,678,679,680,683,684,687],{},"GC runs inside ",[574,681,682],{},"cleanupTransactions()"," at the end of every ",[574,685,686],{},"doc.transact()"," call. You do not need to trigger it manually.",[599,689,692],{"className":690,"code":691,"language":604},[602],"doc.transact(() => {\n  map.set('title', 'New value')   \u002F\u002F marks old Item as deleted\n})\n\u002F\u002F ← GC runs here automatically\n\u002F\u002F    old Item content replaced with ContentDeleted\n\u002F\u002F    adjacent deleted structs merged\n",[574,693,691],{"__ignoreMap":607},[635,695,697],{"id":696},"what-gc-preserves","What GC preserves",[562,699,700,701,704],{},"GC removes content but preserves the ",[587,702,703],{},"causal metadata"," — the Item's client ID, clock, and left\u002Fright origin references. This metadata is essential for sync: without it, a peer applying an update that references the deleted Item would fail to find its insertion position.",[635,706,708],{"id":707},"the-impact-of-gc","The impact of GC",[710,711,712,731],"table",{},[713,714,715],"thead",{},[716,717,718,722,725,728],"tr",{},[719,720,721],"th",{},"Workload",[719,723,724],{},"gc=true",[719,726,727],{},"gc=false",[719,729,730],{},"Savings",[732,733,734,749],"tbody",{},[716,735,736,740,743,746],{},[737,738,739],"td",{},"5 fields overwritten 1,000 times",[737,741,742],{},"44 KB",[737,744,745],{},"117 KB",[737,747,748],{},"2.7x smaller",[716,750,751,754,757,760],{},[737,752,753],{},"3 fields overwritten 10,000 times",[737,755,756],{},"277 KB",[737,758,759],{},"~800 KB",[737,761,762],{},"~3x smaller",[562,764,765],{},"GC is always enabled in protokit. There is no reason to disable it for prototyping workloads.",[566,767,769],{"id":768},"indexeddb-compaction","IndexedDB compaction",[562,771,772,775],{},[574,773,774],{},"y-indexeddb"," stores every Y.js update as a separate IndexedDB entry. Over time, hundreds of small entries accumulate. The library compacts them automatically.",[635,777,779],{"id":778},"how-compaction-works","How compaction works",[640,781,782,787,796,803,806],{},[643,783,572,784,786],{},[574,785,686],{}," produces one incremental update (~30–100 bytes). This update is appended to IndexedDB immediately.",[643,788,789,790,577,793,795],{},"When the update count reaches ",[587,791,792],{},"500",[574,794,774],{}," triggers compaction.",[643,797,798,799,802],{},"Compaction calls ",[574,800,801],{},"Y.encodeStateAsUpdate(doc)"," — a single binary blob representing the entire document state with all merging and GC applied.",[643,804,805],{},"The single blob replaces all 500+ previous entries in IndexedDB.",[643,807,808],{},"The update counter resets to zero.",[599,810,813],{"className":811,"code":812,"language":604},[602],"Update #1   ┐\nUpdate #2   │  500 small entries in IndexedDB\n...         │  (total: ~25 KB across 500 rows)\nUpdate #500 ┘\n        │\n        ▼  compaction trigger\nSingle encoded state  ←  one IndexedDB entry (~8 KB)\n",[574,814,812],{"__ignoreMap":607},[635,816,818],{"id":817},"what-compaction-achieves","What compaction achieves",[562,820,821,822,825,826,829],{},"Compaction reduces both storage size and read latency. Loading 500 individual IndexedDB entries on page load is slower than loading one pre-merged blob. The size reduction depends on the workload — typically ",[587,823,824],{},"2–3x smaller"," because ",[574,827,828],{},"encodeStateAsUpdate()"," produces optimally merged structs.",[710,831,832,845],{},[713,833,834],{},[716,835,836,839,842],{},[719,837,838],{},"Metric",[719,840,841],{},"Before compaction (500 updates)",[719,843,844],{},"After compaction",[732,846,847,857,868],{},[716,848,849,852,854],{},[737,850,851],{},"IndexedDB entries",[737,853,792],{},[737,855,856],{},"1",[716,858,859,862,865],{},[737,860,861],{},"Total stored bytes",[737,863,864],{},"~52 KB",[737,866,867],{},"~18 KB",[716,869,870,873,876],{},[737,871,872],{},"Load time on mount",[737,874,875],{},"~50 ms",[737,877,878],{},"~10 ms",[566,880,882],{"id":881},"size-benchmarks","Size benchmarks",[562,884,885,886,888,889,892],{},"All benchmarks use ",[574,887,628],{}," (default). Sizes represent ",[574,890,891],{},"Y.encodeStateAsUpdate(doc).byteLength"," — the wire format stored in IndexedDB and sent to the server.",[635,894,896],{"id":895},"overwriting-map-keys","Overwriting map keys",[562,898,899],{},"Simulates form fields edited repeatedly (the most common protokit workload).",[710,901,902,915],{},[713,903,904],{},[716,905,906,909,912],{},[719,907,908],{},"Updates",[719,910,911],{},"Doc size",[719,913,914],{},"Notes",[732,916,917,928,938,948],{},[716,918,919,922,925],{},[737,920,921],{},"10",[737,923,924],{},"327 B",[737,926,927],{},"3 keys, negligible",[716,929,930,933,936],{},[737,931,932],{},"100",[737,934,935],{},"2.6 KB",[737,937],{},[716,939,940,943,946],{},[737,941,942],{},"1,000",[737,944,945],{},"26 KB",[737,947],{},[716,949,950,953,955],{},[737,951,952],{},"10,000",[737,954,756],{},[737,956,957],{},"Extreme — 10K edits to 3 fields",[635,959,961],{"id":960},"growing-a-collection","Growing a collection",[562,963,964],{},"Simulates adding items to a CRUD list.",[710,966,967,979],{},[713,968,969],{},[716,970,971,974,976],{},[719,972,973],{},"Items",[719,975,911],{},[719,977,978],{},"Per-item overhead",[732,980,981,992,1001],{},[716,982,983,986,989],{},[737,984,985],{},"50",[737,987,988],{},"6.2 KB",[737,990,991],{},"~124 B",[716,993,994,996,999],{},[737,995,932],{},[737,997,998],{},"12.4 KB",[737,1000,991],{},[716,1002,1003,1005,1008],{},[737,1004,942],{},[737,1006,1007],{},"126 KB",[737,1009,1010],{},"~126 B",[635,1012,1014],{"id":1013},"task-manager-with-rich-content","Task manager with rich content",[562,1016,1017],{},"100 tasks with multi-paragraph descriptions, comments, subtasks, and heavy editing over time.",[710,1019,1020,1032],{},[713,1021,1022],{},[716,1023,1024,1027,1029],{},[719,1025,1026],{},"Phase",[719,1028,911],{},[719,1030,1031],{},"Growth",[732,1033,1034,1045,1056,1067,1078,1089],{},[716,1035,1036,1039,1042],{},[737,1037,1038],{},"100 tasks created (with descriptions, comments, subtasks)",[737,1040,1041],{},"208 KB",[737,1043,1044],{},"—",[716,1046,1047,1050,1053],{},[737,1048,1049],{},"+ 20 rounds of description rewrites",[737,1051,1052],{},"216 KB",[737,1054,1055],{},"+8 KB",[716,1057,1058,1061,1064],{},[737,1059,1060],{},"+ 700 status changes",[737,1062,1063],{},"232 KB",[737,1065,1066],{},"+16 KB",[716,1068,1069,1072,1075],{},[737,1070,1071],{},"+ 340 new comments added",[737,1073,1074],{},"342 KB",[737,1076,1077],{},"+110 KB",[716,1079,1080,1083,1086],{},[737,1081,1082],{},"+ 50 title renames",[737,1084,1085],{},"343 KB",[737,1087,1088],{},"+1 KB",[716,1090,1091,1094,1097],{},[737,1092,1093],{},"+ 20 delete\u002Frecreate cycles",[737,1095,1096],{},"299 KB",[737,1098,1099],{},"-45 KB (GC)",[562,1101,1102,1103,597],{},"The final 299 KB document contains 266 KB of actual JSON data — ",[587,1104,1105],{},"Y.js overhead is only 1.1x",[635,1107,1109],{"id":1108},"long-term-daily-usage","Long-term daily usage",[562,1111,1112],{},"Simulates 2 years of daily task manager usage: 5 tasks created per day, 20 status changes, 10 description edits, 3 tasks archived.",[710,1114,1115,1127],{},[713,1116,1117],{},[716,1118,1119,1122,1124],{},[719,1120,1121],{},"Timeline",[719,1123,911],{},[719,1125,1126],{},"Active tasks",[732,1128,1129,1140,1151,1162],{},[716,1130,1131,1134,1137],{},[737,1132,1133],{},"1 month",[737,1135,1136],{},"28 KB",[737,1138,1139],{},"90",[716,1141,1142,1145,1148],{},[737,1143,1144],{},"6 months",[737,1146,1147],{},"125 KB",[737,1149,1150],{},"390",[716,1152,1153,1156,1159],{},[737,1154,1155],{},"1 year",[737,1157,1158],{},"252 KB",[737,1160,1161],{},"760",[716,1163,1164,1167,1170],{},[737,1165,1166],{},"2 years",[737,1168,1169],{},"502 KB",[737,1171,1172],{},"1,490",[562,1174,1175,1176,1179],{},"After two full years of daily usage, the document is ",[587,1177,1178],{},"~500 KB"," — smaller than a single photograph.",[566,1181,1183],{"id":1182},"gc-in-action","GC in action",[562,1185,1186,1187,1189,1190,1193],{},"The best way to see garbage collection work is to run the same operations on two identical documents — one with ",[574,1188,628],{}," and one with ",[574,1191,1192],{},"gc: false"," — and compare sizes.",[562,1195,1196,1197,1200],{},"All numbers below come from actual Y.js simulations. Run the scripts yourself in ",[574,1198,1199],{},"packages\u002Fnuxt-protokit\u002Fscripts\u002F"," to reproduce them.",[635,1202,1204],{"id":1203},"watching-gc-on-every-overwrite","Watching GC on every overwrite",[562,1206,1207],{},"A single task with a ~500-character description is overwritten repeatedly. Both docs perform the same operations:",[710,1209,1210,1227],{},[713,1211,1212],{},[716,1213,1214,1217,1219,1221,1224],{},[719,1215,1216],{},"Overwrite",[719,1218,724],{},[719,1220,727],{},[719,1222,1223],{},"GC savings",[719,1225,1226],{},"What GC did",[732,1228,1229,1249,1266,1283,1298,1316],{},[716,1230,1231,1233,1236,1239,1242],{},[737,1232,856],{},[737,1234,1235],{},"615 B",[737,1237,1238],{},"1.0 KB",[737,1240,1241],{},"1.7x",[737,1243,1244,1245,1248],{},"Old description content → ",[574,1246,1247],{},"ContentDeleted(1)"," stub",[716,1250,1251,1254,1257,1260,1263],{},[737,1252,1253],{},"2",[737,1255,1256],{},"630 B",[737,1258,1259],{},"1.5 KB",[737,1261,1262],{},"2.5x",[737,1264,1265],{},"Adjacent deleted structs merged",[716,1267,1268,1271,1274,1277,1280],{},[737,1269,1270],{},"3",[737,1272,1273],{},"579 B",[737,1275,1276],{},"1.9 KB",[737,1278,1279],{},"3.4x",[737,1281,1282],{},"Same: strip content, merge stubs",[716,1284,1285,1288,1290,1293,1296],{},[737,1286,1287],{},"5",[737,1289,1256],{},[737,1291,1292],{},"2.9 KB",[737,1294,1295],{},"4.7x",[737,1297],{},[716,1299,1300,1302,1305,1308,1313],{},[737,1301,921],{},[737,1303,1304],{},"627 B",[737,1306,1307],{},"5.2 KB",[737,1309,1310],{},[587,1311,1312],{},"8.5x",[737,1314,1315],{},"10 old strings retained vs 2 tiny stubs",[716,1317,1318,1320,1323,1326,1331],{},[737,1319,932],{},[737,1321,1322],{},"621 B",[737,1324,1325],{},"46.7 KB",[737,1327,1328],{},[587,1329,1330],{},"76.9x",[737,1332,1333],{},"100 old strings retained vs 2 tiny stubs",[562,1335,1336,1337,1339,1340,1343,1344,1346],{},"The ",[574,1338,724],{}," doc stays under ",[587,1341,1342],{},"630 bytes"," regardless of how many times you overwrite. The ",[574,1345,727],{}," doc grows linearly because every old string is retained.",[562,1348,1349],{},"Internally, this is what GC does to each deleted Item:",[599,1351,1354],{"className":1352,"code":1353,"language":604},[602],"Before GC: Item { id:(1,5), deleted:true, content:\"## Overview\\nTask 5: Dashboard...\" }  ← ~500 bytes\nAfter GC:  Item { id:(1,5), deleted:true, content:ContentDeleted(1) }                   ← 8 bytes\n",[574,1355,1353],{"__ignoreMap":607},[562,1357,1358],{},"The Item ID stays (needed for sync) but the string content is gone.",[635,1360,1362],{"id":1361},"gc-on-mixed-crud-operations","GC on mixed CRUD operations",[562,1364,1365,1366,1368,1369,1371],{},"A more realistic workload — 10 tasks with descriptions, status changes, comments, and deletions. Every operation runs on both a ",[574,1367,724],{}," and ",[574,1370,727],{}," doc:",[710,1373,1374,1387],{},[713,1375,1376],{},[716,1377,1378,1381,1383,1385],{},[719,1379,1380],{},"Operation",[719,1382,724],{},[719,1384,727],{},[719,1386,1223],{},[732,1388,1389,1402,1415,1429,1445,1458,1472],{},[716,1390,1391,1394,1397,1399],{},[737,1392,1393],{},"Create 10 tasks with descriptions",[737,1395,1396],{},"5.4 KB",[737,1398,1396],{},[737,1400,1401],{},"1.0x",[716,1403,1404,1407,1410,1413],{},[737,1405,1406],{},"+ Rename all 10 titles",[737,1408,1409],{},"5.6 KB",[737,1411,1412],{},"5.7 KB",[737,1414,1401],{},[716,1416,1417,1420,1423,1426],{},[737,1418,1419],{},"+ 50 status changes (5 rounds × 10)",[737,1421,1422],{},"6.0 KB",[737,1424,1425],{},"6.5 KB",[737,1427,1428],{},"1.1x",[716,1430,1431,1434,1437,1440],{},[737,1432,1433],{},"+ 30 description rewrites (3 rounds × 10)",[737,1435,1436],{},"6.4 KB",[737,1438,1439],{},"20.7 KB",[737,1441,1442],{},[587,1443,1444],{},"3.2x",[716,1446,1447,1450,1452,1455],{},[737,1448,1449],{},"+ Delete 5 tasks, add 5 new",[737,1451,988],{},[737,1453,1454],{},"23.4 KB",[737,1456,1457],{},"3.8x",[716,1459,1460,1463,1466,1469],{},[737,1461,1462],{},"+ Add 30 comments (3 per task)",[737,1464,1465],{},"14.8 KB",[737,1467,1468],{},"32.1 KB",[737,1470,1471],{},"2.2x",[716,1473,1474,1477,1480,1483],{},[737,1475,1476],{},"+ 100 more description rewrites",[737,1478,1479],{},"15.8 KB",[737,1481,1482],{},"79.8 KB",[737,1484,1485],{},[587,1486,1487],{},"5.1x",[562,1489,1490],{},"Two patterns emerge:",[1492,1493,1494,1504],"ul",{},[643,1495,1496,1499,1500,1503],{},[587,1497,1498],{},"Pure appends"," (creating tasks, adding comments) show ",[587,1501,1502],{},"no GC benefit"," — nothing is deleted, so there is nothing to collect.",[643,1505,1506,1509,1510,1513],{},[587,1507,1508],{},"Overwrites of large values"," (description rewrites) show ",[587,1511,1512],{},"the largest GC benefit"," — each ~500-byte string is replaced with an 8-byte stub.",[562,1515,1516,1517,1519,1520,1522,1523,1525,1526,1528,1529,597],{},"After all operations: ",[574,1518,724],{}," has 180 alive items + 150 deleted stubs + 48 GC structs at ",[587,1521,1479],{},". The ",[574,1524,727],{}," doc retains all original content at ",[587,1527,1482],{}," — GC saved ",[587,1530,1531],{},"64 KB",[566,1533,1535],{"id":1534},"multi-user-stress-test","Multi-user stress test",[562,1537,1538,1539,1368,1541,1543],{},"Three users — Alice, Bob, and Carol — collaborate on a task manager through a central server over two simulated years. The simulation runs identical operations on parallel ",[574,1540,724],{},[574,1542,727],{}," document sets to measure GC savings at every checkpoint.",[635,1545,721],{"id":1546},"workload",[1492,1548,1549,1555,1561,1567,1570],{},[643,1550,1551,1554],{},[587,1552,1553],{},"Alice"," creates 2 tasks per day and makes 5 edits (description rewrites, status changes, comments).",[643,1556,1557,1560],{},[587,1558,1559],{},"Bob"," makes 8 edits per day (status changes, reassignments, comments).",[643,1562,1563,1566],{},[587,1564,1565],{},"Carol"," joins at month 3 and makes 4 edits per day.",[643,1568,1569],{},"All three sync with the server daily.",[643,1571,1572],{},"1 completed task is archived every 3 days.",[635,1574,1576],{"id":1575},"results","Results",[710,1578,1579,1597],{},[713,1580,1581],{},[716,1582,1583,1586,1588,1590,1592,1594],{},[719,1584,1585],{},"Day",[719,1587,724],{},[719,1589,727],{},[719,1591,1223],{},[719,1593,1126],{},[719,1595,1596],{},"Alive \u002F Deleted \u002F GC stubs",[732,1598,1599,1617,1637,1657,1676,1696,1715,1734],{},[716,1600,1601,1603,1606,1609,1612,1614],{},[737,1602,856],{},[737,1604,1605],{},"1.6 KB",[737,1607,1608],{},"2.1 KB",[737,1610,1611],{},"1.3x",[737,1613,1253],{},[737,1615,1616],{},"19 \u002F 5 \u002F 0",[716,1618,1619,1622,1625,1628,1631,1634],{},[737,1620,1621],{},"7",[737,1623,1624],{},"10.8 KB",[737,1626,1627],{},"17.8 KB",[737,1629,1630],{},"1.6x",[737,1632,1633],{},"13",[737,1635,1636],{},"123 \u002F 83 \u002F 14",[716,1638,1639,1642,1645,1648,1651,1654],{},[737,1640,1641],{},"30",[737,1643,1644],{},"47.6 KB",[737,1646,1647],{},"85.0 KB",[737,1649,1650],{},"1.8x",[737,1652,1653],{},"51",[737,1655,1656],{},"546 \u002F 377 \u002F 54",[716,1658,1659,1661,1664,1667,1670,1673],{},[737,1660,1139],{},[737,1662,1663],{},"153.6 KB",[737,1665,1666],{},"291.0 KB",[737,1668,1669],{},"1.9x",[737,1671,1672],{},"151",[737,1674,1675],{},"1,793 \u002F 1,098 \u002F 147",[716,1677,1678,1681,1684,1687,1690,1693],{},[737,1679,1680],{},"180",[737,1682,1683],{},"322.8 KB",[737,1685,1686],{},"643.4 KB",[737,1688,1689],{},"2.0x",[737,1691,1692],{},"301",[737,1694,1695],{},"3,745 \u002F 2,622 \u002F 253",[716,1697,1698,1701,1704,1707,1709,1712],{},[737,1699,1700],{},"365",[737,1702,1703],{},"682.7 KB",[737,1705,1706],{},"1.3 MB",[737,1708,1689],{},[737,1710,1711],{},"610",[737,1713,1714],{},"7,935 \u002F 5,698 \u002F 495",[716,1716,1717,1720,1723,1726,1728,1731],{},[737,1718,1719],{},"545",[737,1721,1722],{},"1.0 MB",[737,1724,1725],{},"2.0 MB",[737,1727,1689],{},[737,1729,1730],{},"910",[737,1732,1733],{},"12,066 \u002F 8,642 \u002F 750",[716,1735,1736,1741,1746,1751,1755,1760],{},[737,1737,1738],{},[587,1739,1740],{},"730",[737,1742,1743],{},[587,1744,1745],{},"1.4 MB",[737,1747,1748],{},[587,1749,1750],{},"2.7 MB",[737,1752,1753],{},[587,1754,1689],{},[737,1756,1757],{},[587,1758,1759],{},"1,218",[737,1761,1762],{},[587,1763,1764],{},"16,362 \u002F 11,688 \u002F 990",[635,1766,1768],{"id":1767},"what-the-numbers-show","What the numbers show",[562,1770,1771,1774,1775,1777],{},[587,1772,1773],{},"GC savings stabilize at 2.0x"," once the ratio of overwrites to new data reaches a steady state. GC freed ",[587,1776,1706],{}," over the 2-year period.",[562,1779,1780,1783],{},[587,1781,1782],{},"Growth is driven by actual data, not history."," After 2 years with 1,218 active tasks (each with descriptions, comments, and metadata), the bulk of the 1.4 MB is current content — not CRDT overhead.",[562,1785,1786,1789],{},[587,1787,1788],{},"All four docs converge after every sync."," Server, Alice, Bob, and Carol hold identical content after the final sync round. No data loss, no divergence, despite daily concurrent edits from three clients.",[635,1791,1793],{"id":1792},"indexeddb-compaction-on-top","IndexedDB compaction on top",[562,1795,1796],{},"After the 2-year state, simulating 500 additional edits (a busy week):",[710,1798,1799,1808],{},[713,1800,1801],{},[716,1802,1803,1805],{},[719,1804,838],{},[719,1806,1807],{},"Value",[732,1809,1810,1817,1825,1833,1840],{},[716,1811,1812,1815],{},[737,1813,1814],{},"Base state (already in IndexedDB)",[737,1816,1745],{},[716,1818,1819,1822],{},[737,1820,1821],{},"+ 500 incremental updates",[737,1823,1824],{},"1.4 MB across 501 new entries",[716,1826,1827,1830],{},[737,1828,1829],{},"Total before compaction",[737,1831,1832],{},"2.8 MB in 502 entries",[716,1834,1835,1837],{},[737,1836,844],{},[737,1838,1839],{},"1.4 MB in 1 entry",[716,1841,1842,1845],{},[737,1843,1844],{},"Storage saved",[737,1846,1847],{},[587,1848,1745],{},[562,1850,1851],{},"IndexedDB compaction eliminates all the incremental update entries, reducing the on-disk footprint back to the size of the current document state.",[566,1853,1855],{"id":1854},"sync-and-compaction-safety","Sync and compaction safety",[562,1857,1858],{},"A common concern: if one client compacts its document, does that break sync with a stale client that hasn't synced in a while?",[562,1860,1861,1864,1865,1868],{},[587,1862,1863],{},"No."," Compaction preserves the state vector — the mapping of ",[574,1866,1867],{},"(clientID → clock)"," that tells each peer exactly which operations the other has seen. After compaction:",[640,1870,1871,1874,1881],{},[643,1872,1873],{},"The stale client sends its state vector to the server.",[643,1875,1876,1877,1880],{},"The server computes ",[574,1878,1879],{},"Y.encodeStateAsUpdate(doc, staleClientStateVector)"," — only the operations the stale client is missing.",[643,1882,1883],{},"The stale client applies the diff. No data loss, no divergence.",[562,1885,1886],{},"This works because compaction does not discard causal metadata. The struct IDs remain intact even after GC replaces content with compact markers.",[599,1888,1891],{"className":1889,"code":1890,"language":604},[602],"Client A compacts → syncs with server → makes new edits\nClient B (stale for days) → syncs with server\n        │\n        ▼\nServer sends only the diff B is missing\nB applies diff → all clients converge ✅\n",[574,1892,1890],{"__ignoreMap":607},[566,1894,1896],{"id":1895},"practical-guidance","Practical guidance",[562,1898,1899],{},"For typical protokit workloads — prototyping tools, form-heavy apps, task managers, and CRUD collections — document size stays manageable without intervention.",[1492,1901,1902,1908,1914,1920,1928],{},[643,1903,1904,1907],{},[587,1905,1906],{},"GC runs automatically"," after every transaction. No configuration needed. Saves 2x on overwrite-heavy workloads.",[643,1909,1910,1913],{},[587,1911,1912],{},"IndexedDB compacts"," every 500 updates. No configuration needed.",[643,1915,1916,1919],{},[587,1917,1918],{},"Server sync is safe"," after compaction. Stale clients catch up correctly.",[643,1921,1922,1927],{},[587,1923,1924,1926],{},[574,1925,576],{}," for descriptions"," is efficient. Overwriting a string field costs only the metadata stub (~8 bytes after GC), not the full old string.",[643,1929,1930,1933],{},[587,1931,1932],{},"2 years of 3-user daily usage"," produces a 1.4 MB document with 1,218 active tasks. Without GC it would be 2.7 MB.",[1935,1936,1938],"callout",{"color":1937,"icon":520},"blue",[562,1939,1940,1941,1944,1945,1947],{},"If you use ",[574,1942,1943],{},"Y.Text"," for collaborative rich-text editing where two users type simultaneously, the document grows faster because every keystroke is a separate operation. For protokit's typical use case — single-user form fields stored as strings via ",[574,1946,576],{}," — this does not apply.",[566,1949,1951],{"id":1950},"when-to-consider-manual-compaction","When to consider manual compaction",[562,1953,1954],{},"Manual compaction is unnecessary for most applications. Consider it only if:",[1492,1956,1957,1964,1971],{},[643,1958,1959,1960,1963],{},"A single document exceeds ",[587,1961,1962],{},"5 MB"," (extremely unlikely with protokit schemas).",[643,1965,1966,1967,1970],{},"Initial page load exceeds ",[587,1968,1969],{},"200 ms"," due to IndexedDB read time.",[643,1972,1973],{},"You are building a server that stores Y.js state for thousands of documents and want to reduce storage costs.",[562,1975,1976],{},"Server-side compaction follows the same pattern as IndexedDB compaction:",[599,1978,1982],{"className":1979,"code":1980,"language":1981,"meta":607,"style":607},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Server-side compaction (if ever needed)\nconst state = Y.encodeStateAsUpdate(doc)\nconst compacted = new Y.Doc()\nY.applyUpdate(compacted, state)\nconst compactedState = Y.encodeStateAsUpdate(compacted)\n\u002F\u002F Store compactedState — state vectors preserved, sync-safe\n","typescript",[574,1983,1984,1993,2020,2043,2063,2082],{"__ignoreMap":607},[1985,1986,1989],"span",{"class":1987,"line":1988},"line",1,[1985,1990,1992],{"class":1991},"sHwdD","\u002F\u002F Server-side compaction (if ever needed)\n",[1985,1994,1996,2000,2004,2008,2011,2013,2017],{"class":1987,"line":1995},2,[1985,1997,1999],{"class":1998},"spNyl","const",[1985,2001,2003],{"class":2002},"sTEyZ"," state ",[1985,2005,2007],{"class":2006},"sMK4o","=",[1985,2009,2010],{"class":2002}," Y",[1985,2012,597],{"class":2006},[1985,2014,2016],{"class":2015},"s2Zo4","encodeStateAsUpdate",[1985,2018,2019],{"class":2002},"(doc)\n",[1985,2021,2023,2025,2028,2030,2033,2035,2037,2040],{"class":1987,"line":2022},3,[1985,2024,1999],{"class":1998},[1985,2026,2027],{"class":2002}," compacted ",[1985,2029,2007],{"class":2006},[1985,2031,2032],{"class":2006}," new",[1985,2034,2010],{"class":2002},[1985,2036,597],{"class":2006},[1985,2038,2039],{"class":2015},"Doc",[1985,2041,2042],{"class":2002},"()\n",[1985,2044,2046,2049,2051,2054,2057,2060],{"class":1987,"line":2045},4,[1985,2047,2048],{"class":2002},"Y",[1985,2050,597],{"class":2006},[1985,2052,2053],{"class":2015},"applyUpdate",[1985,2055,2056],{"class":2002},"(compacted",[1985,2058,2059],{"class":2006},",",[1985,2061,2062],{"class":2002}," state)\n",[1985,2064,2066,2068,2071,2073,2075,2077,2079],{"class":1987,"line":2065},5,[1985,2067,1999],{"class":1998},[1985,2069,2070],{"class":2002}," compactedState ",[1985,2072,2007],{"class":2006},[1985,2074,2010],{"class":2002},[1985,2076,597],{"class":2006},[1985,2078,2016],{"class":2015},[1985,2080,2081],{"class":2002},"(compacted)\n",[1985,2083,2085],{"class":1987,"line":2084},6,[1985,2086,2087],{"class":1991},"\u002F\u002F Store compactedState — state vectors preserved, sync-safe\n",[2089,2090,2091],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":607,"searchDepth":1995,"depth":1995,"links":2093},[2094,2095,2101,2105,2111,2115,2121,2122,2123],{"id":568,"depth":1995,"text":569},{"id":621,"depth":1995,"text":622,"children":2096},[2097,2098,2099,2100],{"id":637,"depth":2022,"text":638},{"id":675,"depth":2022,"text":676},{"id":696,"depth":2022,"text":697},{"id":707,"depth":2022,"text":708},{"id":768,"depth":1995,"text":769,"children":2102},[2103,2104],{"id":778,"depth":2022,"text":779},{"id":817,"depth":2022,"text":818},{"id":881,"depth":1995,"text":882,"children":2106},[2107,2108,2109,2110],{"id":895,"depth":2022,"text":896},{"id":960,"depth":2022,"text":961},{"id":1013,"depth":2022,"text":1014},{"id":1108,"depth":2022,"text":1109},{"id":1182,"depth":1995,"text":1183,"children":2112},[2113,2114],{"id":1203,"depth":2022,"text":1204},{"id":1361,"depth":2022,"text":1362},{"id":1534,"depth":1995,"text":1535,"children":2116},[2117,2118,2119,2120],{"id":1546,"depth":2022,"text":721},{"id":1575,"depth":2022,"text":1576},{"id":1767,"depth":2022,"text":1768},{"id":1792,"depth":2022,"text":1793},{"id":1854,"depth":1995,"text":1855},{"id":1895,"depth":1995,"text":1896},{"id":1950,"depth":1995,"text":1951},"How Y.js documents grow over time, how garbage collection compacts them, and what to expect for real-world prototyping workloads.","md",null,{},{"title":460},{"title":552,"description":2124},"VZcu7ngiQSBSk408iLi-of_gR_fsfDkrfEIGM9QOW3w",[2132,2134],{"title":456,"path":457,"stem":458,"description":2133,"children":-1},"How protokit detects IndexedDB corruption, queries server snapshots, and guides users through recovery without data loss.",{"title":464,"path":465,"stem":466,"description":2135,"children":-1},"How to scope Y.js documents per user, tenant, or workspace — and how to clean up IndexedDB on logout.",1792254332136]