[{"data":1,"prerenderedAt":1673},["ShallowReactive",2],{"navigation-landing-en":3,"navigation-nuxt-auto-en":180,"navigation-nuxt-protokit-en":365,"blog-post-\u002Fblog\u002Fnuxt-protokit-launch-en":507,"blog-post-surround-\u002Fblog\u002Fnuxt-protokit-launch-en":1663},[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},{"id":508,"title":509,"authors":510,"badge":515,"body":517,"date":1647,"description":1648,"extension":1649,"image":1650,"meta":1652,"navigation":585,"ogImage":1653,"path":1654,"published":585,"seo":1655,"stem":1656,"tags":1657,"__hash__":1662},"posts\u002F3.blog\u002F11.nuxt-protokit-launch.md","nuxt-protokit: rapid prototyping for Nuxt",[511],{"name":512,"avatar":513},"Benjamin",{"src":514},"profile\u002Fbenjamin.webp",{"label":516},"Launch",{"type":518,"value":519,"toc":1638},"minimark",[520,525,529,532,536,1244,1248,1373,1380,1387,1391,1406,1491,1494,1497,1503,1507,1510,1518,1522,1553,1560,1610,1613,1631,1634],[521,522,524],"h2",{"id":523},"the-problem","The problem",[526,527,528],"p",{},"I often have ideas for small tools. A cost estimator, a tracker, an internal checklist. And the first day always went to the same stuff: a database, an API, forms. By the time it worked I wasn't even sure the idea was good anymore.",[526,530,531],{},"nuxt-protokit is for rapid prototyping and skips that part. You write the tool as a TypeScript schema, render it with one component, and it works. Data is saved in the browser while you type. 0.1.0 is out today.",[521,533,535],{"id":534},"the-schema","The schema",[537,538,544],"pre",{"className":539,"code":540,"filename":541,"language":542,"meta":543,"style":543},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { formatMoney } from '#protokit\u002Futils\u002Fformatters'\n\nexport const resourceEstimator = definePrototype({\n  key: 'resource-estimator-v1', \u002F\u002F also the IndexedDB key\n  title: 'Resource Cost Estimator',\n  shortTitle: 'Estimator',\n  description: 'Estimate total project cost from team size, salaries and duration.',\n  icon: 'i-lucide-calculator',\n\n  fields: {\n    teamSize: { type: 'number', label: 'Team Size', default: 3, trailing: 'people' },\n    avgMonthlySalary: { type: 'number', label: 'Avg. Monthly Salary', default: 4500, leading: '$' },\n    projectDurationMonths: { type: 'range', label: 'Duration (months)', min: 1, max: 24, step: 1, default: 6 },\n  },\n\n  derived: {\n    monthlyCost: {\n      compute: ({ fields }) => fields.teamSize * fields.avgMonthlySalary,\n      format: 'money',\n    },\n    projectTotal: {\n      compute: ({ fields, derived }) => derived.monthlyCost * fields.projectDurationMonths,\n      format: 'money',\n    },\n  },\n\n  results: [\n    {\n      title: 'Cost Summary',\n      stats: ({ derived }) => [\n        { label: 'Monthly', value: formatMoney(derived.monthlyCost) },\n        { label: 'Project Total', value: formatMoney(derived.projectTotal) },\n      ],\n    },\n  ],\n})\n","app\u002Fschemas\u002FresourceEstimator.ts","ts","",[545,546,547,580,587,613,638,656,673,690,707,712,723,787,845,919,925,930,940,950,991,1008,1014,1024,1062,1077,1082,1087,1092,1103,1109,1126,1144,1181,1214,1222,1227,1235],"code",{"__ignoreMap":543},[548,549,552,556,560,564,567,570,573,577],"span",{"class":550,"line":551},"line",1,[548,553,555],{"class":554},"s7zQu","import",[548,557,559],{"class":558},"sMK4o"," {",[548,561,563],{"class":562},"sTEyZ"," formatMoney",[548,565,566],{"class":558}," }",[548,568,569],{"class":554}," from",[548,571,572],{"class":558}," '",[548,574,576],{"class":575},"sfazB","#protokit\u002Futils\u002Fformatters",[548,578,579],{"class":558},"'\n",[548,581,583],{"class":550,"line":582},2,[548,584,586],{"emptyLinePlaceholder":585},true,"\n",[548,588,590,593,597,600,603,607,610],{"class":550,"line":589},3,[548,591,592],{"class":554},"export",[548,594,596],{"class":595},"spNyl"," const",[548,598,599],{"class":562}," resourceEstimator ",[548,601,602],{"class":558},"=",[548,604,606],{"class":605},"s2Zo4"," definePrototype",[548,608,609],{"class":562},"(",[548,611,612],{"class":558},"{\n",[548,614,616,620,623,625,628,631,634],{"class":550,"line":615},4,[548,617,619],{"class":618},"swJcz","  key",[548,621,622],{"class":558},":",[548,624,572],{"class":558},[548,626,627],{"class":575},"resource-estimator-v1",[548,629,630],{"class":558},"'",[548,632,633],{"class":558},",",[548,635,637],{"class":636},"sHwdD"," \u002F\u002F also the IndexedDB key\n",[548,639,641,644,646,648,651,653],{"class":550,"line":640},5,[548,642,643],{"class":618},"  title",[548,645,622],{"class":558},[548,647,572],{"class":558},[548,649,650],{"class":575},"Resource Cost Estimator",[548,652,630],{"class":558},[548,654,655],{"class":558},",\n",[548,657,659,662,664,666,669,671],{"class":550,"line":658},6,[548,660,661],{"class":618},"  shortTitle",[548,663,622],{"class":558},[548,665,572],{"class":558},[548,667,668],{"class":575},"Estimator",[548,670,630],{"class":558},[548,672,655],{"class":558},[548,674,676,679,681,683,686,688],{"class":550,"line":675},7,[548,677,678],{"class":618},"  description",[548,680,622],{"class":558},[548,682,572],{"class":558},[548,684,685],{"class":575},"Estimate total project cost from team size, salaries and duration.",[548,687,630],{"class":558},[548,689,655],{"class":558},[548,691,693,696,698,700,703,705],{"class":550,"line":692},8,[548,694,695],{"class":618},"  icon",[548,697,622],{"class":558},[548,699,572],{"class":558},[548,701,702],{"class":575},"i-lucide-calculator",[548,704,630],{"class":558},[548,706,655],{"class":558},[548,708,710],{"class":550,"line":709},9,[548,711,586],{"emptyLinePlaceholder":585},[548,713,715,718,720],{"class":550,"line":714},10,[548,716,717],{"class":618},"  fields",[548,719,622],{"class":558},[548,721,722],{"class":558}," {\n",[548,724,726,729,731,733,736,738,740,743,745,747,750,752,754,757,759,761,764,766,770,772,775,777,779,782,784],{"class":550,"line":725},11,[548,727,728],{"class":618},"    teamSize",[548,730,622],{"class":558},[548,732,559],{"class":558},[548,734,735],{"class":618}," type",[548,737,622],{"class":558},[548,739,572],{"class":558},[548,741,742],{"class":575},"number",[548,744,630],{"class":558},[548,746,633],{"class":558},[548,748,749],{"class":618}," label",[548,751,622],{"class":558},[548,753,572],{"class":558},[548,755,756],{"class":575},"Team Size",[548,758,630],{"class":558},[548,760,633],{"class":558},[548,762,763],{"class":618}," default",[548,765,622],{"class":558},[548,767,769],{"class":768},"sbssI"," 3",[548,771,633],{"class":558},[548,773,774],{"class":618}," trailing",[548,776,622],{"class":558},[548,778,572],{"class":558},[548,780,781],{"class":575},"people",[548,783,630],{"class":558},[548,785,786],{"class":558}," },\n",[548,788,790,793,795,797,799,801,803,805,807,809,811,813,815,818,820,822,824,826,829,831,834,836,838,841,843],{"class":550,"line":789},12,[548,791,792],{"class":618},"    avgMonthlySalary",[548,794,622],{"class":558},[548,796,559],{"class":558},[548,798,735],{"class":618},[548,800,622],{"class":558},[548,802,572],{"class":558},[548,804,742],{"class":575},[548,806,630],{"class":558},[548,808,633],{"class":558},[548,810,749],{"class":618},[548,812,622],{"class":558},[548,814,572],{"class":558},[548,816,817],{"class":575},"Avg. Monthly Salary",[548,819,630],{"class":558},[548,821,633],{"class":558},[548,823,763],{"class":618},[548,825,622],{"class":558},[548,827,828],{"class":768}," 4500",[548,830,633],{"class":558},[548,832,833],{"class":618}," leading",[548,835,622],{"class":558},[548,837,572],{"class":558},[548,839,840],{"class":575},"$",[548,842,630],{"class":558},[548,844,786],{"class":558},[548,846,848,851,853,855,857,859,861,864,866,868,870,872,874,877,879,881,884,886,889,891,894,896,899,901,904,906,908,910,912,914,917],{"class":550,"line":847},13,[548,849,850],{"class":618},"    projectDurationMonths",[548,852,622],{"class":558},[548,854,559],{"class":558},[548,856,735],{"class":618},[548,858,622],{"class":558},[548,860,572],{"class":558},[548,862,863],{"class":575},"range",[548,865,630],{"class":558},[548,867,633],{"class":558},[548,869,749],{"class":618},[548,871,622],{"class":558},[548,873,572],{"class":558},[548,875,876],{"class":575},"Duration (months)",[548,878,630],{"class":558},[548,880,633],{"class":558},[548,882,883],{"class":618}," min",[548,885,622],{"class":558},[548,887,888],{"class":768}," 1",[548,890,633],{"class":558},[548,892,893],{"class":618}," max",[548,895,622],{"class":558},[548,897,898],{"class":768}," 24",[548,900,633],{"class":558},[548,902,903],{"class":618}," step",[548,905,622],{"class":558},[548,907,888],{"class":768},[548,909,633],{"class":558},[548,911,763],{"class":618},[548,913,622],{"class":558},[548,915,916],{"class":768}," 6",[548,918,786],{"class":558},[548,920,922],{"class":550,"line":921},14,[548,923,924],{"class":558},"  },\n",[548,926,928],{"class":550,"line":927},15,[548,929,586],{"emptyLinePlaceholder":585},[548,931,933,936,938],{"class":550,"line":932},16,[548,934,935],{"class":618},"  derived",[548,937,622],{"class":558},[548,939,722],{"class":558},[548,941,943,946,948],{"class":550,"line":942},17,[548,944,945],{"class":618},"    monthlyCost",[548,947,622],{"class":558},[548,949,722],{"class":558},[548,951,953,956,958,961,965,968,971,973,976,979,982,984,986,989],{"class":550,"line":952},18,[548,954,955],{"class":605},"      compute",[548,957,622],{"class":558},[548,959,960],{"class":558}," ({",[548,962,964],{"class":963},"sHdIc"," fields",[548,966,967],{"class":558}," })",[548,969,970],{"class":595}," =>",[548,972,964],{"class":562},[548,974,975],{"class":558},".",[548,977,978],{"class":562},"teamSize ",[548,980,981],{"class":558},"*",[548,983,964],{"class":562},[548,985,975],{"class":558},[548,987,988],{"class":562},"avgMonthlySalary",[548,990,655],{"class":558},[548,992,994,997,999,1001,1004,1006],{"class":550,"line":993},19,[548,995,996],{"class":618},"      format",[548,998,622],{"class":558},[548,1000,572],{"class":558},[548,1002,1003],{"class":575},"money",[548,1005,630],{"class":558},[548,1007,655],{"class":558},[548,1009,1011],{"class":550,"line":1010},20,[548,1012,1013],{"class":558},"    },\n",[548,1015,1017,1020,1022],{"class":550,"line":1016},21,[548,1018,1019],{"class":618},"    projectTotal",[548,1021,622],{"class":558},[548,1023,722],{"class":558},[548,1025,1027,1029,1031,1033,1035,1037,1040,1042,1044,1046,1048,1051,1053,1055,1057,1060],{"class":550,"line":1026},22,[548,1028,955],{"class":605},[548,1030,622],{"class":558},[548,1032,960],{"class":558},[548,1034,964],{"class":963},[548,1036,633],{"class":558},[548,1038,1039],{"class":963}," derived",[548,1041,967],{"class":558},[548,1043,970],{"class":595},[548,1045,1039],{"class":562},[548,1047,975],{"class":558},[548,1049,1050],{"class":562},"monthlyCost ",[548,1052,981],{"class":558},[548,1054,964],{"class":562},[548,1056,975],{"class":558},[548,1058,1059],{"class":562},"projectDurationMonths",[548,1061,655],{"class":558},[548,1063,1065,1067,1069,1071,1073,1075],{"class":550,"line":1064},23,[548,1066,996],{"class":618},[548,1068,622],{"class":558},[548,1070,572],{"class":558},[548,1072,1003],{"class":575},[548,1074,630],{"class":558},[548,1076,655],{"class":558},[548,1078,1080],{"class":550,"line":1079},24,[548,1081,1013],{"class":558},[548,1083,1085],{"class":550,"line":1084},25,[548,1086,924],{"class":558},[548,1088,1090],{"class":550,"line":1089},26,[548,1091,586],{"emptyLinePlaceholder":585},[548,1093,1095,1098,1100],{"class":550,"line":1094},27,[548,1096,1097],{"class":618},"  results",[548,1099,622],{"class":558},[548,1101,1102],{"class":562}," [\n",[548,1104,1106],{"class":550,"line":1105},28,[548,1107,1108],{"class":558},"    {\n",[548,1110,1112,1115,1117,1119,1122,1124],{"class":550,"line":1111},29,[548,1113,1114],{"class":618},"      title",[548,1116,622],{"class":558},[548,1118,572],{"class":558},[548,1120,1121],{"class":575},"Cost Summary",[548,1123,630],{"class":558},[548,1125,655],{"class":558},[548,1127,1129,1132,1134,1136,1138,1140,1142],{"class":550,"line":1128},30,[548,1130,1131],{"class":605},"      stats",[548,1133,622],{"class":558},[548,1135,960],{"class":558},[548,1137,1039],{"class":963},[548,1139,967],{"class":558},[548,1141,970],{"class":595},[548,1143,1102],{"class":562},[548,1145,1147,1150,1152,1154,1156,1159,1161,1163,1166,1168,1170,1173,1175,1178],{"class":550,"line":1146},31,[548,1148,1149],{"class":558},"        {",[548,1151,749],{"class":618},[548,1153,622],{"class":558},[548,1155,572],{"class":558},[548,1157,1158],{"class":575},"Monthly",[548,1160,630],{"class":558},[548,1162,633],{"class":558},[548,1164,1165],{"class":618}," value",[548,1167,622],{"class":558},[548,1169,563],{"class":605},[548,1171,1172],{"class":562},"(derived",[548,1174,975],{"class":558},[548,1176,1177],{"class":562},"monthlyCost) ",[548,1179,1180],{"class":558},"},\n",[548,1182,1184,1186,1188,1190,1192,1195,1197,1199,1201,1203,1205,1207,1209,1212],{"class":550,"line":1183},32,[548,1185,1149],{"class":558},[548,1187,749],{"class":618},[548,1189,622],{"class":558},[548,1191,572],{"class":558},[548,1193,1194],{"class":575},"Project Total",[548,1196,630],{"class":558},[548,1198,633],{"class":558},[548,1200,1165],{"class":618},[548,1202,622],{"class":558},[548,1204,563],{"class":605},[548,1206,1172],{"class":562},[548,1208,975],{"class":558},[548,1210,1211],{"class":562},"projectTotal) ",[548,1213,1180],{"class":558},[548,1215,1217,1220],{"class":550,"line":1216},33,[548,1218,1219],{"class":562},"      ]",[548,1221,655],{"class":558},[548,1223,1225],{"class":550,"line":1224},34,[548,1226,1013],{"class":558},[548,1228,1230,1233],{"class":550,"line":1229},35,[548,1231,1232],{"class":562},"  ]",[548,1234,655],{"class":558},[548,1236,1238,1241],{"class":550,"line":1237},36,[548,1239,1240],{"class":558},"}",[548,1242,1243],{"class":562},")\n",[521,1245,1247],{"id":1246},"the-page","The page",[537,1249,1254],{"className":1250,"code":1251,"filename":1252,"language":1253,"meta":543,"style":543},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nimport { resourceEstimator } from '~\u002Fschemas\u002FresourceEstimator'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CClientOnly>\n    \u003CProtoTool :schema=\"resourceEstimator\" \u002F>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n","app\u002Fpages\u002Festimator.vue","vue",[545,1255,1256,1282,1302,1311,1315,1324,1334,1356,1365],{"__ignoreMap":543},[548,1257,1258,1261,1264,1267,1270,1272,1275,1277,1279],{"class":550,"line":551},[548,1259,1260],{"class":558},"\u003C",[548,1262,1263],{"class":618},"script",[548,1265,1266],{"class":595}," setup",[548,1268,1269],{"class":595}," lang",[548,1271,602],{"class":558},[548,1273,1274],{"class":558},"\"",[548,1276,542],{"class":575},[548,1278,1274],{"class":558},[548,1280,1281],{"class":558},">\n",[548,1283,1284,1286,1288,1291,1293,1295,1297,1300],{"class":550,"line":582},[548,1285,555],{"class":554},[548,1287,559],{"class":558},[548,1289,1290],{"class":562}," resourceEstimator",[548,1292,566],{"class":558},[548,1294,569],{"class":554},[548,1296,572],{"class":558},[548,1298,1299],{"class":575},"~\u002Fschemas\u002FresourceEstimator",[548,1301,579],{"class":558},[548,1303,1304,1307,1309],{"class":550,"line":589},[548,1305,1306],{"class":558},"\u003C\u002F",[548,1308,1263],{"class":618},[548,1310,1281],{"class":558},[548,1312,1313],{"class":550,"line":615},[548,1314,586],{"emptyLinePlaceholder":585},[548,1316,1317,1319,1322],{"class":550,"line":640},[548,1318,1260],{"class":558},[548,1320,1321],{"class":618},"template",[548,1323,1281],{"class":558},[548,1325,1326,1329,1332],{"class":550,"line":658},[548,1327,1328],{"class":558},"  \u003C",[548,1330,1331],{"class":618},"ClientOnly",[548,1333,1281],{"class":558},[548,1335,1336,1339,1341,1344,1346,1348,1351,1353],{"class":550,"line":675},[548,1337,1338],{"class":558},"    \u003C",[548,1340,434],{"class":618},[548,1342,1343],{"class":595}," :schema",[548,1345,602],{"class":558},[548,1347,1274],{"class":558},[548,1349,1350],{"class":575},"resourceEstimator",[548,1352,1274],{"class":558},[548,1354,1355],{"class":558}," \u002F>\n",[548,1357,1358,1361,1363],{"class":550,"line":692},[548,1359,1360],{"class":558},"  \u003C\u002F",[548,1362,1331],{"class":618},[548,1364,1281],{"class":558},[548,1366,1367,1369,1371],{"class":550,"line":709},[548,1368,1306],{"class":558},[548,1370,1321],{"class":618},[548,1372,1281],{"class":558},[526,1374,1375,1376,1379],{},"Move a slider, the totals update. Refresh, the values are still there because they load from IndexedDB. Open it in a second tab and both tabs stay in sync over ",[545,1377,1378],{},"BroadcastChannel",". Works offline too.",[526,1381,1382],{},[1383,1384],"img",{"alt":1385,"src":1386},"The resource cost estimator from the quick start, as the playground renders it","\u002Fblog\u002Fposts\u002F202610\u002Fnuxt-protokit-launch\u002Festimator.webp",[521,1388,1390],{"id":1389},"how-it-stores-data","How it stores data",[526,1392,1393,1394,1401,1402,1405],{},"Every tool is a ",[1395,1396,1400],"a",{"href":1397,"rel":1398},"https:\u002F\u002Fyjs.dev",[1399],"nofollow","Yjs"," document, saved with ",[545,1403,1404],{},"y-indexeddb",". Writes go to the browser first. If you want sync between devices, you point it at your own backend. That's five endpoints, either from a companion module or written by you. With sync off, protokit doesn't make any HTTP calls:",[537,1407,1410],{"className":539,"code":1408,"filename":1409,"language":542,"meta":543,"style":543},"export default defineNuxtConfig({\n  modules: ['@nuxt\u002Fui', '@websideproject\u002Fnuxt-protokit'],\n  protokit: {\n    serverSync: false, \u002F\u002F local only\n  },\n})\n","nuxt.config.ts",[545,1411,1412,1425,1456,1465,1481,1485],{"__ignoreMap":543},[548,1413,1414,1416,1418,1421,1423],{"class":550,"line":551},[548,1415,592],{"class":554},[548,1417,763],{"class":554},[548,1419,1420],{"class":605}," defineNuxtConfig",[548,1422,609],{"class":562},[548,1424,612],{"class":558},[548,1426,1427,1430,1432,1435,1437,1440,1442,1444,1446,1449,1451,1454],{"class":550,"line":582},[548,1428,1429],{"class":618},"  modules",[548,1431,622],{"class":558},[548,1433,1434],{"class":562}," [",[548,1436,630],{"class":558},[548,1438,1439],{"class":575},"@nuxt\u002Fui",[548,1441,630],{"class":558},[548,1443,633],{"class":558},[548,1445,572],{"class":558},[548,1447,1448],{"class":575},"@websideproject\u002Fnuxt-protokit",[548,1450,630],{"class":558},[548,1452,1453],{"class":562},"]",[548,1455,655],{"class":558},[548,1457,1458,1461,1463],{"class":550,"line":589},[548,1459,1460],{"class":618},"  protokit",[548,1462,622],{"class":558},[548,1464,722],{"class":558},[548,1466,1467,1470,1472,1476,1478],{"class":550,"line":615},[548,1468,1469],{"class":618},"    serverSync",[548,1471,622],{"class":558},[548,1473,1475],{"class":1474},"sfNiH"," false",[548,1477,633],{"class":558},[548,1479,1480],{"class":636}," \u002F\u002F local only\n",[548,1482,1483],{"class":550,"line":640},[548,1484,924],{"class":558},[548,1486,1487,1489],{"class":550,"line":658},[548,1488,1240],{"class":558},[548,1490,1243],{"class":562},[521,1492,428],{"id":1493},"components",[526,1495,1496],{},"There are ready-made components that use the same schema: a calendar (day, week and a scrolling month view, and you can drag tasks from a list onto it), charts (line, bar, pie, funnel, progress), detail panels, CRUD lists with edit modals, stat cards, comparison tables and timelines. There are also twelve field types, schema migrations, AES-GCM encryption, corruption recovery and per-tenant namespaces. If you want your own UI, the composables work without the components.",[526,1498,1499],{},[1383,1500],{"alt":1501,"src":1502},"The ProtoCalendar week view: timed events laid out by the hour","\u002Fblog\u002Fposts\u002F202610\u002Fnuxt-protokit-launch\u002Fcalendar-week.webp",[521,1504,1506],{"id":1505},"where-i-use-it","Where I use it",[526,1508,1509],{},"Prototypes, internal tools, demos for clients. Basically when I want to find out if an idea works before spending time on a backend.",[526,1511,1512,1513,1517],{},"One thing to be clear about: the data is in the browser, so the permissions only change what the UI shows. They don't protect anything. Once an idea works and needs real users and server-side rules, it should get a proper backend. I use ",[1395,1514,1516],{"href":1515},"\u002Fblog\u002Fnuxt-auto-api-launch","nuxt-auto"," for that. Until then it's a lot less setup than Firebase, and the data is plain Yjs, so you can take it with you.",[521,1519,1521],{"id":1520},"try-it","Try it",[537,1523,1527],{"className":1524,"code":1525,"language":1526,"meta":543,"style":543},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npm install @websideproject\u002Fnuxt-protokit yjs y-indexeddb @nuxt\u002Fui tailwindcss\n","bash",[545,1528,1529],{"__ignoreMap":543},[548,1530,1531,1535,1538,1541,1544,1547,1550],{"class":550,"line":551},[548,1532,1534],{"class":1533},"sBMFI","npm",[548,1536,1537],{"class":575}," install",[548,1539,1540],{"class":575}," @websideproject\u002Fnuxt-protokit",[548,1542,1543],{"class":575}," yjs",[548,1545,1546],{"class":575}," y-indexeddb",[548,1548,1549],{"class":575}," @nuxt\u002Fui",[548,1551,1552],{"class":575}," tailwindcss\n",[526,1554,1555,1556,1559],{},"Tailwind doesn't scan ",[545,1557,1558],{},"node_modules",", so add this line to the CSS file that imports Nuxt UI (the path is relative to that file):",[537,1561,1566],{"className":1562,"code":1563,"filename":1564,"language":1565,"meta":543,"style":543},"language-css shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","@import \"tailwindcss\";\n@import \"@nuxt\u002Fui\";\n\n@source \"..\u002F..\u002F..\u002Fnode_modules\u002F@websideproject\u002Fnuxt-protokit\";\n","app\u002Fassets\u002Fcss\u002Fmain.css","css",[545,1567,1568,1584,1596,1600],{"__ignoreMap":543},[548,1569,1570,1573,1576,1579,1581],{"class":550,"line":551},[548,1571,1572],{"class":554},"@import",[548,1574,1575],{"class":558}," \"",[548,1577,1578],{"class":575},"tailwindcss",[548,1580,1274],{"class":558},[548,1582,1583],{"class":558},";\n",[548,1585,1586,1588,1590,1592,1594],{"class":550,"line":582},[548,1587,1572],{"class":554},[548,1589,1575],{"class":558},[548,1591,1439],{"class":575},[548,1593,1274],{"class":558},[548,1595,1583],{"class":558},[548,1597,1598],{"class":550,"line":589},[548,1599,586],{"emptyLinePlaceholder":585},[548,1601,1602,1605,1608],{"class":550,"line":615},[548,1603,1604],{"class":554},"@source",[548,1606,1607],{"class":562}," \"..\u002F..\u002F..\u002Fnode_modules\u002F@websideproject\u002Fnuxt-protokit\"",[548,1609,1583],{"class":558},[526,1611,1612],{},"The playground in the repo has 20 demos: estimators, calendars, charts, encryption, headless mode.",[1614,1615,1616,1623],"ul",{},[1617,1618,1619,1620],"li",{},"Docs: ",[1395,1621,1622],{"href":367},"websideproject.com\u002Fdocs\u002Fnuxt-protokit",[1617,1624,1625,1626],{},"Repo: ",[1395,1627,1630],{"href":1628,"rel":1629},"https:\u002F\u002Fgithub.com\u002Fwebsideproject\u002Fnuxt-protokit",[1399],"github.com\u002Fwebsideproject\u002Fnuxt-protokit",[526,1632,1633],{},"Next week I'll write about the local-first part in more detail: how a write is saved, what happens when two edits conflict, and what survives a crash. If you've used Yjs in production I'd really like your feedback.",[1635,1636,1637],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}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);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":543,"searchDepth":582,"depth":582,"links":1639},[1640,1641,1642,1643,1644,1645,1646],{"id":523,"depth":582,"text":524},{"id":534,"depth":582,"text":535},{"id":1246,"depth":582,"text":1247},{"id":1389,"depth":582,"text":1390},{"id":1493,"depth":582,"text":428},{"id":1505,"depth":582,"text":1506},{"id":1520,"depth":582,"text":1521},"2026-10-13","Prototype a tool in one TypeScript schema and it runs in Nuxt UI, saved in the browser as you type. No backend, no database. What it is and where I use it.","md",{"src":1651},"blog\u002Fposts\u002F202610\u002Fnuxt-protokit-launch\u002Fcover.webp",{},null,"\u002Fblog\u002Fnuxt-protokit-launch",{"title":509,"description":1648},"3.blog\u002F11.nuxt-protokit-launch",[1658,1659,1660,1661],"Nuxt","nuxt-protokit","Local-First","Open Source","0fq-xmY3U23q4G2UiZwSLMneSU2cICvi1m8KLtmvigk",[1664,1668],{"title":1665,"path":1515,"stem":1666,"description":1667,"children":-1},"nuxt-auto: a secure REST API from your Drizzle schema","3.blog\u002F10.nuxt-auto-api-launch","nuxt-auto-api 0.1.0 is out. Register a Drizzle table and you get a REST API with filters, relations and permissions that deny by default. Less backend boilerplate in Nuxt, and why I built it.",{"title":1669,"path":1670,"stem":1671,"description":1672,"children":-1},"Nuxt Content 404 issues? One config can fix it","\u002Fblog\u002Ffix-nuxt-content-404","3.blog\u002F2.fix-nuxt-content-404","Enabled prerendering for optimization. Pushed to production. Suddenly receive weird 404 error. One config line fixes it - autoSubfolderIndex",1791895766357]