[{"data":1,"prerenderedAt":1483},["ShallowReactive",2],{"navigation":3,"\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable":358,"\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable-surround":1478},[4,14,36,69,140,341],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","1.getting-started\u002F1.index",[9,10],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":15,"path":16,"stem":17,"children":18,"page":35},"Guides","\u002Fguides","2.guides",[19,23,27,31],{"title":20,"path":21,"stem":22},"Your First Layout","\u002Fguides\u002Fyour-first-layout","2.guides\u002F1.your-first-layout",{"title":24,"path":25,"stem":26},"Your First Page Template","\u002Fguides\u002Fyour-first-page-template","2.guides\u002F2.your-first-page-template",{"title":28,"path":29,"stem":30},"Your First Component","\u002Fguides\u002Fyour-first-component","2.guides\u002F3.your-first-component",{"title":32,"path":33,"stem":34},"Alternative UI Variants","\u002Fguides\u002Falternative-ui-variants","2.guides\u002F4.alternative-ui-variants",false,{"title":37,"path":38,"stem":39,"children":40,"page":35},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[41,45,49,53,57,61,65],{"title":42,"path":43,"stem":44},"How It All Works","\u002Fcore-concepts\u002Farchitecture","3.core-concepts\u002F1.architecture",{"title":46,"path":47,"stem":48},"The Data Model","\u002Fcore-concepts\u002Fthe-data-model","3.core-concepts\u002F2.the-data-model",{"title":50,"path":51,"stem":52},"Layouts & Pages","\u002Fcore-concepts\u002Flayouts-and-pages","3.core-concepts\u002F3.layouts-and-pages",{"title":54,"path":55,"stem":56},"Dynamic Pages","\u002Fcore-concepts\u002Fdynamic-pages","3.core-concepts\u002F4.dynamic-pages",{"title":58,"path":59,"stem":60},"Components","\u002Fcore-concepts\u002Fcomponents","3.core-concepts\u002F5.components",{"title":62,"path":63,"stem":64},"Draft & Publish Workflow","\u002Fcore-concepts\u002Fdraft-and-publish","3.core-concepts\u002F6.draft-and-publish",{"title":66,"path":67,"stem":68},"The Admin Panel","\u002Fcore-concepts\u002Fadmin-panel","3.core-concepts\u002F7.admin-panel",{"title":70,"path":71,"stem":72,"children":73,"page":35},"Api","\u002Fapi","4.api",[74,78,116,120,124,128,132,136],{"title":75,"path":76,"stem":77},"Bundle Setup","\u002Fapi\u002Fbundle-setup","4.api\u002F1.bundle-setup",{"title":58,"path":79,"stem":80,"children":81,"page":35},"\u002Fapi\u002Fcomponents","4.api\u002F2.components",[82,86,103],{"title":83,"path":84,"stem":85},"Creating Components","\u002Fapi\u002Fcomponents\u002Fcreating-components","4.api\u002F2.components\u002F1.creating-components",{"title":87,"path":88,"stem":89,"children":90,"page":35},"Annotations","\u002Fapi\u002Fcomponents\u002Fannotations","4.api\u002F2.components\u002F2.annotations",[91,95,99],{"title":92,"path":93,"stem":94},"Publishable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable","4.api\u002F2.components\u002F2.annotations\u002F1.publishable",{"title":96,"path":97,"stem":98},"Uploadable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fuploadable","4.api\u002F2.components\u002F2.annotations\u002F2.uploadable",{"title":100,"path":101,"stem":102},"Timestamped","\u002Fapi\u002Fcomponents\u002Fannotations\u002Ftimestamped","4.api\u002F2.components\u002F2.annotations\u002F3.timestamped",{"title":104,"path":105,"stem":106,"children":107,"page":35},"Built Ins","\u002Fapi\u002Fcomponents\u002Fbuilt-ins","4.api\u002F2.components\u002F3.built-ins",[108,112],{"title":109,"path":110,"stem":111},"Collection Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fcollection-component","4.api\u002F2.components\u002F3.built-ins\u002F1.collection-component",{"title":113,"path":114,"stem":115},"Form Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fform-component","4.api\u002F2.components\u002F3.built-ins\u002F2.form-component",{"title":117,"path":118,"stem":119},"Dynamic & Nested Pages","\u002Fapi\u002Fdynamic-pages","4.api\u002F3.dynamic-pages",{"title":121,"path":122,"stem":123},"Users & Security","\u002Fapi\u002Fusers-and-security","4.api\u002F4.users-and-security",{"title":125,"path":126,"stem":127},"Data Fixtures","\u002Fapi\u002Fdata-fixtures","4.api\u002F5.data-fixtures",{"title":129,"path":130,"stem":131},"Configuration Reference","\u002Fapi\u002Fconfiguration","4.api\u002F6.configuration",{"title":133,"path":134,"stem":135},"Console Commands","\u002Fapi\u002Fconsole-commands","4.api\u002F7.console-commands",{"title":137,"path":138,"stem":139},"Debugging & Profiler","\u002Fapi\u002Fdebugging","4.api\u002F8.debugging",{"title":141,"path":142,"stem":143,"children":144,"page":35},"Nuxt Module","\u002Fnuxt-module","5.nuxt-module",[145,149,162,182,207,211,295,320,324],{"title":146,"path":147,"stem":148},"Module Setup","\u002Fnuxt-module\u002Fmodule-setup","5.nuxt-module\u002F1.module-setup",{"title":150,"path":151,"stem":152,"children":153,"page":35},"Configuration","\u002Fnuxt-module\u002Fconfiguration","5.nuxt-module\u002F2.configuration",[154,158],{"title":155,"path":156,"stem":157},"Nuxt Config","\u002Fnuxt-module\u002Fconfiguration\u002Fnuxt-config","5.nuxt-module\u002F2.configuration\u002F1.nuxt-config",{"title":159,"path":160,"stem":161},"Site Config & SEO","\u002Fnuxt-module\u002Fconfiguration\u002Fsite-config-and-seo","5.nuxt-module\u002F2.configuration\u002F2.site-config-and-seo",{"title":163,"path":164,"stem":165,"children":166,"page":35},"Building Your Ui","\u002Fnuxt-module\u002Fbuilding-your-ui","5.nuxt-module\u002F3.building-your-ui",[167,171,175,178],{"title":168,"path":169,"stem":170},"Layouts","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-layouts","5.nuxt-module\u002F3.building-your-ui\u002F1.creating-layouts",{"title":172,"path":173,"stem":174},"Page Templates","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-page-templates","5.nuxt-module\u002F3.building-your-ui\u002F2.creating-page-templates",{"title":83,"path":176,"stem":177},"\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-components","5.nuxt-module\u002F3.building-your-ui\u002F3.creating-components",{"title":179,"path":180,"stem":181},"CLI Generator","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcwa-cli","5.nuxt-module\u002F3.building-your-ui\u002F4.cwa-cli",{"title":183,"path":184,"stem":185,"children":186,"page":35},"Cwa Components","\u002Fnuxt-module\u002Fcwa-components","5.nuxt-module\u002F4.cwa-components",[187,191,195,199,203],{"title":188,"path":189,"stem":190},"\u003CCwaComponentGroup \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-component-group","5.nuxt-module\u002F4.cwa-components\u002F1.cwa-component-group",{"title":192,"path":193,"stem":194},"\u003CCwaPage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-page","5.nuxt-module\u002F4.cwa-components\u002F2.cwa-page",{"title":196,"path":197,"stem":198},"\u003CCwaLink \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-link","5.nuxt-module\u002F4.cwa-components\u002F3.cwa-link",{"title":200,"path":201,"stem":202},"\u003CCwaImage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-image","5.nuxt-module\u002F4.cwa-components\u002F4.cwa-image",{"title":204,"path":205,"stem":206},"\u003CCwaDefaultLayout \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-default-layout","5.nuxt-module\u002F4.cwa-components\u002F5.cwa-default-layout",{"title":208,"path":209,"stem":210},"The useCwa() API","\u002Fnuxt-module\u002Fcwa-api","5.nuxt-module\u002F5.cwa-api",{"title":212,"path":213,"stem":214,"children":215,"page":35},"Composables","\u002Fnuxt-module\u002Fcomposables","5.nuxt-module\u002F6.composables",[216,224,261,278],{"title":217,"path":218,"stem":219,"children":220,"page":35},"Layout","\u002Fnuxt-module\u002Fcomposables\u002Flayout","5.nuxt-module\u002F6.composables\u002F0.layout",[221],{"title":217,"path":222,"stem":223},"\u002Fnuxt-module\u002Fcomposables\u002Flayout\u002Fuse-cwa-layout","5.nuxt-module\u002F6.composables\u002F0.layout\u002F1.use-cwa-layout",{"title":225,"path":226,"stem":227,"children":228,"page":35},"Component","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent","5.nuxt-module\u002F6.composables\u002F1.component",[229,233,237,241,245,249,253,257],{"title":230,"path":231,"stem":232},"Component (recommended)","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-component","5.nuxt-module\u002F6.composables\u002F1.component\u002F0.use-cwa-component",{"title":234,"path":235,"stem":236},"Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F1.use-cwa-resource",{"title":238,"path":239,"stem":240},"Collection Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-collection-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F2.use-cwa-collection-resource",{"title":242,"path":243,"stem":244},"Image Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-image-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F3.use-cwa-image-resource",{"title":246,"path":247,"stem":248},"Form","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form","5.nuxt-module\u002F6.composables\u002F1.component\u002F4.use-cwa-form",{"title":250,"path":251,"stem":252},"Form Input","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-input","5.nuxt-module\u002F6.composables\u002F1.component\u002F5.use-cwa-form-input",{"title":254,"path":255,"stem":256},"Form Repeated","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-repeated","5.nuxt-module\u002F6.composables\u002F1.component\u002F6.use-cwa-form-repeated",{"title":258,"path":259,"stem":260},"Form Collection","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-collection","5.nuxt-module\u002F6.composables\u002F1.component\u002F7.use-cwa-form-collection",{"title":262,"path":263,"stem":264,"children":265,"page":35},"Admin Manager","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager","5.nuxt-module\u002F6.composables\u002F2.admin-manager",[266,270,274],{"title":267,"path":268,"stem":269},"Manager Tab","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-manager-tab","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F1.use-cwa-resource-manager-tab",{"title":271,"path":272,"stem":273},"Resource Model","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-model","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F2.use-cwa-resource-model",{"title":275,"path":276,"stem":277},"Resource Upload","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-upload","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F3.use-cwa-resource-upload",{"title":279,"path":280,"stem":281,"children":282,"page":35},"Utilities","\u002Fnuxt-module\u002Fcomposables\u002Futilities","5.nuxt-module\u002F6.composables\u002F3.utilities",[283,287,291],{"title":284,"path":285,"stem":286},"Resource Endpoint","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-endpoint","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F1.use-cwa-resource-endpoint",{"title":288,"path":289,"stem":290},"Query Model","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-query-bound-model","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F2.use-query-bound-model",{"title":292,"path":293,"stem":294},"Resource Route","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-route","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F3.use-cwa-resource-route",{"title":296,"path":297,"stem":298,"children":299,"page":35},"Component Helpers","\u002Fnuxt-module\u002Fcomponent-helpers","5.nuxt-module\u002F7.component-helpers",[300,304,308,312,316],{"title":301,"path":302,"stem":303},"Images & Media","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fimages-and-uploads","5.nuxt-module\u002F7.component-helpers\u002F1.images-and-uploads",{"title":305,"path":306,"stem":307},"Collections & Pagination","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fcollections-and-pagination","5.nuxt-module\u002F7.component-helpers\u002F2.collections-and-pagination",{"title":309,"path":310,"stem":311},"HTML Content","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fhtml-content","5.nuxt-module\u002F7.component-helpers\u002F3.html-content",{"title":313,"path":314,"stem":315},"Real-Time Updates","\u002Fnuxt-module\u002Fcomponent-helpers\u002Freal-time-updates","5.nuxt-module\u002F7.component-helpers\u002F4.real-time-updates",{"title":317,"path":318,"stem":319},"Forms","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fforms","5.nuxt-module\u002F7.component-helpers\u002F5.forms",{"title":321,"path":322,"stem":323},"Authentication","\u002Fnuxt-module\u002Fauthentication","5.nuxt-module\u002F8.authentication",{"title":325,"path":326,"stem":327,"children":328,"page":35},"Cwa Layer","\u002Fnuxt-module\u002Fcwa-layer","5.nuxt-module\u002F9.cwa-layer",[329,333,337],{"title":330,"path":331,"stem":332},"Overview","\u002Fnuxt-module\u002Fcwa-layer\u002Foverview","5.nuxt-module\u002F9.cwa-layer\u002F1.overview",{"title":334,"path":335,"stem":336},"Auth Pages","\u002Fnuxt-module\u002Fcwa-layer\u002Fauth-pages","5.nuxt-module\u002F9.cwa-layer\u002F2.auth-pages",{"title":338,"path":339,"stem":340},"Admin Panel","\u002Fnuxt-module\u002Fcwa-layer\u002Fadmin-panel","5.nuxt-module\u002F9.cwa-layer\u002F3.admin-panel",{"title":342,"path":343,"stem":344,"children":345,"page":35},"Deployment","\u002Fdeployment","6.deployment",[346,350,354],{"title":347,"path":348,"stem":349},"Docker","\u002Fdeployment\u002Fdocker","6.deployment\u002F1.docker",{"title":351,"path":352,"stem":353},"Kubernetes & Helm","\u002Fdeployment\u002Fkubernetes","6.deployment\u002F2.kubernetes",{"title":355,"path":356,"stem":357},"CI\u002FCD","\u002Fdeployment\u002Fci-cd","6.deployment\u002F3.ci-cd",{"id":359,"title":92,"badge":360,"body":363,"description":1472,"extension":1473,"links":1474,"meta":1475,"navigation":483,"path":93,"seo":1476,"stem":94,"__hash__":1477},"docs\u002F4.api\u002F2.components\u002F2.annotations\u002F1.publishable.md",{"label":361,"color":362},"Draft","amber",{"type":364,"value":365,"toc":1460},"minimark",[366,374,379,657,660,664,734,737,741,748,789,796,800,810,868,875,884,888,891,983,993,996,1031,1035,1040,1077,1080,1084,1098,1170,1176,1180,1185,1198,1205,1209,1216,1355,1427,1442,1446,1456],[367,368,369,373],"p",{},[370,371,372],"code",{},"#[Silverback\\Publishable]"," gives your component a twin-resource draft\u002Fpublish lifecycle. An admin edits the draft privately; visitors always see the published version. Publishing is atomic — the switch happens at the database level with no stale cache window.",[375,376,378],"h2",{"id":377},"setup","Setup",[380,381,386],"pre",{"className":382,"code":383,"language":384,"meta":385,"style":385},"language-php shiki shiki-themes github-light github-dark material-theme-palenight","use Silverback\\ApiComponentsBundle\\Annotation as Silverback;\nuse Silverback\\ApiComponentsBundle\\Entity\\Core\\AbstractComponent;\nuse Silverback\\ApiComponentsBundle\\Entity\\Utility\\PublishableTrait;\n\n#[Silverback\\Publishable]\n#[ORM\\Entity]\n#[ApiResource(mercure: true)]\nclass Title extends AbstractComponent\n{\n    use PublishableTrait;\n\n    #[ORM\\Column(type: 'text', nullable: true)]\n    public ?string $title = null;\n}\n","php","",[370,387,388,423,451,478,485,502,516,541,557,563,574,579,624,651],{"__ignoreMap":385},[389,390,393,397,401,405,408,410,413,416,419],"span",{"class":391,"line":392},"line",1,[389,394,396],{"class":395},"stmX-","use",[389,398,400],{"class":399},"sc2zw"," Silverback",[389,402,404],{"class":403},"sBtbT","\\",[389,406,407],{"class":399},"ApiComponentsBundle",[389,409,404],{"class":403},[389,411,412],{"class":399},"Annotation",[389,414,415],{"class":395}," as",[389,417,400],{"class":418},"sRCss",[389,420,422],{"class":421},"sOvfz",";\n",[389,424,426,428,430,432,434,436,439,441,444,446,449],{"class":391,"line":425},2,[389,427,396],{"class":395},[389,429,400],{"class":399},[389,431,404],{"class":403},[389,433,407],{"class":399},[389,435,404],{"class":403},[389,437,438],{"class":399},"Entity",[389,440,404],{"class":403},[389,442,443],{"class":399},"Core",[389,445,404],{"class":403},[389,447,448],{"class":399},"AbstractComponent",[389,450,422],{"class":421},[389,452,454,456,458,460,462,464,466,468,471,473,476],{"class":391,"line":453},3,[389,455,396],{"class":395},[389,457,400],{"class":399},[389,459,404],{"class":403},[389,461,407],{"class":399},[389,463,404],{"class":403},[389,465,438],{"class":399},[389,467,404],{"class":403},[389,469,470],{"class":399},"Utility",[389,472,404],{"class":403},[389,474,475],{"class":399},"PublishableTrait",[389,477,422],{"class":421},[389,479,481],{"class":391,"line":480},4,[389,482,484],{"emptyLinePlaceholder":483},true,"\n",[389,486,488,492,495,497,499],{"class":391,"line":487},5,[389,489,491],{"class":490},"sPB8G","#[",[389,493,494],{"class":399},"Silverback",[389,496,404],{"class":403},[389,498,92],{"class":399},[389,500,501],{"class":490},"]\n",[389,503,505,507,510,512,514],{"class":391,"line":504},6,[389,506,491],{"class":490},[389,508,509],{"class":399},"ORM",[389,511,404],{"class":403},[389,513,438],{"class":399},[389,515,501],{"class":490},[389,517,519,521,524,527,530,533,536,539],{"class":391,"line":518},7,[389,520,491],{"class":490},[389,522,523],{"class":399},"ApiResource",[389,525,526],{"class":421},"(",[389,528,529],{"class":418},"mercure",[389,531,532],{"class":421},":",[389,534,535],{"class":403}," true",[389,537,538],{"class":421},")",[389,540,501],{"class":490},[389,542,544,548,551,554],{"class":391,"line":543},8,[389,545,547],{"class":546},"swB56","class",[389,549,550],{"class":418}," Title",[389,552,553],{"class":546}," extends",[389,555,556],{"class":418}," AbstractComponent\n",[389,558,560],{"class":391,"line":559},9,[389,561,562],{"class":421},"{\n",[389,564,566,569,572],{"class":391,"line":565},10,[389,567,568],{"class":395},"    use",[389,570,571],{"class":399}," PublishableTrait",[389,573,422],{"class":421},[389,575,577],{"class":391,"line":576},11,[389,578,484],{"emptyLinePlaceholder":483},[389,580,582,585,587,589,592,594,597,599,603,607,610,613,616,618,620,622],{"class":391,"line":581},12,[389,583,584],{"class":490},"    #[",[389,586,509],{"class":399},[389,588,404],{"class":403},[389,590,591],{"class":399},"Column",[389,593,526],{"class":421},[389,595,596],{"class":418},"type",[389,598,532],{"class":421},[389,600,602],{"class":601},"seSrl"," '",[389,604,606],{"class":605},"sLL54","text",[389,608,609],{"class":601},"'",[389,611,612],{"class":421},",",[389,614,615],{"class":418}," nullable",[389,617,532],{"class":421},[389,619,535],{"class":403},[389,621,538],{"class":421},[389,623,501],{"class":490},[389,625,627,630,634,637,640,643,646,649],{"class":391,"line":626},13,[389,628,629],{"class":546},"    public",[389,631,633],{"class":632},"sVlFx"," ?",[389,635,636],{"class":395},"string",[389,638,639],{"class":421}," $",[389,641,642],{"class":490},"title ",[389,644,645],{"class":632},"=",[389,647,648],{"class":403}," null",[389,650,422],{"class":421},[389,652,654],{"class":391,"line":653},14,[389,655,656],{"class":421},"}\n",[367,658,659],{},"That's all that's required. The trait and annotation together wire up the full lifecycle.",[375,661,663],{"id":662},"what-publishabletrait-adds","What PublishableTrait Adds",[665,666,667,683],"table",{},[668,669,670],"thead",{},[671,672,673,677,680],"tr",{},[674,675,676],"th",{},"Property",[674,678,679],{},"Type",[674,681,682],{},"Description",[684,685,686,705,720],"tbody",{},[671,687,688,694,699],{},[689,690,691],"td",{},[370,692,693],{},"publishedAt",[689,695,696],{},[370,697,698],{},"?DateTimeInterface",[689,700,701,704],{},[370,702,703],{},"null"," = unpublished draft",[671,706,707,712,717],{},[689,708,709],{},[370,710,711],{},"publishedResource",[689,713,714],{},[370,715,716],{},"?self",[689,718,719],{},"Points from draft → published twin",[671,721,722,727,731],{},[689,723,724],{},[370,725,726],{},"draftResource",[689,728,729],{},[370,730,716],{},[689,732,733],{},"Points from published → draft twin",[367,735,736],{},"The bundle creates and maintains these twins automatically. You never create the published twin manually.",[375,738,740],{"id":739},"how-it-works-at-the-api-level","How It Works at the API Level",[367,742,743,744,747],{},"The bundle intercepts requests and routes based on the caller's role and the ",[370,745,746],{},"published"," query parameter:",[665,749,750,760],{},[668,751,752],{},[671,753,754,757],{},[674,755,756],{},"Caller",[674,758,759],{},"Gets",[684,761,762,770,778],{},[671,763,764,767],{},[689,765,766],{},"Anonymous visitor",[689,768,769],{},"Published version (or 404 if never published)",[671,771,772,775],{},[689,773,774],{},"Admin in edit mode",[689,776,777],{},"Draft version",[671,779,780,786],{},[689,781,782,783],{},"Direct ",[370,784,785],{},"?published=true",[689,787,788],{},"Published version explicitly",[367,790,791,792,795],{},"The Nuxt module handles the ",[370,793,794],{},"?published=false"," parameter automatically in edit mode — you don't add it manually.",[375,797,799],{"id":798},"publishing-a-resource","Publishing a Resource",[367,801,802,803,806,807,809],{},"Send a ",[370,804,805],{},"PATCH"," with ",[370,808,693],{}," set to a date string:",[380,811,815],{"className":812,"code":813,"language":814,"meta":385,"style":385},"language-json shiki shiki-themes github-light github-dark material-theme-palenight","PATCH \u002Fcomponent\u002Ftitles\u002F018e-...\nContent-Type: application\u002Fmerge-patch+json\n\n{\n    \"publishedAt\": \"2024-01-15T10:30:00+00:00\"\n}\n","json",[370,816,817,829,834,838,842,864],{"__ignoreMap":385},[389,818,819,822,826],{"class":391,"line":392},[389,820,821],{"class":490},"PATCH \u002Fcomponent\u002Ftitles\u002F",[389,823,825],{"class":824},"scSvc","018",[389,827,828],{"class":490},"e-...\n",[389,830,831],{"class":391,"line":425},[389,832,833],{"class":490},"Content-Type: application\u002Fmerge-patch+json\n",[389,835,836],{"class":391,"line":453},[389,837,484],{"emptyLinePlaceholder":483},[389,839,840],{"class":391,"line":480},[389,841,562],{"class":421},[389,843,844,847,850,853,855,858,861],{"class":391,"line":487},[389,845,846],{"class":403},"    \"",[389,848,693],{"class":849},"sphPO",[389,851,852],{"class":403},"\"",[389,854,532],{"class":421},[389,856,857],{"class":601}," \"",[389,859,860],{"class":605},"2024-01-15T10:30:00+00:00",[389,862,863],{"class":601},"\"\n",[389,865,866],{"class":391,"line":504},[389,867,656],{"class":421},[367,869,870,871,874],{},"The bundle creates or updates the published twin and broadcasts a Mercure update if ",[370,872,873],{},"mercure: true"," is on the entity.",[367,876,877,878,806,880,883],{},"To unpublish: ",[370,879,805],{},[370,881,882],{},"\"publishedAt\": null",".",[375,885,887],{"id":886},"publish-only-validation","Publish-Only Validation",[367,889,890],{},"Some fields should only be required when going live, not while saving a draft:",[380,892,894],{"className":382,"code":893,"language":384,"meta":385,"style":385},"#[ORM\\Column(type: 'text', nullable: true)]\n#[Assert\\NotBlank(groups: ['Title:published'])]\npublic ?string $title = null;\n",[370,895,896,930,964],{"__ignoreMap":385},[389,897,898,900,902,904,906,908,910,912,914,916,918,920,922,924,926,928],{"class":391,"line":392},[389,899,491],{"class":490},[389,901,509],{"class":399},[389,903,404],{"class":403},[389,905,591],{"class":399},[389,907,526],{"class":421},[389,909,596],{"class":418},[389,911,532],{"class":421},[389,913,602],{"class":601},[389,915,606],{"class":605},[389,917,609],{"class":601},[389,919,612],{"class":421},[389,921,615],{"class":418},[389,923,532],{"class":421},[389,925,535],{"class":403},[389,927,538],{"class":421},[389,929,501],{"class":490},[389,931,932,934,937,939,942,944,947,949,952,954,957,959,962],{"class":391,"line":425},[389,933,491],{"class":490},[389,935,936],{"class":399},"Assert",[389,938,404],{"class":403},[389,940,941],{"class":399},"NotBlank",[389,943,526],{"class":421},[389,945,946],{"class":418},"groups",[389,948,532],{"class":421},[389,950,951],{"class":421}," [",[389,953,609],{"class":601},[389,955,956],{"class":605},"Title:published",[389,958,609],{"class":601},[389,960,961],{"class":421},"])",[389,963,501],{"class":490},[389,965,966,969,971,973,975,977,979,981],{"class":391,"line":453},[389,967,968],{"class":546},"public",[389,970,633],{"class":632},[389,972,636],{"class":395},[389,974,639],{"class":421},[389,976,642],{"class":490},[389,978,645],{"class":632},[389,980,648],{"class":403},[389,982,422],{"class":421},[367,984,985,986,989,990,992],{},"The convention for the publish validation group is ",[370,987,988],{},"ClassName:published",". The bundle applies this group automatically when ",[370,991,693],{}," is being set.",[367,994,995],{},"Customise the group name:",[380,997,999],{"className":382,"code":998,"language":384,"meta":385,"style":385},"#[Silverback\\Publishable(validationGroups: ['my_custom_group'])]\n",[370,1000,1001],{"__ignoreMap":385},[389,1002,1003,1005,1007,1009,1011,1013,1016,1018,1020,1022,1025,1027,1029],{"class":391,"line":392},[389,1004,491],{"class":490},[389,1006,494],{"class":399},[389,1008,404],{"class":403},[389,1010,92],{"class":399},[389,1012,526],{"class":421},[389,1014,1015],{"class":418},"validationGroups",[389,1017,532],{"class":421},[389,1019,951],{"class":421},[389,1021,609],{"class":601},[389,1023,1024],{"class":605},"my_custom_group",[389,1026,609],{"class":601},[389,1028,961],{"class":421},[389,1030,501],{"class":490},[375,1032,1034],{"id":1033},"configuring-who-can-publish","Configuring Who Can Publish",[367,1036,1037,1038,532],{},"Set the security expression in the bundle config. Only users matching this expression can set ",[370,1039,693],{},[380,1041,1045],{"className":1042,"code":1043,"language":1044,"meta":385,"style":385},"language-yaml shiki shiki-themes github-light github-dark material-theme-palenight","silverback_api_components:\n    publishable:\n        permission: \"is_granted('ROLE_ADMIN')\"\n","yaml",[370,1046,1047,1056,1063],{"__ignoreMap":385},[389,1048,1049,1053],{"class":391,"line":392},[389,1050,1052],{"class":1051},"s-h7I","silverback_api_components",[389,1054,1055],{"class":421},":\n",[389,1057,1058,1061],{"class":391,"line":425},[389,1059,1060],{"class":1051},"    publishable",[389,1062,1055],{"class":421},[389,1064,1065,1068,1070,1072,1075],{"class":391,"line":453},[389,1066,1067],{"class":1051},"        permission",[389,1069,532],{"class":421},[389,1071,857],{"class":601},[389,1073,1074],{"class":605},"is_granted('ROLE_ADMIN')",[389,1076,863],{"class":601},[367,1078,1079],{},"Non-admin users can still PATCH a resource's other fields — they just can't flip the publish switch.",[375,1081,1083],{"id":1082},"custom-property-names","Custom Property Names",[367,1085,1086,1087,1089,1090,1089,1092,1094,1095,1097],{},"The default property names (",[370,1088,693],{},", ",[370,1091,711],{},[370,1093,726],{},") match what ",[370,1096,475],{}," declares. Override them when names conflict with your own fields:",[380,1099,1101],{"className":382,"code":1100,"language":384,"meta":385,"style":385},"#[Silverback\\Publishable(\n    fieldName: 'publicationDate',\n    associationName: 'original',\n    reverseAssociationName: 'draft'\n)]\n",[370,1102,1103,1116,1133,1149,1164],{"__ignoreMap":385},[389,1104,1105,1107,1109,1111,1113],{"class":391,"line":392},[389,1106,491],{"class":490},[389,1108,494],{"class":399},[389,1110,404],{"class":403},[389,1112,92],{"class":399},[389,1114,1115],{"class":421},"(\n",[389,1117,1118,1121,1123,1125,1128,1130],{"class":391,"line":425},[389,1119,1120],{"class":418},"    fieldName",[389,1122,532],{"class":421},[389,1124,602],{"class":601},[389,1126,1127],{"class":605},"publicationDate",[389,1129,609],{"class":601},[389,1131,1132],{"class":421},",\n",[389,1134,1135,1138,1140,1142,1145,1147],{"class":391,"line":453},[389,1136,1137],{"class":418},"    associationName",[389,1139,532],{"class":421},[389,1141,602],{"class":601},[389,1143,1144],{"class":605},"original",[389,1146,609],{"class":601},[389,1148,1132],{"class":421},[389,1150,1151,1154,1156,1158,1161],{"class":391,"line":480},[389,1152,1153],{"class":418},"    reverseAssociationName",[389,1155,532],{"class":421},[389,1157,602],{"class":601},[389,1159,1160],{"class":605},"draft",[389,1162,1163],{"class":601},"'\n",[389,1165,1166,1168],{"class":391,"line":487},[389,1167,538],{"class":421},[389,1169,501],{"class":490},[367,1171,1172,1173,1175],{},"If you customise names, don't use ",[370,1174,475],{}," — declare the properties yourself using the matching names.",[375,1177,1179],{"id":1178},"migration-notes","Migration Notes",[367,1181,1182,1184],{},[370,1183,475],{}," adds:",[1186,1187,1188,1195],"ul",{},[1189,1190,1191,1192,538],"li",{},"1 nullable datetime column (",[370,1193,1194],{},"published_at",[1189,1196,1197],{},"2 nullable self-referencing foreign keys (published_resource_id, draft_resource_id)",[367,1199,1200,1201,1204],{},"Always review the generated Doctrine migration. The self-referencing keys use ",[370,1202,1203],{},"ON DELETE SET NULL"," so deleting a draft doesn't cascade to the published version.",[375,1206,1208],{"id":1207},"api-response-metadata","API Response Metadata",[367,1210,1211,1212,1215],{},"Every publishable component response includes a ",[370,1213,1214],{},"_metadata.publishable"," object visible to admin users:",[380,1217,1219],{"className":812,"code":1218,"language":814,"meta":385,"style":385},"{\n  \"@id\": \"\u002Fcomponent\u002Ftitles\u002F018e-...\",\n  \"title\": \"My Heading\",\n  \"_metadata\": {\n    \"publishable\": {\n      \"published\": true,\n      \"publishedAt\": \"2024-01-15T10:30:00+00:00\",\n      \"locationCount\": 3\n    }\n  }\n}\n",[370,1220,1221,1225,1246,1266,1280,1294,1309,1327,1341,1346,1351],{"__ignoreMap":385},[389,1222,1223],{"class":391,"line":392},[389,1224,562],{"class":421},[389,1226,1227,1230,1233,1235,1237,1239,1242,1244],{"class":391,"line":425},[389,1228,1229],{"class":403},"  \"",[389,1231,1232],{"class":849},"@id",[389,1234,852],{"class":403},[389,1236,532],{"class":421},[389,1238,857],{"class":601},[389,1240,1241],{"class":605},"\u002Fcomponent\u002Ftitles\u002F018e-...",[389,1243,852],{"class":601},[389,1245,1132],{"class":421},[389,1247,1248,1250,1253,1255,1257,1259,1262,1264],{"class":391,"line":453},[389,1249,1229],{"class":403},[389,1251,1252],{"class":849},"title",[389,1254,852],{"class":403},[389,1256,532],{"class":421},[389,1258,857],{"class":601},[389,1260,1261],{"class":605},"My Heading",[389,1263,852],{"class":601},[389,1265,1132],{"class":421},[389,1267,1268,1270,1273,1275,1277],{"class":391,"line":480},[389,1269,1229],{"class":403},[389,1271,1272],{"class":849},"_metadata",[389,1274,852],{"class":403},[389,1276,532],{"class":421},[389,1278,1279],{"class":421}," {\n",[389,1281,1282,1284,1288,1290,1292],{"class":391,"line":487},[389,1283,846],{"class":403},[389,1285,1287],{"class":1286},"sbW4m","publishable",[389,1289,852],{"class":403},[389,1291,532],{"class":421},[389,1293,1279],{"class":421},[389,1295,1296,1299,1301,1303,1305,1307],{"class":391,"line":504},[389,1297,1298],{"class":403},"      \"",[389,1300,746],{"class":824},[389,1302,852],{"class":403},[389,1304,532],{"class":421},[389,1306,535],{"class":403},[389,1308,1132],{"class":421},[389,1310,1311,1313,1315,1317,1319,1321,1323,1325],{"class":391,"line":518},[389,1312,1298],{"class":403},[389,1314,693],{"class":824},[389,1316,852],{"class":403},[389,1318,532],{"class":421},[389,1320,857],{"class":601},[389,1322,860],{"class":605},[389,1324,852],{"class":601},[389,1326,1132],{"class":421},[389,1328,1329,1331,1334,1336,1338],{"class":391,"line":543},[389,1330,1298],{"class":403},[389,1332,1333],{"class":824},"locationCount",[389,1335,852],{"class":403},[389,1337,532],{"class":421},[389,1339,1340],{"class":824}," 3\n",[389,1342,1343],{"class":391,"line":559},[389,1344,1345],{"class":421},"    }\n",[389,1347,1348],{"class":391,"line":565},[389,1349,1350],{"class":421},"  }\n",[389,1352,1353],{"class":391,"line":576},[389,1354,656],{"class":421},[665,1356,1357,1368],{},[668,1358,1359],{},[671,1360,1361,1364,1366],{},[674,1362,1363],{},"Field",[674,1365,679],{},[674,1367,682],{},[684,1369,1370,1384,1401],{},[671,1371,1372,1376,1381],{},[689,1373,1374],{},[370,1375,746],{},[689,1377,1378],{},[370,1379,1380],{},"boolean",[689,1382,1383],{},"Whether the published twin exists",[671,1385,1386,1390,1395],{},[689,1387,1388],{},[370,1389,693],{},[689,1391,1392],{},[370,1393,1394],{},"string | null",[689,1396,1397,1398,1400],{},"ISO 8601 timestamp of last publish, or ",[370,1399,703],{}," if unpublished",[671,1402,1403,1407,1412],{},[689,1404,1405],{},[370,1406,1333],{},[689,1408,1409],{},[370,1410,1411],{},"integer | null",[689,1413,1414,1415,1418,1419,1422,1423,1426],{},"Total number of places this component appears — counts both direct ",[370,1416,1417],{},"ComponentPosition"," references and ",[370,1420,1421],{},"AbstractPageData"," instances that hold it as a typed property (resolved via ",[370,1424,1425],{},"pageDataProperty"," positions at render time). Useful for showing admins \"used in N places\" before deleting.",[367,1428,1429,1431,1432,1434,1435,1438,1439,1441],{},[370,1430,1333],{}," is ",[370,1433,703],{}," for component types that have no ",[370,1436,1437],{},"getComponentPositions()"," method. Anonymous visitors do not receive ",[370,1440,1272],{}," at all.",[375,1443,1445],{"id":1444},"interaction-with-mercure","Interaction with Mercure",[367,1447,1448,1449,1451,1452,1455],{},"When a resource is published (or unpublished), if ",[370,1450,873],{}," is on the ",[370,1453,1454],{},"#[ApiResource]",", the API broadcasts an update to the hub. Every browser that has loaded the resource receives the new content in real time with no page reload needed.",[1457,1458,1459],"style",{},"html pre.shiki code .stmX-, html code.shiki .stmX-{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F78C6C}html pre.shiki code .sc2zw, html code.shiki .sc2zw{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#BABED8}html pre.shiki code .sBtbT, html code.shiki .sBtbT{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#89DDFF}html pre.shiki code .sRCss, html code.shiki .sRCss{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#FFCB6B}html pre.shiki code .sOvfz, html code.shiki .sOvfz{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#89DDFF}html pre.shiki code .sPB8G, html code.shiki .sPB8G{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#BABED8}html pre.shiki code .swB56, html code.shiki .swB56{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#C792EA}html pre.shiki code .seSrl, html code.shiki .seSrl{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#89DDFF}html pre.shiki code .sLL54, html code.shiki .sLL54{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#C3E88D}html pre.shiki code .sVlFx, html code.shiki .sVlFx{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#89DDFF}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 .scSvc, html code.shiki .scSvc{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#F78C6C}html pre.shiki code .sphPO, html code.shiki .sphPO{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#C792EA}html pre.shiki code .s-h7I, html code.shiki .s-h7I{--shiki-light:#22863A;--shiki-default:#85E89D;--shiki-dark:#F07178}html pre.shiki code .sbW4m, html code.shiki .sbW4m{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#FFCB6B}",{"title":385,"searchDepth":425,"depth":425,"links":1461},[1462,1463,1464,1465,1466,1467,1468,1469,1470,1471],{"id":377,"depth":425,"text":378},{"id":662,"depth":425,"text":663},{"id":739,"depth":425,"text":740},{"id":798,"depth":425,"text":799},{"id":886,"depth":425,"text":887},{"id":1033,"depth":425,"text":1034},{"id":1082,"depth":425,"text":1083},{"id":1178,"depth":425,"text":1179},{"id":1207,"depth":425,"text":1208},{"id":1444,"depth":425,"text":1445},"Add a draft\u002Fpublish workflow to any component so admins can edit content privately before making it live.","md",null,{},{"title":92,"description":1472},"TVNclyfQTDupRJVJQ4cIh4i-NdJKrXFzEaJZ24MUuWw",[1479,1481],{"title":83,"path":84,"stem":85,"description":1480,"children":-1},"How to define a custom content resource by extending AbstractComponent, adding API Platform metadata, and running migrations.",{"title":96,"path":97,"stem":98,"description":1482,"children":-1},"Add file upload support to any component with Flysystem adapters and optional Imagine image processing.",1782512901918]