[{"data":1,"prerenderedAt":8561},["ShallowReactive",2],{"articles-page":3,"articles":23},{"id":4,"title":5,"author":6,"body":6,"date":6,"description":7,"draft":8,"extension":9,"image":6,"lastmod":6,"meta":10,"minRead":6,"navigation":18,"path":19,"seo":20,"stem":21,"__hash__":22},"articles\u002Farticles.yml","Articles",null,"Thoughts, tutorials, and insights about web development, programming, and technology.",false,"yml",{"links":11},[12],{"label":13,"icon":14,"to":15,"variant":16,"color":17},"RSS Feed","lucide:rss","\u002Farticles\u002Frss.xml","outline","neutral",true,"\u002Farticles",{"title":5,"description":7},"articles","tNwPWBv1WB84WpbyIQmNhF7f601BIKGrRR-3ZsvVAB4",[24,2453,4632,5505,6309,6700,7410,8556],{"id":25,"title":26,"author":6,"body":27,"date":2438,"description":33,"draft":8,"extension":2439,"image":6,"lastmod":2438,"meta":2440,"minRead":6,"navigation":18,"path":2449,"seo":2450,"stem":2451,"__hash__":2452},"articles\u002Farticles\u002Fnuxt-ui-custom-button-variants.md","Adding Custom Button Variants in Nuxt UI",{"type":28,"value":29,"toc":2419},"minimark",[30,34,41,49,54,72,79,83,86,99,103,106,130,133,137,144,479,484,535,545,549,555,819,823,879,883,886,1228,1231,1383,1387,1390,1614,1618,1621,1624,1917,1922,2186,2189,2262,2268,2292,2296,2338,2342,2353,2369,2373,2379,2382,2386,2411,2415],[31,32,33],"p",{},"Learn how to extend Nuxt UI's button component with custom variants like a stunning skew animation effect. We'll explore app.config.ts configuration, CSS pseudo-elements, and compound variants to create unique button styles that match your brand.",[31,35,36,40],{},[37,38,39],"strong",{},"Here's what we'll be building"," - try hovering over the buttons:",[42,43,46],"component-frame",{"description":44,"title":45},"A showcase of custom button animations built with Nuxt UI and CSS pseudo-elements.","Skew Button Variants",[47,48],"button-skew-demo",{},[50,51,53],"h2",{"id":52},"the-challenge","The Challenge",[31,55,56,57,61,62,61,64,67,68,71],{},"Nuxt UI provides excellent built-in button variants like ",[58,59,60],"code",{},"solid",", ",[58,63,16],{},[58,65,66],{},"soft",", and ",[58,69,70],{},"ghost",". But what if you want something more unique? Something that makes your buttons stand out with eye-catching animations?",[31,73,74,75,78],{},"In this tutorial, I'll show you how I created a custom ",[37,76,77],{},"skew"," button variant that features an animated background that sweeps across the button on hover - a signature effect for my portfolio.",[50,80,82],{"id":81},"prerequisites","Prerequisites",[31,84,85],{},"Before we start, make sure you have:",[87,88,89,93,96],"ul",{},[90,91,92],"li",{},"Nuxt project with Nuxt UI v4 installed",[90,94,95],{},"Basic understanding of Tailwind CSS",[90,97,98],{},"Familiarity with CSS pseudo-elements",[50,100,102],{"id":101},"the-approach","The Approach",[31,104,105],{},"Creating a custom button variant in Nuxt UI involves three steps:",[107,108,109,115,124],"ol",{},[90,110,111,114],{},[37,112,113],{},"Define the CSS animation"," in your global stylesheet",[90,116,117,120,121],{},[37,118,119],{},"Register the variant"," in ",[58,122,123],{},"app.config.ts",[90,125,126,129],{},[37,127,128],{},"Add compound variants"," for different color options",[31,131,132],{},"Let's dive in!",[50,134,136],{"id":135},"step-1-the-css-animation","Step 1: The CSS Animation",[31,138,139,140,143],{},"First, we need to create the skew animation using CSS pseudo-elements. Add this to your ",[58,141,142],{},"assets\u002Fcss\u002Fmain.css",":",[145,146,152],"pre",{"className":147,"code":148,"filename":149,"language":150,"meta":151,"style":151},"language-css shiki shiki-themes material-theme-lighter one-light one-dark-pro","@layer base {\n  \u002F* Skew Button Animation *\u002F\n  .btn-skew {\n    position: relative;\n    overflow: hidden;\n    z-index: 0;\n  }\n\n  .btn-skew::before {\n    content: \"\";\n    position: absolute;\n    top: 0;\n    left: -25px;\n    height: 100%;\n    width: 0%;\n    background-color: var(--ui-primary);\n    transform: skewX(35deg);\n    z-index: -1;\n    transition: width 500ms ease-out;\n  }\n\n  .btn-skew:hover::before {\n    width: 150%;\n  }\n}\n","main.css","css","",[58,153,154,171,178,192,208,221,235,241,247,264,278,290,302,319,335,349,371,392,404,426,431,436,454,468,473],{"__ignoreMap":151},[155,156,159,163,167],"span",{"class":157,"line":158},"line",1,[155,160,162],{"class":161},"sQsOY","@layer",[155,164,166],{"class":165},"sM89C"," base ",[155,168,170],{"class":169},"sB4Xn","{\n",[155,172,174],{"class":157,"line":173},2,[155,175,177],{"class":176},"seacL","  \u002F* Skew Button Animation *\u002F\n",[155,179,181,185,189],{"class":157,"line":180},3,[155,182,184],{"class":183},"svDm9","  .",[155,186,188],{"class":187},"s6wAS","btn-skew",[155,190,191],{"class":169}," {\n",[155,193,195,199,201,205],{"class":157,"line":194},4,[155,196,198],{"class":197},"sGRuu","    position",[155,200,143],{"class":169},[155,202,204],{"class":203},"sngOx"," relative",[155,206,207],{"class":169},";\n",[155,209,211,214,216,219],{"class":157,"line":210},5,[155,212,213],{"class":197},"    overflow",[155,215,143],{"class":169},[155,217,218],{"class":203}," hidden",[155,220,207],{"class":169},[155,222,224,227,229,233],{"class":157,"line":223},6,[155,225,226],{"class":197},"    z-index",[155,228,143],{"class":169},[155,230,232],{"class":231},"sriKn"," 0",[155,234,207],{"class":169},[155,236,238],{"class":157,"line":237},7,[155,239,240],{"class":169},"  }\n",[155,242,244],{"class":157,"line":243},8,[155,245,246],{"emptyLinePlaceholder":18},"\n",[155,248,250,252,254,258,262],{"class":157,"line":249},9,[155,251,184],{"class":183},[155,253,188],{"class":187},[155,255,257],{"class":256},"sst0O","::",[155,259,261],{"class":260},"sSxop","before",[155,263,191],{"class":169},[155,265,267,270,272,276],{"class":157,"line":266},10,[155,268,269],{"class":197},"    content",[155,271,143],{"class":169},[155,273,275],{"class":274},"sVH1b"," \"\"",[155,277,207],{"class":169},[155,279,281,283,285,288],{"class":157,"line":280},11,[155,282,198],{"class":197},[155,284,143],{"class":169},[155,286,287],{"class":203}," absolute",[155,289,207],{"class":169},[155,291,293,296,298,300],{"class":157,"line":292},12,[155,294,295],{"class":197},"    top",[155,297,143],{"class":169},[155,299,232],{"class":231},[155,301,207],{"class":169},[155,303,305,308,310,313,317],{"class":157,"line":304},13,[155,306,307],{"class":197},"    left",[155,309,143],{"class":169},[155,311,312],{"class":231}," -25",[155,314,316],{"class":315},"sLhkd","px",[155,318,207],{"class":169},[155,320,322,325,327,330,333],{"class":157,"line":321},14,[155,323,324],{"class":197},"    height",[155,326,143],{"class":169},[155,328,329],{"class":231}," 100",[155,331,332],{"class":315},"%",[155,334,207],{"class":169},[155,336,338,341,343,345,347],{"class":157,"line":337},15,[155,339,340],{"class":197},"    width",[155,342,143],{"class":169},[155,344,232],{"class":231},[155,346,332],{"class":315},[155,348,207],{"class":169},[155,350,352,355,357,361,364,368],{"class":157,"line":351},16,[155,353,354],{"class":197},"    background-color",[155,356,143],{"class":169},[155,358,360],{"class":359},"sTDPv"," var",[155,362,363],{"class":169},"(",[155,365,367],{"class":366},"s8dPH","--ui-primary",[155,369,370],{"class":169},");\n",[155,372,374,377,379,382,384,387,390],{"class":157,"line":373},17,[155,375,376],{"class":197},"    transform",[155,378,143],{"class":169},[155,380,381],{"class":359}," skewX",[155,383,363],{"class":169},[155,385,386],{"class":231},"35",[155,388,389],{"class":315},"deg",[155,391,370],{"class":169},[155,393,395,397,399,402],{"class":157,"line":394},18,[155,396,226],{"class":197},[155,398,143],{"class":169},[155,400,401],{"class":231}," -1",[155,403,207],{"class":169},[155,405,407,410,412,415,418,421,424],{"class":157,"line":406},19,[155,408,409],{"class":197},"    transition",[155,411,143],{"class":169},[155,413,414],{"class":165}," width ",[155,416,417],{"class":231},"500",[155,419,420],{"class":315},"ms",[155,422,423],{"class":203}," ease-out",[155,425,207],{"class":169},[155,427,429],{"class":157,"line":428},20,[155,430,240],{"class":169},[155,432,434],{"class":157,"line":433},21,[155,435,246],{"emptyLinePlaceholder":18},[155,437,439,441,443,445,448,450,452],{"class":157,"line":438},22,[155,440,184],{"class":183},[155,442,188],{"class":187},[155,444,143],{"class":256},[155,446,447],{"class":260},"hover",[155,449,257],{"class":256},[155,451,261],{"class":260},[155,453,191],{"class":169},[155,455,457,459,461,464,466],{"class":157,"line":456},23,[155,458,340],{"class":197},[155,460,143],{"class":169},[155,462,463],{"class":231}," 150",[155,465,332],{"class":315},[155,467,207],{"class":169},[155,469,471],{"class":157,"line":470},24,[155,472,240],{"class":169},[155,474,476],{"class":157,"line":475},25,[155,477,478],{"class":169},"}\n",[480,481,483],"h3",{"id":482},"how-it-works","How It Works",[107,485,486,498,507,515,527],{},[90,487,488,497],{},[37,489,490,493,494],{},[58,491,492],{},"position: relative"," & ",[58,495,496],{},"overflow: hidden",": Creates a containing box for the pseudo-element and clips any overflow",[90,499,500,506],{},[37,501,502,505],{},[58,503,504],{},"::before"," pseudo-element",": Creates an invisible layer behind the button",[90,508,509,514],{},[37,510,511],{},[58,512,513],{},"transform: skewX(35deg)",": Gives the sliding background its angled edge",[90,516,517,526],{},[37,518,519,522,523],{},[58,520,521],{},"width: 0%"," → ",[58,524,525],{},"width: 150%",": Animates from invisible to fully covering on hover",[90,528,529,534],{},[37,530,531],{},[58,532,533],{},"var(--ui-primary)",": Uses Nuxt UI's theme color variable",[536,537,538],"note",{},[31,539,540,541,544],{},"The ",[58,542,543],{},"z-index: -1"," on the pseudo-element ensures the animated background stays behind the button text.",[50,546,548],{"id":547},"step-2-register-the-variant","Step 2: Register the Variant",[31,550,551,552,554],{},"Now we register our custom variant in ",[58,553,123],{},". This is where Nuxt UI's extensibility shines:",[556,557,558],"code-collapse",{},[145,559,563],{"className":560,"code":561,"filename":123,"language":562,"meta":151,"style":151},"language-typescript shiki shiki-themes material-theme-lighter one-light one-dark-pro","export default defineAppConfig({\n  ui: {\n    colors: {\n      primary: \"red\",\n      neutral: \"zinc\",\n    },\n    button: {\n      variants: {\n        variant: {\n          skew: {\n            base: [\n              \"btn-skew\",\n              \"border border-neutral-300 dark:border-neutral-700\",\n              \"bg-default\",\n              \"transition-all duration-300\",\n              \"hover:border-primary\",\n              \"hover:text-white dark:hover:text-default\",\n              \"disabled:cursor-not-allowed\",\n              \"disabled:opacity-50\",\n            ],\n          },\n        },\n      },\n    },\n  },\n});\n","typescript",[58,564,565,582,593,602,622,638,643,652,661,670,679,689,700,711,722,733,744,755,766,777,784,789,794,799,803,808],{"__ignoreMap":151},[155,566,567,570,574,578,580],{"class":157,"line":158},[155,568,569],{"class":161},"export",[155,571,573],{"class":572},"sH50Z"," default",[155,575,577],{"class":576},"spnjr"," defineAppConfig",[155,579,363],{"class":165},[155,581,170],{"class":169},[155,583,584,588,591],{"class":157,"line":173},[155,585,587],{"class":586},"su13H","  ui",[155,589,143],{"class":590},"saKOp",[155,592,191],{"class":169},[155,594,595,598,600],{"class":157,"line":180},[155,596,597],{"class":586},"    colors",[155,599,143],{"class":590},[155,601,191],{"class":169},[155,603,604,607,609,612,616,619],{"class":157,"line":194},[155,605,606],{"class":586},"      primary",[155,608,143],{"class":590},[155,610,611],{"class":274}," \"",[155,613,615],{"class":614},"spZWa","red",[155,617,618],{"class":274},"\"",[155,620,621],{"class":169},",\n",[155,623,624,627,629,631,634,636],{"class":157,"line":210},[155,625,626],{"class":586},"      neutral",[155,628,143],{"class":590},[155,630,611],{"class":274},[155,632,633],{"class":614},"zinc",[155,635,618],{"class":274},[155,637,621],{"class":169},[155,639,640],{"class":157,"line":223},[155,641,642],{"class":169},"    },\n",[155,644,645,648,650],{"class":157,"line":237},[155,646,647],{"class":586},"    button",[155,649,143],{"class":590},[155,651,191],{"class":169},[155,653,654,657,659],{"class":157,"line":243},[155,655,656],{"class":586},"      variants",[155,658,143],{"class":590},[155,660,191],{"class":169},[155,662,663,666,668],{"class":157,"line":249},[155,664,665],{"class":586},"        variant",[155,667,143],{"class":590},[155,669,191],{"class":169},[155,671,672,675,677],{"class":157,"line":266},[155,673,674],{"class":586},"          skew",[155,676,143],{"class":590},[155,678,191],{"class":169},[155,680,681,684,686],{"class":157,"line":280},[155,682,683],{"class":586},"            base",[155,685,143],{"class":590},[155,687,688],{"class":165}," [\n",[155,690,691,694,696,698],{"class":157,"line":292},[155,692,693],{"class":274},"              \"",[155,695,188],{"class":614},[155,697,618],{"class":274},[155,699,621],{"class":169},[155,701,702,704,707,709],{"class":157,"line":304},[155,703,693],{"class":274},[155,705,706],{"class":614},"border border-neutral-300 dark:border-neutral-700",[155,708,618],{"class":274},[155,710,621],{"class":169},[155,712,713,715,718,720],{"class":157,"line":321},[155,714,693],{"class":274},[155,716,717],{"class":614},"bg-default",[155,719,618],{"class":274},[155,721,621],{"class":169},[155,723,724,726,729,731],{"class":157,"line":337},[155,725,693],{"class":274},[155,727,728],{"class":614},"transition-all duration-300",[155,730,618],{"class":274},[155,732,621],{"class":169},[155,734,735,737,740,742],{"class":157,"line":351},[155,736,693],{"class":274},[155,738,739],{"class":614},"hover:border-primary",[155,741,618],{"class":274},[155,743,621],{"class":169},[155,745,746,748,751,753],{"class":157,"line":373},[155,747,693],{"class":274},[155,749,750],{"class":614},"hover:text-white dark:hover:text-default",[155,752,618],{"class":274},[155,754,621],{"class":169},[155,756,757,759,762,764],{"class":157,"line":394},[155,758,693],{"class":274},[155,760,761],{"class":614},"disabled:cursor-not-allowed",[155,763,618],{"class":274},[155,765,621],{"class":169},[155,767,768,770,773,775],{"class":157,"line":406},[155,769,693],{"class":274},[155,771,772],{"class":614},"disabled:opacity-50",[155,774,618],{"class":274},[155,776,621],{"class":169},[155,778,779,782],{"class":157,"line":428},[155,780,781],{"class":165},"            ]",[155,783,621],{"class":169},[155,785,786],{"class":157,"line":433},[155,787,788],{"class":169},"          },\n",[155,790,791],{"class":157,"line":438},[155,792,793],{"class":169},"        },\n",[155,795,796],{"class":157,"line":456},[155,797,798],{"class":169},"      },\n",[155,800,801],{"class":157,"line":470},[155,802,642],{"class":169},[155,804,805],{"class":157,"line":475},[155,806,807],{"class":169},"  },\n",[155,809,811,814,817],{"class":157,"line":810},26,[155,812,813],{"class":169},"}",[155,815,816],{"class":165},")",[155,818,207],{"class":169},[480,820,822],{"id":821},"breaking-down-the-configuration","Breaking Down the Configuration",[87,824,825,833,841,848,857,864,871],{},[90,826,827,832],{},[37,828,829],{},[58,830,831],{},"variants.variant.skew",": Defines a new variant called \"skew\"",[90,834,835,840],{},[37,836,837],{},[58,838,839],{},"base",": An array of Tailwind classes applied by default",[90,842,843,847],{},[37,844,845],{},[58,846,188],{},": Our custom CSS class with the animation",[90,849,850,856],{},[37,851,852,855],{},[58,853,854],{},"border"," classes",": Creates a visible border",[90,858,859,863],{},[37,860,861],{},[58,862,717],{},": Uses the default background color",[90,865,866,870],{},[37,867,868],{},[58,869,739],{},": Border turns primary color on hover",[90,872,873,878],{},[37,874,875],{},[58,876,877],{},"hover:text-white",": Text turns white on hover (matching the primary background)",[50,880,882],{"id":881},"step-3-add-compound-variants-for-colors","Step 3: Add Compound Variants for Colors",[31,884,885],{},"To support different colors with our skew variant, we use compound variants:",[556,887,888],{},[145,889,891],{"className":560,"code":890,"filename":123,"language":562,"meta":151,"style":151},"export default defineAppConfig({\n  ui: {\n    button: {\n      \u002F\u002F ... variants from above\n      compoundVariants: [\n        {\n          variant: \"skew\",\n          color: \"primary\",\n          class: \"btn-skew\",\n        },\n        {\n          variant: \"skew\",\n          color: \"success\",\n          class: \"btn-skew btn-skew-success hover:border-success\",\n        },\n        {\n          variant: \"skew\",\n          color: \"info\",\n          class: \"btn-skew btn-skew-info hover:border-info\",\n        },\n        {\n          variant: \"skew\",\n          color: \"warning\",\n          class: \"btn-skew btn-skew-warning hover:border-warning\",\n        },\n        {\n          variant: \"skew\",\n          color: \"neutral\",\n          class: \"btn-skew btn-skew-neutral hover:border-neutral\",\n        },\n      ],\n    },\n  },\n});\n",[58,892,893,905,913,921,926,935,940,955,971,986,990,994,1008,1023,1038,1042,1046,1060,1075,1090,1094,1098,1112,1127,1142,1146,1150,1165,1180,1196,1201,1209,1214,1219],{"__ignoreMap":151},[155,894,895,897,899,901,903],{"class":157,"line":158},[155,896,569],{"class":161},[155,898,573],{"class":572},[155,900,577],{"class":576},[155,902,363],{"class":165},[155,904,170],{"class":169},[155,906,907,909,911],{"class":157,"line":173},[155,908,587],{"class":586},[155,910,143],{"class":590},[155,912,191],{"class":169},[155,914,915,917,919],{"class":157,"line":180},[155,916,647],{"class":586},[155,918,143],{"class":590},[155,920,191],{"class":169},[155,922,923],{"class":157,"line":194},[155,924,925],{"class":176},"      \u002F\u002F ... variants from above\n",[155,927,928,931,933],{"class":157,"line":210},[155,929,930],{"class":586},"      compoundVariants",[155,932,143],{"class":590},[155,934,688],{"class":165},[155,936,937],{"class":157,"line":223},[155,938,939],{"class":169},"        {\n",[155,941,942,945,947,949,951,953],{"class":157,"line":237},[155,943,944],{"class":586},"          variant",[155,946,143],{"class":590},[155,948,611],{"class":274},[155,950,77],{"class":614},[155,952,618],{"class":274},[155,954,621],{"class":169},[155,956,957,960,962,964,967,969],{"class":157,"line":243},[155,958,959],{"class":586},"          color",[155,961,143],{"class":590},[155,963,611],{"class":274},[155,965,966],{"class":614},"primary",[155,968,618],{"class":274},[155,970,621],{"class":169},[155,972,973,976,978,980,982,984],{"class":157,"line":249},[155,974,975],{"class":586},"          class",[155,977,143],{"class":590},[155,979,611],{"class":274},[155,981,188],{"class":614},[155,983,618],{"class":274},[155,985,621],{"class":169},[155,987,988],{"class":157,"line":266},[155,989,793],{"class":169},[155,991,992],{"class":157,"line":280},[155,993,939],{"class":169},[155,995,996,998,1000,1002,1004,1006],{"class":157,"line":292},[155,997,944],{"class":586},[155,999,143],{"class":590},[155,1001,611],{"class":274},[155,1003,77],{"class":614},[155,1005,618],{"class":274},[155,1007,621],{"class":169},[155,1009,1010,1012,1014,1016,1019,1021],{"class":157,"line":304},[155,1011,959],{"class":586},[155,1013,143],{"class":590},[155,1015,611],{"class":274},[155,1017,1018],{"class":614},"success",[155,1020,618],{"class":274},[155,1022,621],{"class":169},[155,1024,1025,1027,1029,1031,1034,1036],{"class":157,"line":321},[155,1026,975],{"class":586},[155,1028,143],{"class":590},[155,1030,611],{"class":274},[155,1032,1033],{"class":614},"btn-skew btn-skew-success hover:border-success",[155,1035,618],{"class":274},[155,1037,621],{"class":169},[155,1039,1040],{"class":157,"line":337},[155,1041,793],{"class":169},[155,1043,1044],{"class":157,"line":351},[155,1045,939],{"class":169},[155,1047,1048,1050,1052,1054,1056,1058],{"class":157,"line":373},[155,1049,944],{"class":586},[155,1051,143],{"class":590},[155,1053,611],{"class":274},[155,1055,77],{"class":614},[155,1057,618],{"class":274},[155,1059,621],{"class":169},[155,1061,1062,1064,1066,1068,1071,1073],{"class":157,"line":394},[155,1063,959],{"class":586},[155,1065,143],{"class":590},[155,1067,611],{"class":274},[155,1069,1070],{"class":614},"info",[155,1072,618],{"class":274},[155,1074,621],{"class":169},[155,1076,1077,1079,1081,1083,1086,1088],{"class":157,"line":406},[155,1078,975],{"class":586},[155,1080,143],{"class":590},[155,1082,611],{"class":274},[155,1084,1085],{"class":614},"btn-skew btn-skew-info hover:border-info",[155,1087,618],{"class":274},[155,1089,621],{"class":169},[155,1091,1092],{"class":157,"line":428},[155,1093,793],{"class":169},[155,1095,1096],{"class":157,"line":433},[155,1097,939],{"class":169},[155,1099,1100,1102,1104,1106,1108,1110],{"class":157,"line":438},[155,1101,944],{"class":586},[155,1103,143],{"class":590},[155,1105,611],{"class":274},[155,1107,77],{"class":614},[155,1109,618],{"class":274},[155,1111,621],{"class":169},[155,1113,1114,1116,1118,1120,1123,1125],{"class":157,"line":456},[155,1115,959],{"class":586},[155,1117,143],{"class":590},[155,1119,611],{"class":274},[155,1121,1122],{"class":614},"warning",[155,1124,618],{"class":274},[155,1126,621],{"class":169},[155,1128,1129,1131,1133,1135,1138,1140],{"class":157,"line":470},[155,1130,975],{"class":586},[155,1132,143],{"class":590},[155,1134,611],{"class":274},[155,1136,1137],{"class":614},"btn-skew btn-skew-warning hover:border-warning",[155,1139,618],{"class":274},[155,1141,621],{"class":169},[155,1143,1144],{"class":157,"line":475},[155,1145,793],{"class":169},[155,1147,1148],{"class":157,"line":810},[155,1149,939],{"class":169},[155,1151,1153,1155,1157,1159,1161,1163],{"class":157,"line":1152},27,[155,1154,944],{"class":586},[155,1156,143],{"class":590},[155,1158,611],{"class":274},[155,1160,77],{"class":614},[155,1162,618],{"class":274},[155,1164,621],{"class":169},[155,1166,1168,1170,1172,1174,1176,1178],{"class":157,"line":1167},28,[155,1169,959],{"class":586},[155,1171,143],{"class":590},[155,1173,611],{"class":274},[155,1175,17],{"class":614},[155,1177,618],{"class":274},[155,1179,621],{"class":169},[155,1181,1183,1185,1187,1189,1192,1194],{"class":157,"line":1182},29,[155,1184,975],{"class":586},[155,1186,143],{"class":590},[155,1188,611],{"class":274},[155,1190,1191],{"class":614},"btn-skew btn-skew-neutral hover:border-neutral",[155,1193,618],{"class":274},[155,1195,621],{"class":169},[155,1197,1199],{"class":157,"line":1198},30,[155,1200,793],{"class":169},[155,1202,1204,1207],{"class":157,"line":1203},31,[155,1205,1206],{"class":165},"      ]",[155,1208,621],{"class":169},[155,1210,1212],{"class":157,"line":1211},32,[155,1213,642],{"class":169},[155,1215,1217],{"class":157,"line":1216},33,[155,1218,807],{"class":169},[155,1220,1222,1224,1226],{"class":157,"line":1221},34,[155,1223,813],{"class":169},[155,1225,816],{"class":165},[155,1227,207],{"class":169},[31,1229,1230],{},"Now add the corresponding CSS for each color:",[145,1232,1234],{"className":147,"code":1233,"filename":149,"language":150,"meta":151,"style":151},"\u002F* Alternative skew variants with different colors *\u002F\n.btn-skew-success::before {\n  background-color: var(--ui-success);\n}\n\n.btn-skew-info::before {\n  background-color: var(--ui-info);\n}\n\n.btn-skew-warning::before {\n  background-color: var(--ui-warning);\n}\n\n.btn-skew-neutral::before {\n  background-color: var(--ui-bg-inverted);\n}\n",[58,1235,1236,1241,1255,1271,1275,1279,1292,1307,1311,1315,1328,1343,1347,1351,1364,1379],{"__ignoreMap":151},[155,1237,1238],{"class":157,"line":158},[155,1239,1240],{"class":176},"\u002F* Alternative skew variants with different colors *\u002F\n",[155,1242,1243,1246,1249,1251,1253],{"class":157,"line":173},[155,1244,1245],{"class":183},".",[155,1247,1248],{"class":187},"btn-skew-success",[155,1250,257],{"class":256},[155,1252,261],{"class":260},[155,1254,191],{"class":169},[155,1256,1257,1260,1262,1264,1266,1269],{"class":157,"line":180},[155,1258,1259],{"class":197},"  background-color",[155,1261,143],{"class":169},[155,1263,360],{"class":359},[155,1265,363],{"class":169},[155,1267,1268],{"class":366},"--ui-success",[155,1270,370],{"class":169},[155,1272,1273],{"class":157,"line":194},[155,1274,478],{"class":169},[155,1276,1277],{"class":157,"line":210},[155,1278,246],{"emptyLinePlaceholder":18},[155,1280,1281,1283,1286,1288,1290],{"class":157,"line":223},[155,1282,1245],{"class":183},[155,1284,1285],{"class":187},"btn-skew-info",[155,1287,257],{"class":256},[155,1289,261],{"class":260},[155,1291,191],{"class":169},[155,1293,1294,1296,1298,1300,1302,1305],{"class":157,"line":237},[155,1295,1259],{"class":197},[155,1297,143],{"class":169},[155,1299,360],{"class":359},[155,1301,363],{"class":169},[155,1303,1304],{"class":366},"--ui-info",[155,1306,370],{"class":169},[155,1308,1309],{"class":157,"line":243},[155,1310,478],{"class":169},[155,1312,1313],{"class":157,"line":249},[155,1314,246],{"emptyLinePlaceholder":18},[155,1316,1317,1319,1322,1324,1326],{"class":157,"line":266},[155,1318,1245],{"class":183},[155,1320,1321],{"class":187},"btn-skew-warning",[155,1323,257],{"class":256},[155,1325,261],{"class":260},[155,1327,191],{"class":169},[155,1329,1330,1332,1334,1336,1338,1341],{"class":157,"line":280},[155,1331,1259],{"class":197},[155,1333,143],{"class":169},[155,1335,360],{"class":359},[155,1337,363],{"class":169},[155,1339,1340],{"class":366},"--ui-warning",[155,1342,370],{"class":169},[155,1344,1345],{"class":157,"line":292},[155,1346,478],{"class":169},[155,1348,1349],{"class":157,"line":304},[155,1350,246],{"emptyLinePlaceholder":18},[155,1352,1353,1355,1358,1360,1362],{"class":157,"line":321},[155,1354,1245],{"class":183},[155,1356,1357],{"class":187},"btn-skew-neutral",[155,1359,257],{"class":256},[155,1361,261],{"class":260},[155,1363,191],{"class":169},[155,1365,1366,1368,1370,1372,1374,1377],{"class":157,"line":337},[155,1367,1259],{"class":197},[155,1369,143],{"class":169},[155,1371,360],{"class":359},[155,1373,363],{"class":169},[155,1375,1376],{"class":366},"--ui-bg-inverted",[155,1378,370],{"class":169},[155,1380,1381],{"class":157,"line":351},[155,1382,478],{"class":169},[50,1384,1386],{"id":1385},"usage","Usage",[31,1388,1389],{},"Now you can use your custom variant just like any built-in variant:",[145,1391,1396],{"className":1392,"code":1393,"filename":1394,"language":1395,"meta":151,"style":151},"language-vue shiki shiki-themes material-theme-lighter one-light one-dark-pro","\u003Ctemplate>\n  \u003Cdiv class=\"flex gap-4\">\n    \u003C!-- Primary skew button -->\n    \u003CUButton variant=\"skew\" color=\"primary\">\n      Get Started\n    \u003C\u002FUButton>\n\n    \u003C!-- Success skew button -->\n    \u003CUButton variant=\"skew\" color=\"success\">\n      Save Changes\n    \u003C\u002FUButton>\n\n    \u003C!-- With an icon -->\n    \u003CUButton variant=\"skew\" color=\"primary\" icon=\"lucide:download\">\n      Download\n    \u003C\u002FUButton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","example.vue","vue",[58,1397,1398,1409,1433,1438,1470,1475,1484,1488,1493,1521,1526,1534,1538,1543,1583,1588,1596,1605],{"__ignoreMap":151},[155,1399,1400,1403,1406],{"class":157,"line":158},[155,1401,1402],{"class":169},"\u003C",[155,1404,1405],{"class":586},"template",[155,1407,1408],{"class":169},">\n",[155,1410,1411,1414,1417,1421,1424,1426,1429,1431],{"class":157,"line":173},[155,1412,1413],{"class":169},"  \u003C",[155,1415,1416],{"class":586},"div",[155,1418,1420],{"class":1419},"sGh1W"," class",[155,1422,1423],{"class":169},"=",[155,1425,618],{"class":274},[155,1427,1428],{"class":614},"flex gap-4",[155,1430,618],{"class":274},[155,1432,1408],{"class":169},[155,1434,1435],{"class":157,"line":180},[155,1436,1437],{"class":176},"    \u003C!-- Primary skew button -->\n",[155,1439,1440,1443,1446,1449,1451,1453,1455,1457,1460,1462,1464,1466,1468],{"class":157,"line":194},[155,1441,1442],{"class":169},"    \u003C",[155,1444,1445],{"class":586},"UButton",[155,1447,1448],{"class":1419}," variant",[155,1450,1423],{"class":169},[155,1452,618],{"class":274},[155,1454,77],{"class":614},[155,1456,618],{"class":274},[155,1458,1459],{"class":1419}," color",[155,1461,1423],{"class":169},[155,1463,618],{"class":274},[155,1465,966],{"class":614},[155,1467,618],{"class":274},[155,1469,1408],{"class":169},[155,1471,1472],{"class":157,"line":210},[155,1473,1474],{"class":165},"      Get Started\n",[155,1476,1477,1480,1482],{"class":157,"line":223},[155,1478,1479],{"class":169},"    \u003C\u002F",[155,1481,1445],{"class":586},[155,1483,1408],{"class":169},[155,1485,1486],{"class":157,"line":237},[155,1487,246],{"emptyLinePlaceholder":18},[155,1489,1490],{"class":157,"line":243},[155,1491,1492],{"class":176},"    \u003C!-- Success skew button -->\n",[155,1494,1495,1497,1499,1501,1503,1505,1507,1509,1511,1513,1515,1517,1519],{"class":157,"line":249},[155,1496,1442],{"class":169},[155,1498,1445],{"class":586},[155,1500,1448],{"class":1419},[155,1502,1423],{"class":169},[155,1504,618],{"class":274},[155,1506,77],{"class":614},[155,1508,618],{"class":274},[155,1510,1459],{"class":1419},[155,1512,1423],{"class":169},[155,1514,618],{"class":274},[155,1516,1018],{"class":614},[155,1518,618],{"class":274},[155,1520,1408],{"class":169},[155,1522,1523],{"class":157,"line":266},[155,1524,1525],{"class":165},"      Save Changes\n",[155,1527,1528,1530,1532],{"class":157,"line":280},[155,1529,1479],{"class":169},[155,1531,1445],{"class":586},[155,1533,1408],{"class":169},[155,1535,1536],{"class":157,"line":292},[155,1537,246],{"emptyLinePlaceholder":18},[155,1539,1540],{"class":157,"line":304},[155,1541,1542],{"class":176},"    \u003C!-- With an icon -->\n",[155,1544,1545,1547,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567,1569,1572,1574,1576,1579,1581],{"class":157,"line":321},[155,1546,1442],{"class":169},[155,1548,1445],{"class":586},[155,1550,1448],{"class":1419},[155,1552,1423],{"class":169},[155,1554,618],{"class":274},[155,1556,77],{"class":614},[155,1558,618],{"class":274},[155,1560,1459],{"class":1419},[155,1562,1423],{"class":169},[155,1564,618],{"class":274},[155,1566,966],{"class":614},[155,1568,618],{"class":274},[155,1570,1571],{"class":1419}," icon",[155,1573,1423],{"class":169},[155,1575,618],{"class":274},[155,1577,1578],{"class":614},"lucide:download",[155,1580,618],{"class":274},[155,1582,1408],{"class":169},[155,1584,1585],{"class":157,"line":337},[155,1586,1587],{"class":165},"      Download\n",[155,1589,1590,1592,1594],{"class":157,"line":351},[155,1591,1479],{"class":169},[155,1593,1445],{"class":586},[155,1595,1408],{"class":169},[155,1597,1598,1601,1603],{"class":157,"line":373},[155,1599,1600],{"class":169},"  \u003C\u002F",[155,1602,1416],{"class":586},[155,1604,1408],{"class":169},[155,1606,1607,1610,1612],{"class":157,"line":394},[155,1608,1609],{"class":169},"\u003C\u002F",[155,1611,1405],{"class":586},[155,1613,1408],{"class":169},[50,1615,1617],{"id":1616},"bonus-circular-button-variant","Bonus: Circular Button Variant",[31,1619,1620],{},"For circular buttons like a scroll-to-top button, the skew effect doesn't work well because of the rounded shape. Here's a variant that expands from the center instead.",[31,1622,1623],{},"First, add the CSS:",[556,1625,1626],{},[145,1627,1629],{"className":147,"code":1628,"filename":149,"language":150,"meta":151,"style":151},"\u002F* Circular Button Animation - for rounded-full buttons *\u002F\n.btn-skew-circle {\n  position: relative;\n  overflow: hidden;\n  z-index: 0;\n}\n\n.btn-skew-circle::before {\n  content: \"\";\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  width: 0%;\n  height: 0%;\n  background-color: var(--ui-primary);\n  border-radius: 50%;\n  transform: translate(-50%, -50%);\n  z-index: -1;\n  transition: width 300ms ease-out, height 300ms ease-out;\n}\n\n.btn-skew-circle:hover::before {\n  width: 150%;\n  height: 150%;\n}\n",[58,1630,1631,1636,1645,1656,1667,1678,1682,1686,1698,1709,1719,1733,1746,1759,1772,1786,1799,1826,1836,1865,1869,1873,1889,1901,1913],{"__ignoreMap":151},[155,1632,1633],{"class":157,"line":158},[155,1634,1635],{"class":176},"\u002F* Circular Button Animation - for rounded-full buttons *\u002F\n",[155,1637,1638,1640,1643],{"class":157,"line":173},[155,1639,1245],{"class":183},[155,1641,1642],{"class":187},"btn-skew-circle",[155,1644,191],{"class":169},[155,1646,1647,1650,1652,1654],{"class":157,"line":180},[155,1648,1649],{"class":197},"  position",[155,1651,143],{"class":169},[155,1653,204],{"class":203},[155,1655,207],{"class":169},[155,1657,1658,1661,1663,1665],{"class":157,"line":194},[155,1659,1660],{"class":197},"  overflow",[155,1662,143],{"class":169},[155,1664,218],{"class":203},[155,1666,207],{"class":169},[155,1668,1669,1672,1674,1676],{"class":157,"line":210},[155,1670,1671],{"class":197},"  z-index",[155,1673,143],{"class":169},[155,1675,232],{"class":231},[155,1677,207],{"class":169},[155,1679,1680],{"class":157,"line":223},[155,1681,478],{"class":169},[155,1683,1684],{"class":157,"line":237},[155,1685,246],{"emptyLinePlaceholder":18},[155,1687,1688,1690,1692,1694,1696],{"class":157,"line":243},[155,1689,1245],{"class":183},[155,1691,1642],{"class":187},[155,1693,257],{"class":256},[155,1695,261],{"class":260},[155,1697,191],{"class":169},[155,1699,1700,1703,1705,1707],{"class":157,"line":249},[155,1701,1702],{"class":197},"  content",[155,1704,143],{"class":169},[155,1706,275],{"class":274},[155,1708,207],{"class":169},[155,1710,1711,1713,1715,1717],{"class":157,"line":266},[155,1712,1649],{"class":197},[155,1714,143],{"class":169},[155,1716,287],{"class":203},[155,1718,207],{"class":169},[155,1720,1721,1724,1726,1729,1731],{"class":157,"line":280},[155,1722,1723],{"class":197},"  top",[155,1725,143],{"class":169},[155,1727,1728],{"class":231}," 50",[155,1730,332],{"class":315},[155,1732,207],{"class":169},[155,1734,1735,1738,1740,1742,1744],{"class":157,"line":292},[155,1736,1737],{"class":197},"  left",[155,1739,143],{"class":169},[155,1741,1728],{"class":231},[155,1743,332],{"class":315},[155,1745,207],{"class":169},[155,1747,1748,1751,1753,1755,1757],{"class":157,"line":304},[155,1749,1750],{"class":197},"  width",[155,1752,143],{"class":169},[155,1754,232],{"class":231},[155,1756,332],{"class":315},[155,1758,207],{"class":169},[155,1760,1761,1764,1766,1768,1770],{"class":157,"line":321},[155,1762,1763],{"class":197},"  height",[155,1765,143],{"class":169},[155,1767,232],{"class":231},[155,1769,332],{"class":315},[155,1771,207],{"class":169},[155,1773,1774,1776,1778,1780,1782,1784],{"class":157,"line":337},[155,1775,1259],{"class":197},[155,1777,143],{"class":169},[155,1779,360],{"class":359},[155,1781,363],{"class":169},[155,1783,367],{"class":366},[155,1785,370],{"class":169},[155,1787,1788,1791,1793,1795,1797],{"class":157,"line":351},[155,1789,1790],{"class":197},"  border-radius",[155,1792,143],{"class":169},[155,1794,1728],{"class":231},[155,1796,332],{"class":315},[155,1798,207],{"class":169},[155,1800,1801,1804,1806,1809,1811,1814,1816,1819,1822,1824],{"class":157,"line":373},[155,1802,1803],{"class":197},"  transform",[155,1805,143],{"class":169},[155,1807,1808],{"class":359}," translate",[155,1810,363],{"class":169},[155,1812,1813],{"class":231},"-50",[155,1815,332],{"class":315},[155,1817,1818],{"class":169},",",[155,1820,1821],{"class":231}," -50",[155,1823,332],{"class":315},[155,1825,370],{"class":169},[155,1827,1828,1830,1832,1834],{"class":157,"line":394},[155,1829,1671],{"class":197},[155,1831,143],{"class":169},[155,1833,401],{"class":231},[155,1835,207],{"class":169},[155,1837,1838,1841,1843,1845,1848,1850,1852,1854,1857,1859,1861,1863],{"class":157,"line":406},[155,1839,1840],{"class":197},"  transition",[155,1842,143],{"class":169},[155,1844,414],{"class":165},[155,1846,1847],{"class":231},"300",[155,1849,420],{"class":315},[155,1851,423],{"class":203},[155,1853,1818],{"class":169},[155,1855,1856],{"class":165}," height ",[155,1858,1847],{"class":231},[155,1860,420],{"class":315},[155,1862,423],{"class":203},[155,1864,207],{"class":169},[155,1866,1867],{"class":157,"line":428},[155,1868,478],{"class":169},[155,1870,1871],{"class":157,"line":433},[155,1872,246],{"emptyLinePlaceholder":18},[155,1874,1875,1877,1879,1881,1883,1885,1887],{"class":157,"line":438},[155,1876,1245],{"class":183},[155,1878,1642],{"class":187},[155,1880,143],{"class":256},[155,1882,447],{"class":260},[155,1884,257],{"class":256},[155,1886,261],{"class":260},[155,1888,191],{"class":169},[155,1890,1891,1893,1895,1897,1899],{"class":157,"line":456},[155,1892,1750],{"class":197},[155,1894,143],{"class":169},[155,1896,463],{"class":231},[155,1898,332],{"class":315},[155,1900,207],{"class":169},[155,1902,1903,1905,1907,1909,1911],{"class":157,"line":470},[155,1904,1763],{"class":197},[155,1906,143],{"class":169},[155,1908,463],{"class":231},[155,1910,332],{"class":315},[155,1912,207],{"class":169},[155,1914,1915],{"class":157,"line":475},[155,1916,478],{"class":169},[31,1918,1919,1920,143],{},"Then register it as a variant in ",[58,1921,123],{},[145,1923,1925],{"className":560,"code":1924,"filename":123,"language":562,"meta":151,"style":151},"button: {\n  variants: {\n    variant: {\n      skew: { \u002F* ... *\u002F },\n      \"skew-circle\": {\n        base: [\n          \"btn-skew-circle\",\n          \"rounded-full\",\n          \"border border-neutral-300 dark:border-neutral-700\",\n          \"bg-default\",\n          \"transition-all duration-300\",\n          \"hover:border-primary\",\n          \"hover:text-white dark:hover:text-default\",\n          \"disabled:cursor-not-allowed\",\n          \"disabled:opacity-50\",\n        ],\n      },\n    },\n  },\n  compoundVariants: [\n    \u002F\u002F ... other variants\n    {\n      variant: \"skew-circle\",\n      color: \"primary\",\n      class: \"btn-skew-circle\",\n    },\n  ],\n}\n",[58,1926,1927,1937,1946,1955,1971,1987,1996,2007,2018,2028,2038,2048,2058,2068,2078,2088,2095,2099,2103,2107,2116,2121,2126,2141,2156,2171,2175,2182],{"__ignoreMap":151},[155,1928,1929,1933,1935],{"class":157,"line":158},[155,1930,1932],{"class":1931},"sPgms","button",[155,1934,143],{"class":169},[155,1936,191],{"class":169},[155,1938,1939,1942,1944],{"class":157,"line":173},[155,1940,1941],{"class":1931},"  variants",[155,1943,143],{"class":169},[155,1945,191],{"class":169},[155,1947,1948,1951,1953],{"class":157,"line":180},[155,1949,1950],{"class":1931},"    variant",[155,1952,143],{"class":169},[155,1954,191],{"class":169},[155,1956,1957,1960,1962,1965,1968],{"class":157,"line":194},[155,1958,1959],{"class":1931},"      skew",[155,1961,143],{"class":169},[155,1963,1964],{"class":169}," {",[155,1966,1967],{"class":176}," \u002F* ... *\u002F",[155,1969,1970],{"class":169}," },\n",[155,1972,1973,1976,1979,1981,1985],{"class":157,"line":210},[155,1974,1975],{"class":274},"      \"",[155,1977,1978],{"class":614},"skew-circle",[155,1980,618],{"class":274},[155,1982,1984],{"class":1983},"sA0eD",": ",[155,1986,170],{"class":169},[155,1988,1989,1992,1994],{"class":157,"line":223},[155,1990,1991],{"class":586},"        base",[155,1993,143],{"class":590},[155,1995,688],{"class":1983},[155,1997,1998,2001,2003,2005],{"class":157,"line":237},[155,1999,2000],{"class":274},"          \"",[155,2002,1642],{"class":614},[155,2004,618],{"class":274},[155,2006,621],{"class":169},[155,2008,2009,2011,2014,2016],{"class":157,"line":243},[155,2010,2000],{"class":274},[155,2012,2013],{"class":614},"rounded-full",[155,2015,618],{"class":274},[155,2017,621],{"class":169},[155,2019,2020,2022,2024,2026],{"class":157,"line":249},[155,2021,2000],{"class":274},[155,2023,706],{"class":614},[155,2025,618],{"class":274},[155,2027,621],{"class":169},[155,2029,2030,2032,2034,2036],{"class":157,"line":266},[155,2031,2000],{"class":274},[155,2033,717],{"class":614},[155,2035,618],{"class":274},[155,2037,621],{"class":169},[155,2039,2040,2042,2044,2046],{"class":157,"line":280},[155,2041,2000],{"class":274},[155,2043,728],{"class":614},[155,2045,618],{"class":274},[155,2047,621],{"class":169},[155,2049,2050,2052,2054,2056],{"class":157,"line":292},[155,2051,2000],{"class":274},[155,2053,739],{"class":614},[155,2055,618],{"class":274},[155,2057,621],{"class":169},[155,2059,2060,2062,2064,2066],{"class":157,"line":304},[155,2061,2000],{"class":274},[155,2063,750],{"class":614},[155,2065,618],{"class":274},[155,2067,621],{"class":169},[155,2069,2070,2072,2074,2076],{"class":157,"line":321},[155,2071,2000],{"class":274},[155,2073,761],{"class":614},[155,2075,618],{"class":274},[155,2077,621],{"class":169},[155,2079,2080,2082,2084,2086],{"class":157,"line":337},[155,2081,2000],{"class":274},[155,2083,772],{"class":614},[155,2085,618],{"class":274},[155,2087,621],{"class":169},[155,2089,2090,2093],{"class":157,"line":351},[155,2091,2092],{"class":1983},"        ]",[155,2094,621],{"class":169},[155,2096,2097],{"class":157,"line":373},[155,2098,798],{"class":169},[155,2100,2101],{"class":157,"line":394},[155,2102,642],{"class":169},[155,2104,2105],{"class":157,"line":406},[155,2106,807],{"class":169},[155,2108,2109,2112,2114],{"class":157,"line":428},[155,2110,2111],{"class":1931},"  compoundVariants",[155,2113,143],{"class":169},[155,2115,688],{"class":1983},[155,2117,2118],{"class":157,"line":433},[155,2119,2120],{"class":176},"    \u002F\u002F ... other variants\n",[155,2122,2123],{"class":157,"line":438},[155,2124,2125],{"class":169},"    {\n",[155,2127,2128,2131,2133,2135,2137,2139],{"class":157,"line":456},[155,2129,2130],{"class":586},"      variant",[155,2132,143],{"class":590},[155,2134,611],{"class":274},[155,2136,1978],{"class":614},[155,2138,618],{"class":274},[155,2140,621],{"class":169},[155,2142,2143,2146,2148,2150,2152,2154],{"class":157,"line":470},[155,2144,2145],{"class":586},"      color",[155,2147,143],{"class":590},[155,2149,611],{"class":274},[155,2151,966],{"class":614},[155,2153,618],{"class":274},[155,2155,621],{"class":169},[155,2157,2158,2161,2163,2165,2167,2169],{"class":157,"line":475},[155,2159,2160],{"class":586},"      class",[155,2162,143],{"class":590},[155,2164,611],{"class":274},[155,2166,1642],{"class":614},[155,2168,618],{"class":274},[155,2170,621],{"class":169},[155,2172,2173],{"class":157,"line":810},[155,2174,642],{"class":169},[155,2176,2177,2180],{"class":157,"line":1152},[155,2178,2179],{"class":1983},"  ]",[155,2181,621],{"class":169},[155,2183,2184],{"class":157,"line":1167},[155,2185,478],{"class":169},[31,2187,2188],{},"Now you can use it cleanly without adding extra classes:",[145,2190,2193],{"className":1392,"code":2191,"filename":2192,"language":1395,"meta":151,"style":151},"\u003CUButton\n  icon=\"lucide:arrow-up\"\n  variant=\"skew-circle\"\n  color=\"primary\"\n  aria-label=\"Scroll to top\"\n\u002F>\n","ScrollToTop.vue",[58,2194,2195,2202,2217,2230,2243,2257],{"__ignoreMap":151},[155,2196,2197,2199],{"class":157,"line":158},[155,2198,1402],{"class":169},[155,2200,2201],{"class":586},"UButton\n",[155,2203,2204,2207,2209,2211,2214],{"class":157,"line":173},[155,2205,2206],{"class":1419},"  icon",[155,2208,1423],{"class":169},[155,2210,618],{"class":274},[155,2212,2213],{"class":614},"lucide:arrow-up",[155,2215,2216],{"class":274},"\"\n",[155,2218,2219,2222,2224,2226,2228],{"class":157,"line":180},[155,2220,2221],{"class":1419},"  variant",[155,2223,1423],{"class":169},[155,2225,618],{"class":274},[155,2227,1978],{"class":614},[155,2229,2216],{"class":274},[155,2231,2232,2235,2237,2239,2241],{"class":157,"line":194},[155,2233,2234],{"class":1419},"  color",[155,2236,1423],{"class":169},[155,2238,618],{"class":274},[155,2240,966],{"class":614},[155,2242,2216],{"class":274},[155,2244,2245,2248,2250,2252,2255],{"class":157,"line":210},[155,2246,2247],{"class":1419},"  aria-label",[155,2249,1423],{"class":169},[155,2251,618],{"class":274},[155,2253,2254],{"class":614},"Scroll to top",[155,2256,2216],{"class":274},[155,2258,2259],{"class":157,"line":223},[155,2260,2261],{"class":165},"\u002F>\n",[31,2263,2264,2265,2267],{},"The key difference is that ",[58,2266,1978],{}," uses:",[87,2269,2270,2278,2286],{},[90,2271,2272,2277],{},[37,2273,2274],{},[58,2275,2276],{},"border-radius: 50%"," on the pseudo-element for a circular fill",[90,2279,2280,2285],{},[37,2281,2282],{},[58,2283,2284],{},"transform: translate(-50%, -50%)"," to center the animation",[90,2287,2288,2291],{},[37,2289,2290],{},"Both width and height"," animate together for uniform expansion",[50,2293,2295],{"id":2294},"key-takeaways","Key Takeaways",[107,2297,2298,2307,2313,2319,2328],{},[90,2299,2300,2303,2304,2306],{},[37,2301,2302],{},"CSS Variables",": Use Nuxt UI's CSS variables like ",[58,2305,533],{}," for consistent theming",[90,2308,2309,2312],{},[37,2310,2311],{},"Compound Variants",": Allow you to combine variant + color for specific styling",[90,2314,2315,2318],{},[37,2316,2317],{},"Pseudo-elements",": Perfect for creating animated backgrounds without extra DOM elements",[90,2320,2321,2327],{},[37,2322,2323,2326],{},[58,2324,2325],{},"z-index"," layering",": Keep animations behind content using negative z-index",[90,2329,2330,2333,2334,2337],{},[37,2331,2332],{},"Transition timing",": The ",[58,2335,2336],{},"500ms ease-out"," creates a smooth, premium feel",[50,2339,2341],{"id":2340},"common-pitfalls","Common Pitfalls",[1122,2343,2344],{},[31,2345,2346,2349,2350,2352],{},[37,2347,2348],{},"Overflow Hidden",": Always set ",[58,2351,496],{}," on the button to clip the animated pseudo-element.",[2354,2355,2356],"caution",{},[31,2357,2358,2361,2362,2364,2365,2368],{},[37,2359,2360],{},"Z-Index Context",": Make sure your pseudo-element has ",[58,2363,543],{}," and the parent has ",[58,2366,2367],{},"z-index: 0"," to create a proper stacking context.",[50,2370,2372],{"id":2371},"conclusion","Conclusion",[31,2374,2375,2376,2378],{},"Nuxt UI's configuration system makes it incredibly easy to extend the component library with custom variants. By combining CSS pseudo-elements with the ",[58,2377,123],{}," configuration, you can create unique, branded button styles that work seamlessly with Nuxt UI's theming system.",[31,2380,2381],{},"The skew effect adds a touch of premium interactivity to any button, making your UI feel more polished and engaging. Try experimenting with different animations, timing functions, and transform properties to create your own signature effects!",[50,2383,2385],{"id":2384},"resources","Resources",[87,2387,2388,2397,2404],{},[90,2389,2390],{},[2391,2392,2396],"a",{"href":2393,"rel":2394},"https:\u002F\u002Fui.nuxt.com\u002Fdocs\u002Fgetting-started\u002Ftheme\u002Fcomponents",[2395],"nofollow","Nuxt UI Documentation",[90,2398,2399],{},[2391,2400,2403],{"href":2401,"rel":2402},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FCSS\u002F::before",[2395],"CSS Pseudo-elements",[90,2405,2406],{},[2391,2407,2410],{"href":2408,"rel":2409},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FCSS\u002Ftransform",[2395],"CSS Transforms",[50,2412,2414],{"id":2413},"thank-you","Thank You",[2416,2417,2418],"style",{},"html pre.shiki code .sQsOY, html code.shiki .sQsOY{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A626A4;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .svDm9, html code.shiki .svDm9{--shiki-light:#39ADB5;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .s6wAS, html code.shiki .s6wAS{--shiki-light:#E2931D;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sGRuu, html code.shiki .sGRuu{--shiki-light:#8796B0;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sngOx, html code.shiki .sngOx{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#D19A66}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sst0O, html code.shiki .sst0O{--shiki-light:#39ADB5;--shiki-default:#986801;--shiki-dark:#56B6C2}html pre.shiki code .sSxop, html code.shiki .sSxop{--shiki-light:#9C3EDA;--shiki-default:#986801;--shiki-dark:#56B6C2}html pre.shiki code .sVH1b, html code.shiki .sVH1b{--shiki-light:#39ADB5;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sLhkd, html code.shiki .sLhkd{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#E06C75}html pre.shiki code .sTDPv, html code.shiki .sTDPv{--shiki-light:#6182B8;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .s8dPH, html code.shiki .s8dPH{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E06C75}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 .sH50Z, html code.shiki .sH50Z{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#E45649;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .spnjr, html code.shiki .spnjr{--shiki-light:#6182B8;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .su13H, html code.shiki .su13H{--shiki-light:#E53935;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .saKOp, html code.shiki .saKOp{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#ABB2BF}html pre.shiki code .spZWa, html code.shiki .spZWa{--shiki-light:#91B859;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sGh1W, html code.shiki .sGh1W{--shiki-light:#9C3EDA;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sPgms, html code.shiki .sPgms{--shiki-light:#E2931D;--shiki-default:#383A42;--shiki-dark:#E06C75}html pre.shiki code .sA0eD, html code.shiki .sA0eD{--shiki-light:#E53935;--shiki-default:#383A42;--shiki-dark:#ABB2BF}",{"title":151,"searchDepth":173,"depth":173,"links":2420},[2421,2422,2423,2424,2427,2430,2431,2432,2433,2434,2435,2436,2437],{"id":52,"depth":173,"text":53},{"id":81,"depth":173,"text":82},{"id":101,"depth":173,"text":102},{"id":135,"depth":173,"text":136,"children":2425},[2426],{"id":482,"depth":180,"text":483},{"id":547,"depth":173,"text":548,"children":2428},[2429],{"id":821,"depth":180,"text":822},{"id":881,"depth":173,"text":882},{"id":1385,"depth":173,"text":1386},{"id":1616,"depth":173,"text":1617},{"id":2294,"depth":173,"text":2295},{"id":2340,"depth":173,"text":2341},{"id":2371,"depth":173,"text":2372},{"id":2384,"depth":173,"text":2385},{"id":2413,"depth":173,"text":2414},"2026-01-17","md",{"slug":2441,"difficulty":2442,"featured":18,"icon":2443,"ogImage":2444,"tags":2446,"topic":2443},"nuxt-ui-custom-button-variants","intermediate","nuxt",{"alt":2445},"Custom button variants in Nuxt UI",[2443,2447,150,2448],"nuxt-ui","guide","\u002Farticles\u002Fnuxt-ui-custom-button-variants",{"title":26,"description":33},"articles\u002Fnuxt-ui-custom-button-variants","7Nfqzz-tDpTzanfcGL90dM2FgDZbg3OtcgotntAfaHo",{"id":2454,"title":2455,"author":6,"body":2456,"date":4621,"description":2460,"draft":8,"extension":2439,"image":6,"lastmod":4621,"meta":4622,"minRead":6,"navigation":18,"path":4628,"seo":4629,"stem":4630,"__hash__":4631},"articles\u002Farticles\u002Fremote-back-button-js.md","How to Handle Browser Back Button Navigation Events in Vue 3",{"type":28,"value":2457,"toc":4597},[2458,2461,2463,2466,2477,2480,2491,2494,2498,2505,2522,2525,2529,3389,3391,3395,3398,3482,3485,3489,3492,3500,3553,3557,3560,3629,3632,3636,3639,3740,3744,3748,3958,3962,4284,4288,4293,4297,4300,4370,4374,4377,4470,4474,4477,4521,4525,4562,4564,4569,4572,4575,4589,4592,4594],[31,2459,2460],{},"As web applications become more sophisticated, managing browser navigation becomes increasingly complex. One common challenge is handling the browser's back button when dealing with modals, dialogs, or drawers. Today, we'll explore a powerful Vue 3 composable that solves this problem while maintaining a smooth user experience.",[50,2462,53],{"id":52},[31,2464,2465],{},"Have you ever encountered these scenarios?",[107,2467,2468,2471,2474],{},[90,2469,2470],{},"User opens a modal dialog",[90,2472,2473],{},"User clicks the browser's back button",[90,2475,2476],{},"Instead of closing the modal, the whole application navigates back",[31,2478,2479],{},"Or maybe:",[107,2481,2482,2485,2488],{},[90,2483,2484],{},"User opens a modal",[90,2486,2487],{},"Modal closes when back button is pressed (good!)",[90,2489,2490],{},"But the page unexpectedly scrolls to the top (bad!)",[31,2492,2493],{},"These are common issues that can frustrate users and make your application feel unprofessional. Let's solve them with a robust solution.",[50,2495,2497],{"id":2496},"introducing-usebackbutton-composable","Introducing useBackButton Composable",[31,2499,2500,2501,2504],{},"Our ",[58,2502,2503],{},"useBackButton"," composable is designed to:",[87,2506,2507,2510,2513,2516,2519],{},[90,2508,2509],{},"Intercept back button clicks",[90,2511,2512],{},"Close modals\u002Fdialogs instead of navigating",[90,2514,2515],{},"Preserve scroll position when appropriate",[90,2517,2518],{},"Handle edge cases like double-clicks",[90,2520,2521],{},"Maintain a clean browser history",[31,2523,2524],{},"Here's how we build it:",[480,2526,2528],{"id":2527},"the-core-implementation","The Core Implementation",[556,2530,2531],{},[145,2532,2537],{"className":2533,"code":2534,"filename":2535,"language":2536,"meta":151,"style":151},"language-js shiki shiki-themes material-theme-lighter one-light one-dark-pro","\u002F\u002F composables\u002FuseBackButton.js\nimport { watch, onMounted, onUnmounted } from \"vue\";\nimport { useGlobalStore } from \"@\u002Fstores\u002Fglobal\";\n\nexport function useBackButton(contentVisibleRef) {\n  const globalStore = useGlobalStore();\n\n  const handlePopState = () => {\n    if (contentVisibleRef.value) {\n      \u002F\u002F Add history.pushState first to prevent navigation\n      history.pushState(null, \"\", window.location.pathname);\n      history.pushState(null, \"\", window.location.pathname); \u002F\u002F Add twice to ensure it works with double back click\n\n      globalStore.isBackBtnPressed = true;\n      contentVisibleRef.value = false;\n    }\n  };\n\n  onMounted(() => {\n    \u002F\u002F Add initial history state\n    history.pushState(null, \"\", window.location.pathname);\n    window.addEventListener(\"popstate\", handlePopState);\n  });\n\n  onUnmounted(() => {\n    window.removeEventListener(\"popstate\", handlePopState);\n  });\n\n  watch(contentVisibleRef, (newValue) => {\n    if (!newValue) {\n      setTimeout(() => {\n        globalStore.isBackBtnPressed = false;\n      }, 100);\n    }\n  });\n\n  watch(\n    () => globalStore.isBackBtnPressed,\n    (newValue) => {\n      if (newValue) {\n        \u002F\u002F Ensure route change is prevented when state is true\n        history.pushState(null, \"\", window.location.pathname);\n      }\n    },\n  );\n}\n\n\u002F\u002F router guard\nrouter.beforeEach((to, from, next) => {\n  if (globals.isBackBtnPressed) {\n    globals.isBackBtnPressed = false; \u002F\u002F Reset immediately\n    next(false); \u002F\u002F Prevent navigation\n    return;\n  }\n  next();\n});\n\n\u002F\u002F global store\nexport const useGlobalStore = defineStore(\"global\", {\n  state: () => ({\n    isBackBtnPressed: false,\n  }),\n});\n","useBackButton.js","js",[58,2538,2539,2544,2578,2600,2604,2625,2645,2649,2667,2688,2693,2732,2768,2772,2790,2806,2811,2816,2820,2833,2838,2871,2899,2908,2912,2925,2950,2958,2962,2984,2999,3012,3027,3038,3042,3051,3056,3064,3080,3094,3108,3114,3148,3154,3159,3167,3172,3177,3183,3216,3235,3254,3272,3280,3285,3295,3304,3309,3315,3343,3359,3371,3380],{"__ignoreMap":151},[155,2540,2541],{"class":157,"line":158},[155,2542,2543],{"class":176},"\u002F\u002F composables\u002FuseBackButton.js\n",[155,2545,2546,2549,2551,2554,2556,2559,2561,2564,2567,2570,2572,2574,2576],{"class":157,"line":173},[155,2547,2548],{"class":161},"import",[155,2550,1964],{"class":169},[155,2552,2553],{"class":366}," watch",[155,2555,1818],{"class":169},[155,2557,2558],{"class":366}," onMounted",[155,2560,1818],{"class":169},[155,2562,2563],{"class":366}," onUnmounted",[155,2565,2566],{"class":169}," }",[155,2568,2569],{"class":161}," from",[155,2571,611],{"class":274},[155,2573,1395],{"class":614},[155,2575,618],{"class":274},[155,2577,207],{"class":169},[155,2579,2580,2582,2584,2587,2589,2591,2593,2596,2598],{"class":157,"line":180},[155,2581,2548],{"class":161},[155,2583,1964],{"class":169},[155,2585,2586],{"class":366}," useGlobalStore",[155,2588,2566],{"class":169},[155,2590,2569],{"class":161},[155,2592,611],{"class":274},[155,2594,2595],{"class":614},"@\u002Fstores\u002Fglobal",[155,2597,618],{"class":274},[155,2599,207],{"class":169},[155,2601,2602],{"class":157,"line":194},[155,2603,246],{"emptyLinePlaceholder":18},[155,2605,2606,2608,2612,2615,2617,2621,2623],{"class":157,"line":210},[155,2607,569],{"class":161},[155,2609,2611],{"class":2610},"sJvVP"," function",[155,2613,2614],{"class":576}," useBackButton",[155,2616,363],{"class":169},[155,2618,2620],{"class":2619},"s5f2p","contentVisibleRef",[155,2622,816],{"class":169},[155,2624,191],{"class":169},[155,2626,2627,2630,2634,2638,2640,2643],{"class":157,"line":223},[155,2628,2629],{"class":2610},"  const",[155,2631,2633],{"class":2632},"sMm83"," globalStore",[155,2635,2637],{"class":2636},"syPST"," =",[155,2639,2586],{"class":576},[155,2641,2642],{"class":1983},"()",[155,2644,207],{"class":169},[155,2646,2647],{"class":157,"line":237},[155,2648,246],{"emptyLinePlaceholder":18},[155,2650,2651,2653,2657,2659,2662,2665],{"class":157,"line":243},[155,2652,2629],{"class":2610},[155,2654,2656],{"class":2655},"svfkx"," handlePopState",[155,2658,2637],{"class":2636},[155,2660,2661],{"class":169}," ()",[155,2663,2664],{"class":2610}," =>",[155,2666,191],{"class":169},[155,2668,2669,2672,2675,2678,2680,2683,2686],{"class":157,"line":249},[155,2670,2671],{"class":161},"    if",[155,2673,2674],{"class":1983}," (",[155,2676,2620],{"class":2677},"scCn_",[155,2679,1245],{"class":169},[155,2681,2682],{"class":366},"value",[155,2684,2685],{"class":1983},") ",[155,2687,170],{"class":169},[155,2689,2690],{"class":157,"line":266},[155,2691,2692],{"class":176},"      \u002F\u002F Add history.pushState first to prevent navigation\n",[155,2694,2695,2698,2700,2703,2705,2708,2710,2712,2714,2717,2719,2723,2725,2728,2730],{"class":157,"line":280},[155,2696,2697],{"class":2677},"      history",[155,2699,1245],{"class":169},[155,2701,2702],{"class":576},"pushState",[155,2704,363],{"class":1983},[155,2706,2707],{"class":183},"null",[155,2709,1818],{"class":169},[155,2711,275],{"class":274},[155,2713,1818],{"class":169},[155,2715,2716],{"class":2677}," window",[155,2718,1245],{"class":169},[155,2720,2722],{"class":2721},"sDC5J","location",[155,2724,1245],{"class":169},[155,2726,2727],{"class":366},"pathname",[155,2729,816],{"class":1983},[155,2731,207],{"class":169},[155,2733,2734,2736,2738,2740,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762,2765],{"class":157,"line":292},[155,2735,2697],{"class":2677},[155,2737,1245],{"class":169},[155,2739,2702],{"class":576},[155,2741,363],{"class":1983},[155,2743,2707],{"class":183},[155,2745,1818],{"class":169},[155,2747,275],{"class":274},[155,2749,1818],{"class":169},[155,2751,2716],{"class":2677},[155,2753,1245],{"class":169},[155,2755,2722],{"class":2721},[155,2757,1245],{"class":169},[155,2759,2727],{"class":366},[155,2761,816],{"class":1983},[155,2763,2764],{"class":169},";",[155,2766,2767],{"class":176}," \u002F\u002F Add twice to ensure it works with double back click\n",[155,2769,2770],{"class":157,"line":304},[155,2771,246],{"emptyLinePlaceholder":18},[155,2773,2774,2777,2779,2782,2784,2788],{"class":157,"line":321},[155,2775,2776],{"class":2677},"      globalStore",[155,2778,1245],{"class":169},[155,2780,2781],{"class":366},"isBackBtnPressed",[155,2783,2637],{"class":2636},[155,2785,2787],{"class":2786},"sbyCm"," true",[155,2789,207],{"class":169},[155,2791,2792,2795,2797,2799,2801,2804],{"class":157,"line":337},[155,2793,2794],{"class":2677},"      contentVisibleRef",[155,2796,1245],{"class":169},[155,2798,2682],{"class":366},[155,2800,2637],{"class":2636},[155,2802,2803],{"class":2786}," false",[155,2805,207],{"class":169},[155,2807,2808],{"class":157,"line":351},[155,2809,2810],{"class":169},"    }\n",[155,2812,2813],{"class":157,"line":373},[155,2814,2815],{"class":169},"  };\n",[155,2817,2818],{"class":157,"line":394},[155,2819,246],{"emptyLinePlaceholder":18},[155,2821,2822,2825,2827,2829,2831],{"class":157,"line":406},[155,2823,2824],{"class":576},"  onMounted",[155,2826,363],{"class":1983},[155,2828,2642],{"class":169},[155,2830,2664],{"class":2610},[155,2832,191],{"class":169},[155,2834,2835],{"class":157,"line":428},[155,2836,2837],{"class":176},"    \u002F\u002F Add initial history state\n",[155,2839,2840,2843,2845,2847,2849,2851,2853,2855,2857,2859,2861,2863,2865,2867,2869],{"class":157,"line":433},[155,2841,2842],{"class":2677},"    history",[155,2844,1245],{"class":169},[155,2846,2702],{"class":576},[155,2848,363],{"class":1983},[155,2850,2707],{"class":183},[155,2852,1818],{"class":169},[155,2854,275],{"class":274},[155,2856,1818],{"class":169},[155,2858,2716],{"class":2677},[155,2860,1245],{"class":169},[155,2862,2722],{"class":2721},[155,2864,1245],{"class":169},[155,2866,2727],{"class":366},[155,2868,816],{"class":1983},[155,2870,207],{"class":169},[155,2872,2873,2876,2878,2881,2883,2885,2888,2890,2892,2895,2897],{"class":157,"line":438},[155,2874,2875],{"class":2677},"    window",[155,2877,1245],{"class":169},[155,2879,2880],{"class":576},"addEventListener",[155,2882,363],{"class":1983},[155,2884,618],{"class":274},[155,2886,2887],{"class":614},"popstate",[155,2889,618],{"class":274},[155,2891,1818],{"class":169},[155,2893,2656],{"class":2894},"sWjah",[155,2896,816],{"class":1983},[155,2898,207],{"class":169},[155,2900,2901,2904,2906],{"class":157,"line":456},[155,2902,2903],{"class":169},"  }",[155,2905,816],{"class":1983},[155,2907,207],{"class":169},[155,2909,2910],{"class":157,"line":470},[155,2911,246],{"emptyLinePlaceholder":18},[155,2913,2914,2917,2919,2921,2923],{"class":157,"line":475},[155,2915,2916],{"class":576},"  onUnmounted",[155,2918,363],{"class":1983},[155,2920,2642],{"class":169},[155,2922,2664],{"class":2610},[155,2924,191],{"class":169},[155,2926,2927,2929,2931,2934,2936,2938,2940,2942,2944,2946,2948],{"class":157,"line":810},[155,2928,2875],{"class":2677},[155,2930,1245],{"class":169},[155,2932,2933],{"class":576},"removeEventListener",[155,2935,363],{"class":1983},[155,2937,618],{"class":274},[155,2939,2887],{"class":614},[155,2941,618],{"class":274},[155,2943,1818],{"class":169},[155,2945,2656],{"class":2894},[155,2947,816],{"class":1983},[155,2949,207],{"class":169},[155,2951,2952,2954,2956],{"class":157,"line":1152},[155,2953,2903],{"class":169},[155,2955,816],{"class":1983},[155,2957,207],{"class":169},[155,2959,2960],{"class":157,"line":1167},[155,2961,246],{"emptyLinePlaceholder":18},[155,2963,2964,2967,2969,2971,2973,2975,2978,2980,2982],{"class":157,"line":1182},[155,2965,2966],{"class":576},"  watch",[155,2968,363],{"class":1983},[155,2970,2620],{"class":2894},[155,2972,1818],{"class":169},[155,2974,2674],{"class":169},[155,2976,2977],{"class":2619},"newValue",[155,2979,816],{"class":169},[155,2981,2664],{"class":2610},[155,2983,191],{"class":169},[155,2985,2986,2988,2990,2993,2995,2997],{"class":157,"line":1198},[155,2987,2671],{"class":161},[155,2989,2674],{"class":1983},[155,2991,2992],{"class":2636},"!",[155,2994,2977],{"class":2894},[155,2996,2685],{"class":1983},[155,2998,170],{"class":169},[155,3000,3001,3004,3006,3008,3010],{"class":157,"line":1203},[155,3002,3003],{"class":576},"      setTimeout",[155,3005,363],{"class":1983},[155,3007,2642],{"class":169},[155,3009,2664],{"class":2610},[155,3011,191],{"class":169},[155,3013,3014,3017,3019,3021,3023,3025],{"class":157,"line":1211},[155,3015,3016],{"class":2677},"        globalStore",[155,3018,1245],{"class":169},[155,3020,2781],{"class":366},[155,3022,2637],{"class":2636},[155,3024,2803],{"class":2786},[155,3026,207],{"class":169},[155,3028,3029,3032,3034,3036],{"class":157,"line":1216},[155,3030,3031],{"class":169},"      },",[155,3033,329],{"class":231},[155,3035,816],{"class":1983},[155,3037,207],{"class":169},[155,3039,3040],{"class":157,"line":1221},[155,3041,2810],{"class":169},[155,3043,3045,3047,3049],{"class":157,"line":3044},35,[155,3046,2903],{"class":169},[155,3048,816],{"class":1983},[155,3050,207],{"class":169},[155,3052,3054],{"class":157,"line":3053},36,[155,3055,246],{"emptyLinePlaceholder":18},[155,3057,3059,3061],{"class":157,"line":3058},37,[155,3060,2966],{"class":576},[155,3062,3063],{"class":1983},"(\n",[155,3065,3067,3070,3072,3074,3076,3078],{"class":157,"line":3066},38,[155,3068,3069],{"class":169},"    ()",[155,3071,2664],{"class":2610},[155,3073,2633],{"class":2677},[155,3075,1245],{"class":169},[155,3077,2781],{"class":366},[155,3079,621],{"class":169},[155,3081,3083,3086,3088,3090,3092],{"class":157,"line":3082},39,[155,3084,3085],{"class":169},"    (",[155,3087,2977],{"class":2619},[155,3089,816],{"class":169},[155,3091,2664],{"class":2610},[155,3093,191],{"class":169},[155,3095,3097,3100,3102,3104,3106],{"class":157,"line":3096},40,[155,3098,3099],{"class":161},"      if",[155,3101,2674],{"class":1983},[155,3103,2977],{"class":2894},[155,3105,2685],{"class":1983},[155,3107,170],{"class":169},[155,3109,3111],{"class":157,"line":3110},41,[155,3112,3113],{"class":176},"        \u002F\u002F Ensure route change is prevented when state is true\n",[155,3115,3117,3120,3122,3124,3126,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146],{"class":157,"line":3116},42,[155,3118,3119],{"class":2677},"        history",[155,3121,1245],{"class":169},[155,3123,2702],{"class":576},[155,3125,363],{"class":1983},[155,3127,2707],{"class":183},[155,3129,1818],{"class":169},[155,3131,275],{"class":274},[155,3133,1818],{"class":169},[155,3135,2716],{"class":2677},[155,3137,1245],{"class":169},[155,3139,2722],{"class":2721},[155,3141,1245],{"class":169},[155,3143,2727],{"class":366},[155,3145,816],{"class":1983},[155,3147,207],{"class":169},[155,3149,3151],{"class":157,"line":3150},43,[155,3152,3153],{"class":169},"      }\n",[155,3155,3157],{"class":157,"line":3156},44,[155,3158,642],{"class":169},[155,3160,3162,3165],{"class":157,"line":3161},45,[155,3163,3164],{"class":1983},"  )",[155,3166,207],{"class":169},[155,3168,3170],{"class":157,"line":3169},46,[155,3171,478],{"class":169},[155,3173,3175],{"class":157,"line":3174},47,[155,3176,246],{"emptyLinePlaceholder":18},[155,3178,3180],{"class":157,"line":3179},48,[155,3181,3182],{"class":176},"\u002F\u002F router guard\n",[155,3184,3186,3189,3191,3194,3196,3198,3201,3203,3205,3207,3210,3212,3214],{"class":157,"line":3185},49,[155,3187,3188],{"class":2677},"router",[155,3190,1245],{"class":169},[155,3192,3193],{"class":576},"beforeEach",[155,3195,363],{"class":165},[155,3197,363],{"class":169},[155,3199,3200],{"class":2619},"to",[155,3202,1818],{"class":169},[155,3204,2569],{"class":2619},[155,3206,1818],{"class":169},[155,3208,3209],{"class":2619}," next",[155,3211,816],{"class":169},[155,3213,2664],{"class":2610},[155,3215,191],{"class":169},[155,3217,3219,3222,3224,3227,3229,3231,3233],{"class":157,"line":3218},50,[155,3220,3221],{"class":161},"  if",[155,3223,2674],{"class":1983},[155,3225,3226],{"class":2677},"globals",[155,3228,1245],{"class":169},[155,3230,2781],{"class":366},[155,3232,2685],{"class":1983},[155,3234,170],{"class":169},[155,3236,3238,3241,3243,3245,3247,3249,3251],{"class":157,"line":3237},51,[155,3239,3240],{"class":2677},"    globals",[155,3242,1245],{"class":169},[155,3244,2781],{"class":366},[155,3246,2637],{"class":2636},[155,3248,2803],{"class":2786},[155,3250,2764],{"class":169},[155,3252,3253],{"class":176}," \u002F\u002F Reset immediately\n",[155,3255,3257,3260,3262,3265,3267,3269],{"class":157,"line":3256},52,[155,3258,3259],{"class":576},"    next",[155,3261,363],{"class":1983},[155,3263,3264],{"class":2786},"false",[155,3266,816],{"class":1983},[155,3268,2764],{"class":169},[155,3270,3271],{"class":176}," \u002F\u002F Prevent navigation\n",[155,3273,3275,3278],{"class":157,"line":3274},53,[155,3276,3277],{"class":161},"    return",[155,3279,207],{"class":169},[155,3281,3283],{"class":157,"line":3282},54,[155,3284,240],{"class":169},[155,3286,3288,3291,3293],{"class":157,"line":3287},55,[155,3289,3290],{"class":576},"  next",[155,3292,2642],{"class":1983},[155,3294,207],{"class":169},[155,3296,3298,3300,3302],{"class":157,"line":3297},56,[155,3299,813],{"class":169},[155,3301,816],{"class":165},[155,3303,207],{"class":169},[155,3305,3307],{"class":157,"line":3306},57,[155,3308,246],{"emptyLinePlaceholder":18},[155,3310,3312],{"class":157,"line":3311},58,[155,3313,3314],{"class":176},"\u002F\u002F global store\n",[155,3316,3318,3320,3323,3325,3327,3330,3332,3334,3337,3339,3341],{"class":157,"line":3317},59,[155,3319,569],{"class":161},[155,3321,3322],{"class":2610}," const",[155,3324,2586],{"class":2632},[155,3326,2637],{"class":2636},[155,3328,3329],{"class":576}," defineStore",[155,3331,363],{"class":165},[155,3333,618],{"class":274},[155,3335,3336],{"class":614},"global",[155,3338,618],{"class":274},[155,3340,1818],{"class":169},[155,3342,191],{"class":169},[155,3344,3346,3349,3351,3353,3355,3357],{"class":157,"line":3345},60,[155,3347,3348],{"class":576},"  state",[155,3350,143],{"class":590},[155,3352,2661],{"class":169},[155,3354,2664],{"class":2610},[155,3356,2674],{"class":165},[155,3358,170],{"class":169},[155,3360,3362,3365,3367,3369],{"class":157,"line":3361},61,[155,3363,3364],{"class":586},"    isBackBtnPressed",[155,3366,143],{"class":590},[155,3368,2803],{"class":2786},[155,3370,621],{"class":169},[155,3372,3374,3376,3378],{"class":157,"line":3373},62,[155,3375,2903],{"class":169},[155,3377,816],{"class":165},[155,3379,621],{"class":169},[155,3381,3383,3385,3387],{"class":157,"line":3382},63,[155,3384,813],{"class":169},[155,3386,816],{"class":165},[155,3388,207],{"class":169},[50,3390,483],{"id":482},[480,3392,3394],{"id":3393},"_1-history-state-management","1. History State Management",[31,3396,3397],{},"The composable uses the History API to manage browser navigation. When mounted, it adds an initial state:",[145,3399,3401],{"className":2533,"code":3400,"language":2536,"meta":151,"style":151},"onMounted(() => {\n  history.pushState(null, \"\", window.location.pathname);\n  window.addEventListener(\"popstate\", handlePopState);\n});\n",[58,3402,3403,3416,3449,3474],{"__ignoreMap":151},[155,3404,3405,3408,3410,3412,3414],{"class":157,"line":158},[155,3406,3407],{"class":576},"onMounted",[155,3409,363],{"class":165},[155,3411,2642],{"class":169},[155,3413,2664],{"class":2610},[155,3415,191],{"class":169},[155,3417,3418,3421,3423,3425,3427,3429,3431,3433,3435,3437,3439,3441,3443,3445,3447],{"class":157,"line":173},[155,3419,3420],{"class":2677},"  history",[155,3422,1245],{"class":169},[155,3424,2702],{"class":576},[155,3426,363],{"class":1983},[155,3428,2707],{"class":183},[155,3430,1818],{"class":169},[155,3432,275],{"class":274},[155,3434,1818],{"class":169},[155,3436,2716],{"class":2677},[155,3438,1245],{"class":169},[155,3440,2722],{"class":2721},[155,3442,1245],{"class":169},[155,3444,2727],{"class":366},[155,3446,816],{"class":1983},[155,3448,207],{"class":169},[155,3450,3451,3454,3456,3458,3460,3462,3464,3466,3468,3470,3472],{"class":157,"line":180},[155,3452,3453],{"class":2677},"  window",[155,3455,1245],{"class":169},[155,3457,2880],{"class":576},[155,3459,363],{"class":1983},[155,3461,618],{"class":274},[155,3463,2887],{"class":614},[155,3465,618],{"class":274},[155,3467,1818],{"class":169},[155,3469,2656],{"class":2894},[155,3471,816],{"class":1983},[155,3473,207],{"class":169},[155,3475,3476,3478,3480],{"class":157,"line":194},[155,3477,813],{"class":169},[155,3479,816],{"class":165},[155,3481,207],{"class":169},[31,3483,3484],{},"This creates a \"buffer\" state that we can use to detect back button clicks.",[480,3486,3488],{"id":3487},"_2-scroll-position-management","2. Scroll Position Management",[31,3490,3491],{},"We implement smart scroll behavior:",[87,3493,3494,3497],{},[90,3495,3496],{},"Preserve scroll position when closing modals via back button",[90,3498,3499],{},"Allow normal scroll-to-top behavior for regular navigation",[145,3501,3503],{"className":2533,"code":3502,"language":2536,"meta":151,"style":151},"if (\"scrollRestoration\" in history) {\n  history.scrollRestoration = \"manual\";\n}\n",[58,3504,3505,3530,3549],{"__ignoreMap":151},[155,3506,3507,3510,3512,3514,3517,3519,3523,3526,3528],{"class":157,"line":158},[155,3508,3509],{"class":161},"if",[155,3511,2674],{"class":165},[155,3513,618],{"class":274},[155,3515,3516],{"class":614},"scrollRestoration",[155,3518,618],{"class":274},[155,3520,3522],{"class":3521},"sUnt3"," in",[155,3524,3525],{"class":2894}," history",[155,3527,2685],{"class":165},[155,3529,170],{"class":169},[155,3531,3532,3534,3536,3538,3540,3542,3545,3547],{"class":157,"line":173},[155,3533,3420],{"class":2677},[155,3535,1245],{"class":169},[155,3537,3516],{"class":366},[155,3539,2637],{"class":2636},[155,3541,611],{"class":274},[155,3543,3544],{"class":614},"manual",[155,3546,618],{"class":274},[155,3548,207],{"class":169},[155,3550,3551],{"class":157,"line":180},[155,3552,478],{"class":169},[480,3554,3556],{"id":3555},"_3-state-management-with-pinia","3. State Management with Pinia",[31,3558,3559],{},"We use a global store to track back button states:",[145,3561,3563],{"className":2533,"code":3562,"language":2536,"meta":151,"style":151},"export const useGlobalStore = defineStore(\"global\", {\n  state: () => ({\n    isBackBtnPressed: false,\n  }),\n});\n",[58,3564,3565,3589,3603,3613,3621],{"__ignoreMap":151},[155,3566,3567,3569,3571,3573,3575,3577,3579,3581,3583,3585,3587],{"class":157,"line":158},[155,3568,569],{"class":161},[155,3570,3322],{"class":2610},[155,3572,2586],{"class":2632},[155,3574,2637],{"class":2636},[155,3576,3329],{"class":576},[155,3578,363],{"class":165},[155,3580,618],{"class":274},[155,3582,3336],{"class":614},[155,3584,618],{"class":274},[155,3586,1818],{"class":169},[155,3588,191],{"class":169},[155,3590,3591,3593,3595,3597,3599,3601],{"class":157,"line":173},[155,3592,3348],{"class":576},[155,3594,143],{"class":590},[155,3596,2661],{"class":169},[155,3598,2664],{"class":2610},[155,3600,2674],{"class":165},[155,3602,170],{"class":169},[155,3604,3605,3607,3609,3611],{"class":157,"line":180},[155,3606,3364],{"class":586},[155,3608,143],{"class":590},[155,3610,2803],{"class":2786},[155,3612,621],{"class":169},[155,3614,3615,3617,3619],{"class":157,"line":194},[155,3616,2903],{"class":169},[155,3618,816],{"class":165},[155,3620,621],{"class":169},[155,3622,3623,3625,3627],{"class":157,"line":210},[155,3624,813],{"class":169},[155,3626,816],{"class":165},[155,3628,207],{"class":169},[31,3630,3631],{},"This helps coordinate between the composable and router guards.",[480,3633,3635],{"id":3634},"_4-router-integration","4. Router Integration",[31,3637,3638],{},"The router guard prevents unwanted navigation:",[145,3640,3642],{"className":2533,"code":3641,"language":2536,"meta":151,"style":151},"router.beforeEach((to, from, next) => {\n  if (globals.isBackBtnPressed) {\n    globals.isBackBtnPressed = false;\n    next(false);\n    return;\n  }\n  next();\n});\n",[58,3643,3644,3672,3688,3702,3714,3720,3724,3732],{"__ignoreMap":151},[155,3645,3646,3648,3650,3652,3654,3656,3658,3660,3662,3664,3666,3668,3670],{"class":157,"line":158},[155,3647,3188],{"class":2677},[155,3649,1245],{"class":169},[155,3651,3193],{"class":576},[155,3653,363],{"class":165},[155,3655,363],{"class":169},[155,3657,3200],{"class":2619},[155,3659,1818],{"class":169},[155,3661,2569],{"class":2619},[155,3663,1818],{"class":169},[155,3665,3209],{"class":2619},[155,3667,816],{"class":169},[155,3669,2664],{"class":2610},[155,3671,191],{"class":169},[155,3673,3674,3676,3678,3680,3682,3684,3686],{"class":157,"line":173},[155,3675,3221],{"class":161},[155,3677,2674],{"class":1983},[155,3679,3226],{"class":2677},[155,3681,1245],{"class":169},[155,3683,2781],{"class":366},[155,3685,2685],{"class":1983},[155,3687,170],{"class":169},[155,3689,3690,3692,3694,3696,3698,3700],{"class":157,"line":180},[155,3691,3240],{"class":2677},[155,3693,1245],{"class":169},[155,3695,2781],{"class":366},[155,3697,2637],{"class":2636},[155,3699,2803],{"class":2786},[155,3701,207],{"class":169},[155,3703,3704,3706,3708,3710,3712],{"class":157,"line":194},[155,3705,3259],{"class":576},[155,3707,363],{"class":1983},[155,3709,3264],{"class":2786},[155,3711,816],{"class":1983},[155,3713,207],{"class":169},[155,3715,3716,3718],{"class":157,"line":210},[155,3717,3277],{"class":161},[155,3719,207],{"class":169},[155,3721,3722],{"class":157,"line":223},[155,3723,240],{"class":169},[155,3725,3726,3728,3730],{"class":157,"line":237},[155,3727,3290],{"class":576},[155,3729,2642],{"class":1983},[155,3731,207],{"class":169},[155,3733,3734,3736,3738],{"class":157,"line":243},[155,3735,813],{"class":169},[155,3737,816],{"class":165},[155,3739,207],{"class":169},[50,3741,3743],{"id":3742},"usage-examples","Usage Examples",[480,3745,3747],{"id":3746},"basic-modal-implementation","Basic Modal Implementation",[145,3749,3751],{"className":1392,"code":3750,"filename":1394,"language":1395,"meta":151,"style":151},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cbutton @click=\"showModal = true\">Open Modal\u003C\u002Fbutton>\n    \u003CModal v-if=\"showModal\" v-model=\"showModal\"> Content here \u003C\u002FModal>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref } from \"vue\";\nimport { useBackButton } from \"@\u002Fcomposables\u002FuseBackButton\";\n\nconst showModal = ref(false);\nuseBackButton(showModal);\n\u003C\u002Fscript>\n",[58,3752,3753,3761,3769,3799,3840,3848,3856,3860,3872,3893,3914,3918,3938,3950],{"__ignoreMap":151},[155,3754,3755,3757,3759],{"class":157,"line":158},[155,3756,1402],{"class":169},[155,3758,1405],{"class":586},[155,3760,1408],{"class":169},[155,3762,3763,3765,3767],{"class":157,"line":173},[155,3764,1413],{"class":169},[155,3766,1416],{"class":586},[155,3768,1408],{"class":169},[155,3770,3771,3773,3775,3778,3780,3782,3785,3787,3790,3793,3795,3797],{"class":157,"line":180},[155,3772,1442],{"class":169},[155,3774,1932],{"class":586},[155,3776,3777],{"class":1419}," @click",[155,3779,1423],{"class":169},[155,3781,618],{"class":274},[155,3783,3784],{"class":614},"showModal = true",[155,3786,618],{"class":274},[155,3788,3789],{"class":169},">",[155,3791,3792],{"class":165},"Open Modal",[155,3794,1609],{"class":169},[155,3796,1932],{"class":586},[155,3798,1408],{"class":169},[155,3800,3801,3803,3806,3809,3811,3813,3816,3818,3821,3823,3825,3827,3829,3831,3834,3836,3838],{"class":157,"line":194},[155,3802,1442],{"class":169},[155,3804,3805],{"class":586},"Modal",[155,3807,3808],{"class":1419}," v-if",[155,3810,1423],{"class":169},[155,3812,618],{"class":274},[155,3814,3815],{"class":614},"showModal",[155,3817,618],{"class":274},[155,3819,3820],{"class":1419}," v-model",[155,3822,1423],{"class":169},[155,3824,618],{"class":274},[155,3826,3815],{"class":614},[155,3828,618],{"class":274},[155,3830,3789],{"class":169},[155,3832,3833],{"class":165}," Content here ",[155,3835,1609],{"class":169},[155,3837,3805],{"class":586},[155,3839,1408],{"class":169},[155,3841,3842,3844,3846],{"class":157,"line":210},[155,3843,1600],{"class":169},[155,3845,1416],{"class":586},[155,3847,1408],{"class":169},[155,3849,3850,3852,3854],{"class":157,"line":223},[155,3851,1609],{"class":169},[155,3853,1405],{"class":586},[155,3855,1408],{"class":169},[155,3857,3858],{"class":157,"line":237},[155,3859,246],{"emptyLinePlaceholder":18},[155,3861,3862,3864,3867,3870],{"class":157,"line":243},[155,3863,1402],{"class":169},[155,3865,3866],{"class":586},"script",[155,3868,3869],{"class":1419}," setup",[155,3871,1408],{"class":169},[155,3873,3874,3876,3878,3881,3883,3885,3887,3889,3891],{"class":157,"line":249},[155,3875,2548],{"class":161},[155,3877,1964],{"class":169},[155,3879,3880],{"class":366}," ref",[155,3882,2566],{"class":169},[155,3884,2569],{"class":161},[155,3886,611],{"class":274},[155,3888,1395],{"class":614},[155,3890,618],{"class":274},[155,3892,207],{"class":169},[155,3894,3895,3897,3899,3901,3903,3905,3907,3910,3912],{"class":157,"line":266},[155,3896,2548],{"class":161},[155,3898,1964],{"class":169},[155,3900,2614],{"class":366},[155,3902,2566],{"class":169},[155,3904,2569],{"class":161},[155,3906,611],{"class":274},[155,3908,3909],{"class":614},"@\u002Fcomposables\u002FuseBackButton",[155,3911,618],{"class":274},[155,3913,207],{"class":169},[155,3915,3916],{"class":157,"line":280},[155,3917,246],{"emptyLinePlaceholder":18},[155,3919,3920,3923,3926,3928,3930,3932,3934,3936],{"class":157,"line":292},[155,3921,3922],{"class":2610},"const",[155,3924,3925],{"class":2632}," showModal",[155,3927,2637],{"class":2636},[155,3929,3880],{"class":576},[155,3931,363],{"class":165},[155,3933,3264],{"class":2786},[155,3935,816],{"class":165},[155,3937,207],{"class":169},[155,3939,3940,3942,3944,3946,3948],{"class":157,"line":304},[155,3941,2503],{"class":576},[155,3943,363],{"class":165},[155,3945,3815],{"class":2894},[155,3947,816],{"class":165},[155,3949,207],{"class":169},[155,3951,3952,3954,3956],{"class":157,"line":321},[155,3953,1609],{"class":169},[155,3955,3866],{"class":586},[155,3957,1408],{"class":169},[480,3959,3961],{"id":3960},"with-complex-dialog","With Complex Dialog",[556,3963,3964],{},[145,3965,3967],{"className":1392,"code":3966,"filename":1394,"language":1395,"meta":151,"style":151},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cbutton @click=\"openDialog\">Open Complex Dialog\u003C\u002Fbutton>\n    \u003CDialog v-model=\"dialogVisible\" :options=\"dialogOptions\">\n      \u003Ctemplate #default>\n        \u003Cform @submit.prevent=\"handleSubmit\">\n          \u003C!-- Form content -->\n        \u003C\u002Fform>\n      \u003C\u002Ftemplate>\n    \u003C\u002FDialog>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref } from \"vue\";\nimport { useBackButton } from \"@\u002Fcomposables\u002FuseBackButton\";\n\nconst dialogVisible = ref(false);\nconst dialogOptions = ref({\n  title: \"Complex Form\",\n  width: \"600px\",\n});\n\nuseBackButton(dialogVisible);\n\u003C\u002Fscript>\n",[58,3968,3969,3977,3985,4013,4045,4060,4082,4087,4096,4105,4113,4121,4129,4133,4143,4163,4183,4187,4206,4221,4237,4252,4260,4264,4276],{"__ignoreMap":151},[155,3970,3971,3973,3975],{"class":157,"line":158},[155,3972,1402],{"class":169},[155,3974,1405],{"class":586},[155,3976,1408],{"class":169},[155,3978,3979,3981,3983],{"class":157,"line":173},[155,3980,1413],{"class":169},[155,3982,1416],{"class":586},[155,3984,1408],{"class":169},[155,3986,3987,3989,3991,3993,3995,3997,4000,4002,4004,4007,4009,4011],{"class":157,"line":180},[155,3988,1442],{"class":169},[155,3990,1932],{"class":586},[155,3992,3777],{"class":1419},[155,3994,1423],{"class":169},[155,3996,618],{"class":274},[155,3998,3999],{"class":614},"openDialog",[155,4001,618],{"class":274},[155,4003,3789],{"class":169},[155,4005,4006],{"class":165},"Open Complex Dialog",[155,4008,1609],{"class":169},[155,4010,1932],{"class":586},[155,4012,1408],{"class":169},[155,4014,4015,4017,4020,4022,4024,4026,4029,4031,4034,4036,4038,4041,4043],{"class":157,"line":194},[155,4016,1442],{"class":169},[155,4018,4019],{"class":586},"Dialog",[155,4021,3820],{"class":1419},[155,4023,1423],{"class":169},[155,4025,618],{"class":274},[155,4027,4028],{"class":614},"dialogVisible",[155,4030,618],{"class":274},[155,4032,4033],{"class":1419}," :options",[155,4035,1423],{"class":169},[155,4037,618],{"class":274},[155,4039,4040],{"class":614},"dialogOptions",[155,4042,618],{"class":274},[155,4044,1408],{"class":169},[155,4046,4047,4050,4052,4055,4058],{"class":157,"line":210},[155,4048,4049],{"class":169},"      \u003C",[155,4051,1405],{"class":586},[155,4053,4054],{"class":169}," #",[155,4056,4057],{"class":1419},"default",[155,4059,1408],{"class":169},[155,4061,4062,4065,4068,4071,4073,4075,4078,4080],{"class":157,"line":223},[155,4063,4064],{"class":169},"        \u003C",[155,4066,4067],{"class":586},"form",[155,4069,4070],{"class":1419}," @submit.prevent",[155,4072,1423],{"class":169},[155,4074,618],{"class":274},[155,4076,4077],{"class":614},"handleSubmit",[155,4079,618],{"class":274},[155,4081,1408],{"class":169},[155,4083,4084],{"class":157,"line":237},[155,4085,4086],{"class":176},"          \u003C!-- Form content -->\n",[155,4088,4089,4092,4094],{"class":157,"line":243},[155,4090,4091],{"class":169},"        \u003C\u002F",[155,4093,4067],{"class":586},[155,4095,1408],{"class":169},[155,4097,4098,4101,4103],{"class":157,"line":249},[155,4099,4100],{"class":169},"      \u003C\u002F",[155,4102,1405],{"class":586},[155,4104,1408],{"class":169},[155,4106,4107,4109,4111],{"class":157,"line":266},[155,4108,1479],{"class":169},[155,4110,4019],{"class":586},[155,4112,1408],{"class":169},[155,4114,4115,4117,4119],{"class":157,"line":280},[155,4116,1600],{"class":169},[155,4118,1416],{"class":586},[155,4120,1408],{"class":169},[155,4122,4123,4125,4127],{"class":157,"line":292},[155,4124,1609],{"class":169},[155,4126,1405],{"class":586},[155,4128,1408],{"class":169},[155,4130,4131],{"class":157,"line":304},[155,4132,246],{"emptyLinePlaceholder":18},[155,4134,4135,4137,4139,4141],{"class":157,"line":321},[155,4136,1402],{"class":169},[155,4138,3866],{"class":586},[155,4140,3869],{"class":1419},[155,4142,1408],{"class":169},[155,4144,4145,4147,4149,4151,4153,4155,4157,4159,4161],{"class":157,"line":337},[155,4146,2548],{"class":161},[155,4148,1964],{"class":169},[155,4150,3880],{"class":366},[155,4152,2566],{"class":169},[155,4154,2569],{"class":161},[155,4156,611],{"class":274},[155,4158,1395],{"class":614},[155,4160,618],{"class":274},[155,4162,207],{"class":169},[155,4164,4165,4167,4169,4171,4173,4175,4177,4179,4181],{"class":157,"line":351},[155,4166,2548],{"class":161},[155,4168,1964],{"class":169},[155,4170,2614],{"class":366},[155,4172,2566],{"class":169},[155,4174,2569],{"class":161},[155,4176,611],{"class":274},[155,4178,3909],{"class":614},[155,4180,618],{"class":274},[155,4182,207],{"class":169},[155,4184,4185],{"class":157,"line":373},[155,4186,246],{"emptyLinePlaceholder":18},[155,4188,4189,4191,4194,4196,4198,4200,4202,4204],{"class":157,"line":394},[155,4190,3922],{"class":2610},[155,4192,4193],{"class":2632}," dialogVisible",[155,4195,2637],{"class":2636},[155,4197,3880],{"class":576},[155,4199,363],{"class":165},[155,4201,3264],{"class":2786},[155,4203,816],{"class":165},[155,4205,207],{"class":169},[155,4207,4208,4210,4213,4215,4217,4219],{"class":157,"line":406},[155,4209,3922],{"class":2610},[155,4211,4212],{"class":2632}," dialogOptions",[155,4214,2637],{"class":2636},[155,4216,3880],{"class":576},[155,4218,363],{"class":165},[155,4220,170],{"class":169},[155,4222,4223,4226,4228,4230,4233,4235],{"class":157,"line":428},[155,4224,4225],{"class":586},"  title",[155,4227,143],{"class":590},[155,4229,611],{"class":274},[155,4231,4232],{"class":614},"Complex Form",[155,4234,618],{"class":274},[155,4236,621],{"class":169},[155,4238,4239,4241,4243,4245,4248,4250],{"class":157,"line":433},[155,4240,1750],{"class":586},[155,4242,143],{"class":590},[155,4244,611],{"class":274},[155,4246,4247],{"class":614},"600px",[155,4249,618],{"class":274},[155,4251,621],{"class":169},[155,4253,4254,4256,4258],{"class":157,"line":438},[155,4255,813],{"class":169},[155,4257,816],{"class":165},[155,4259,207],{"class":169},[155,4261,4262],{"class":157,"line":456},[155,4263,246],{"emptyLinePlaceholder":18},[155,4265,4266,4268,4270,4272,4274],{"class":157,"line":470},[155,4267,2503],{"class":576},[155,4269,363],{"class":165},[155,4271,4028],{"class":2894},[155,4273,816],{"class":165},[155,4275,207],{"class":169},[155,4277,4278,4280,4282],{"class":157,"line":475},[155,4279,1609],{"class":169},[155,4281,3866],{"class":586},[155,4283,1408],{"class":169},[50,4285,4287],{"id":4286},"edge-cases-and-solutions","Edge Cases and Solutions",[2354,4289,4290],{},[31,4291,4292],{},"It is important to handle edge cases such as double click, removing listener events & global state to ensure a smooth user experience.",[480,4294,4296],{"id":4295},"_1-double-back-click-handling","1. Double Back Click Handling",[31,4298,4299],{},"We handle rapid back button clicks by adding two history states:",[145,4301,4303],{"className":2533,"code":4302,"language":2536,"meta":151,"style":151},"history.pushState(null, \"\", window.location.pathname);\nhistory.pushState(null, \"\", window.location.pathname);\n",[58,4304,4305,4338],{"__ignoreMap":151},[155,4306,4307,4310,4312,4314,4316,4318,4320,4322,4324,4326,4328,4330,4332,4334,4336],{"class":157,"line":158},[155,4308,4309],{"class":2677},"history",[155,4311,1245],{"class":169},[155,4313,2702],{"class":576},[155,4315,363],{"class":165},[155,4317,2707],{"class":183},[155,4319,1818],{"class":169},[155,4321,275],{"class":274},[155,4323,1818],{"class":169},[155,4325,2716],{"class":2677},[155,4327,1245],{"class":169},[155,4329,2722],{"class":2721},[155,4331,1245],{"class":169},[155,4333,2727],{"class":366},[155,4335,816],{"class":165},[155,4337,207],{"class":169},[155,4339,4340,4342,4344,4346,4348,4350,4352,4354,4356,4358,4360,4362,4364,4366,4368],{"class":157,"line":173},[155,4341,4309],{"class":2677},[155,4343,1245],{"class":169},[155,4345,2702],{"class":576},[155,4347,363],{"class":165},[155,4349,2707],{"class":183},[155,4351,1818],{"class":169},[155,4353,275],{"class":274},[155,4355,1818],{"class":169},[155,4357,2716],{"class":2677},[155,4359,1245],{"class":169},[155,4361,2722],{"class":2721},[155,4363,1245],{"class":169},[155,4365,2727],{"class":366},[155,4367,816],{"class":165},[155,4369,207],{"class":169},[480,4371,4373],{"id":4372},"_2-cleanup","2. Cleanup",[31,4375,4376],{},"Proper cleanup is essential to prevent memory leaks:",[145,4378,4380],{"className":2533,"code":4379,"language":2536,"meta":151,"style":151},"onUnmounted(() => {\n  if (\"scrollRestoration\" in history) {\n    history.scrollRestoration = \"auto\";\n  }\n  window.removeEventListener(\"popstate\", handlePopState);\n});\n",[58,4381,4382,4395,4415,4434,4438,4462],{"__ignoreMap":151},[155,4383,4384,4387,4389,4391,4393],{"class":157,"line":158},[155,4385,4386],{"class":576},"onUnmounted",[155,4388,363],{"class":165},[155,4390,2642],{"class":169},[155,4392,2664],{"class":2610},[155,4394,191],{"class":169},[155,4396,4397,4399,4401,4403,4405,4407,4409,4411,4413],{"class":157,"line":173},[155,4398,3221],{"class":161},[155,4400,2674],{"class":1983},[155,4402,618],{"class":274},[155,4404,3516],{"class":614},[155,4406,618],{"class":274},[155,4408,3522],{"class":3521},[155,4410,3525],{"class":2894},[155,4412,2685],{"class":1983},[155,4414,170],{"class":169},[155,4416,4417,4419,4421,4423,4425,4427,4430,4432],{"class":157,"line":180},[155,4418,2842],{"class":2677},[155,4420,1245],{"class":169},[155,4422,3516],{"class":366},[155,4424,2637],{"class":2636},[155,4426,611],{"class":274},[155,4428,4429],{"class":614},"auto",[155,4431,618],{"class":274},[155,4433,207],{"class":169},[155,4435,4436],{"class":157,"line":194},[155,4437,240],{"class":169},[155,4439,4440,4442,4444,4446,4448,4450,4452,4454,4456,4458,4460],{"class":157,"line":210},[155,4441,3453],{"class":2677},[155,4443,1245],{"class":169},[155,4445,2933],{"class":576},[155,4447,363],{"class":1983},[155,4449,618],{"class":274},[155,4451,2887],{"class":614},[155,4453,618],{"class":274},[155,4455,1818],{"class":169},[155,4457,2656],{"class":2894},[155,4459,816],{"class":1983},[155,4461,207],{"class":169},[155,4463,4464,4466,4468],{"class":157,"line":223},[155,4465,813],{"class":169},[155,4467,816],{"class":165},[155,4469,207],{"class":169},[480,4471,4473],{"id":4472},"_3-timing-issues","3. Timing Issues",[31,4475,4476],{},"We use small timeouts to ensure proper state management:",[145,4478,4480],{"className":2533,"code":4479,"language":2536,"meta":151,"style":151},"setTimeout(() => {\n  globalStore.isBackBtnPressed = false;\n}, 100);\n",[58,4481,4482,4495,4510],{"__ignoreMap":151},[155,4483,4484,4487,4489,4491,4493],{"class":157,"line":158},[155,4485,4486],{"class":576},"setTimeout",[155,4488,363],{"class":165},[155,4490,2642],{"class":169},[155,4492,2664],{"class":2610},[155,4494,191],{"class":169},[155,4496,4497,4500,4502,4504,4506,4508],{"class":157,"line":173},[155,4498,4499],{"class":2677},"  globalStore",[155,4501,1245],{"class":169},[155,4503,2781],{"class":366},[155,4505,2637],{"class":2636},[155,4507,2803],{"class":2786},[155,4509,207],{"class":169},[155,4511,4512,4515,4517,4519],{"class":157,"line":180},[155,4513,4514],{"class":169},"},",[155,4516,329],{"class":231},[155,4518,816],{"class":165},[155,4520,207],{"class":169},[50,4522,4524],{"id":4523},"best-practices","Best Practices",[107,4526,4527,4533,4539,4545],{},[90,4528,4529,4532],{},[37,4530,4531],{},"Always Use Refs","\nPass reactive refs to the composable for reliable state management.",[90,4534,4535,4538],{},[37,4536,4537],{},"Router Guard Integration","\nImplement the router guard to ensure consistent navigation behavior.",[90,4540,4541,4544],{},[37,4542,4543],{},"Clean Unmounting","\nThe composable handles its own cleanup, but ensure parent components handle their state properly.",[90,4546,4547,4550,4551],{},[37,4548,4549],{},"Testing","\nTest various scenarios:",[87,4552,4553,4556,4559],{},[90,4554,4555],{},"Rapid back button clicks",[90,4557,4558],{},"Modal opening\u002Fclosing sequences",[90,4560,4561],{},"Navigation during modal open states",[50,4563,2372],{"id":2371},[31,4565,540,4566,4568],{},[58,4567,2503],{}," composable provides a robust solution for handling browser navigation in modern Vue applications. It solves common UX issues while maintaining clean code architecture and providing a seamless user experience.",[31,4570,4571],{},"Whether you're building a simple modal dialog or a complex multi-step form, this composable can help you manage browser navigation effectively while preserving user context and scroll position.",[31,4573,4574],{},"Remember to:",[87,4576,4577,4580,4583,4586],{},[90,4578,4579],{},"Test thoroughly in your specific use case",[90,4581,4582],{},"Consider edge cases specific to your application",[90,4584,4585],{},"Maintain proper state management",[90,4587,4588],{},"Handle cleanup appropriately",[31,4590,4591],{},"With these considerations in mind, you'll have a reliable solution for handling browser navigation in your Vue 3 applications.",[50,4593,2414],{"id":2413},[2416,4595,4596],{},"html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .sQsOY, html code.shiki .sQsOY{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A626A4;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .s8dPH, html code.shiki .s8dPH{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .sVH1b, html code.shiki .sVH1b{--shiki-light:#39ADB5;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .spZWa, html code.shiki .spZWa{--shiki-light:#91B859;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sJvVP, html code.shiki .sJvVP{--shiki-light:#9C3EDA;--shiki-default:#A626A4;--shiki-dark:#C678DD}html pre.shiki code .spnjr, html code.shiki .spnjr{--shiki-light:#6182B8;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .s5f2p, html code.shiki .s5f2p{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#383A42;--shiki-default-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic}html pre.shiki code .sMm83, html code.shiki .sMm83{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#E5C07B}html pre.shiki code .syPST, html code.shiki .syPST{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .sA0eD, html code.shiki .sA0eD{--shiki-light:#E53935;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .svfkx, html code.shiki .svfkx{--shiki-light:#90A4AE;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .scCn_, html code.shiki .scCn_{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E5C07B}html pre.shiki code .svDm9, html code.shiki .svDm9{--shiki-light:#39ADB5;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sDC5J, html code.shiki .sDC5J{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E5C07B}html pre.shiki code .sbyCm, html code.shiki .sbyCm{--shiki-light:#FF5370;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sWjah, html code.shiki .sWjah{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E06C75}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .saKOp, html code.shiki .saKOp{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#ABB2BF}html pre.shiki code .su13H, html code.shiki .su13H{--shiki-light:#E53935;--shiki-default:#E45649;--shiki-dark:#E06C75}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 .sUnt3, html code.shiki .sUnt3{--shiki-light:#39ADB5;--shiki-default:#A626A4;--shiki-dark:#C678DD}html pre.shiki code .sGh1W, html code.shiki .sGh1W{--shiki-light:#9C3EDA;--shiki-default:#986801;--shiki-dark:#D19A66}",{"title":151,"searchDepth":173,"depth":173,"links":4598},[4599,4600,4603,4609,4613,4618,4619,4620],{"id":52,"depth":173,"text":53},{"id":2496,"depth":173,"text":2497,"children":4601},[4602],{"id":2527,"depth":180,"text":2528},{"id":482,"depth":173,"text":483,"children":4604},[4605,4606,4607,4608],{"id":3393,"depth":180,"text":3394},{"id":3487,"depth":180,"text":3488},{"id":3555,"depth":180,"text":3556},{"id":3634,"depth":180,"text":3635},{"id":3742,"depth":173,"text":3743,"children":4610},[4611,4612],{"id":3746,"depth":180,"text":3747},{"id":3960,"depth":180,"text":3961},{"id":4286,"depth":173,"text":4287,"children":4614},[4615,4616,4617],{"id":4295,"depth":180,"text":4296},{"id":4372,"depth":180,"text":4373},{"id":4472,"depth":180,"text":4473},{"id":4523,"depth":173,"text":4524},{"id":2371,"depth":173,"text":2372},{"id":2413,"depth":173,"text":2414},"2024-12-02",{"slug":4623,"difficulty":2442,"featured":8,"icon":1395,"ogImage":4624,"tags":4626,"topic":1395},"remote-back-button-js",{"alt":4625},"remote back button function",[1395,4627,2448],"composable","\u002Farticles\u002Fremote-back-button-js",{"title":2455,"description":2460},"articles\u002Fremote-back-button-js","c9McQgPfIrLnWtQfO9BV7b7nDG5cwoJisMDonjUVoWc",{"id":4633,"title":4634,"author":6,"body":4635,"date":5490,"description":4639,"draft":8,"extension":2439,"image":6,"lastmod":5490,"meta":5491,"minRead":6,"navigation":18,"path":5501,"seo":5502,"stem":5503,"__hash__":5504},"articles\u002Farticles\u002Fcommit-to-release.md","From Commit to Release: Automating GitHub Workflows",{"type":28,"value":4636,"toc":5470},[4637,4640,4642,4653,4658,4662,4679,4683,4753,4757,4759,4767,4771,4821,4825,4829,4835,4925,4929,4935,4942,5048,5055,5080,5087,5154,5158,5214,5217,5257,5261,5268,5291,5298,5339,5346,5354,5361,5369,5373,5377,5384,5397,5404,5428,5435,5450,5454,5465,5467],[31,4638,4639],{},"This documentation describes an automated GitHub workflow system that handles pull request labelling and automated releases for both development and production environments. The system uses branch naming conventions to automatically label PRs, generates release notes, and manages versioning.",[50,4641,483],{"id":482},[4643,4644,4645],"mermaid",{},[145,4646,4651],{"className":4647,"code":4649,"language":4650},[4648],"language-text","graph LR\n    A[\"🌿 Branch Name\"] --> B{\"PR Labeler\"}\n    \n    B -->|\"breaking:*\"| C1[\"🏷️ breaking\"]\n    B -->|\"feature:*\"| C2[\"🏷️ feature\"]\n    B -->|\"fix:*\"| C3[\"🏷️ fix\"]\n    B -->|\"chore:*\"| C4[\"🏷️ chore\"]\n    \n    C1 --> D[\"Version Resolution\"]\n    C2 --> D\n    C3 --> D\n    C4 --> D\n    \n    D -->|breaking| E1[\"📈 Major\n    1.0.0 → 2.0.0\"]\n    D -->|feature\u002Ffix| E2[\"📊 Minor\n    1.0.0 → 1.1.0\"]\n    D -->|chore| E3[\"📉 Patch\n    1.0.0 → 1.0.1\"]\n    \n    E1 --> F[\"📦 Release\"]\n    E2 --> F\n    E3 --> F\n    \n    style A fill:#4078f2,stroke:#2c5aa0,color:#fff\n    style F fill:#0e8a16,stroke:#0a6b11,color:#fff\n    style C1 fill:#d73a49,stroke:#b02a37,color:#fff\n    style C2 fill:#0e8a16,stroke:#0a6b11,color:#fff\n    style C3 fill:#ffd33d,stroke:#d4a72c,color:#000\n    style C4 fill:#0366d6,stroke:#024c9c,color:#fff\n","text",[58,4652,4649],{"__ignoreMap":151},[536,4654,4655],{},[31,4656,4657],{},"This workflow automates the entire release process from branch creation to production deployment.",[480,4659,4661],{"id":4660},"pr-labeling-system","PR Labeling System",[87,4663,4664,4667,4670,4676],{},[90,4665,4666],{},"Monitors for new pull requests",[90,4668,4669],{},"Analyses branch names to apply appropriate labels",[90,4671,4672,4673],{},"Uses configured patterns in ",[58,4674,4675],{},"pr-labeler.yml",[90,4677,4678],{},"Labels determine how changes are categorised in releases",[480,4680,4682],{"id":4681},"release-management","Release Management",[107,4684,4685,4705,4724],{},[90,4686,4687,4690],{},[37,4688,4689],{},"Development Releases",[107,4691,4692,4699,4702],{},[90,4693,4694,4695,4698],{},"Triggered by pushes to ",[58,4696,4697],{},"dev"," branch",[90,4700,4701],{},"Creates draft releases",[90,4703,4704],{},"Maintains development version tracking",[90,4706,4707,4710,4711],{},[37,4708,4709],{},"Production Releases",":\n",[107,4712,4713,4718,4721],{},[90,4714,4694,4715,4698],{},[58,4716,4717],{},"main",[90,4719,4720],{},"Automatically publishes releases",[90,4722,4723],{},"Includes hotfix detection",[90,4725,4726,4729,4730],{},[37,4727,4728],{},"Version Resolution"," : Automatically determines version numbers based on PR labels\n",[107,4731,4732,4738,4747],{},[90,4733,4734,4737],{},[58,4735,4736],{},"breaking"," → Major version bump",[90,4739,4740,61,4743,4746],{},[58,4741,4742],{},"feature",[58,4744,4745],{},"fix"," → Minor version bump",[90,4748,4749,4752],{},[58,4750,4751],{},"chore",", etc. → Patch version bump",[50,4754,4756],{"id":4755},"setup-instructions","Setup Instructions",[480,4758,82],{"id":81},[87,4760,4761,4764],{},[90,4762,4763],{},"GitHub Personal Access Token (classic) or Organisation Token",[90,4765,4766],{},"Token Must have private repository read, write and workflow permissions",[480,4768,4770],{"id":4769},"required-files-structure","Required Files Structure",[145,4772,4777],{"className":4773,"code":4774,"filename":4775,"highlights":4776,"language":2439,"meta":151,"style":151},"language-md shiki shiki-themes material-theme-lighter one-light one-dark-pro","📦root\n┣📦.github\n┣ 📂workflows\n┃ ┣ 📜pr-labeler.yml # PR labeling workflow\n┃ ┣ 📜release-dev.yml # Development release workflow\n┃ ┗ 📜release-prod.yml # Production release workflow\n┣ 📜pr-labeler.yml # Label configuration\n┗ 📜release-drafter.yml # Release configuration\n","Folder Structure.md",[180],[58,4778,4779,4784,4789,4796,4801,4806,4811,4816],{"__ignoreMap":151},[155,4780,4781],{"class":157,"line":158},[155,4782,4783],{"class":165},"📦root\n",[155,4785,4786],{"class":157,"line":173},[155,4787,4788],{"class":165},"┣📦.github\n",[155,4790,4793],{"class":4791,"line":180},[157,4792],"highlight",[155,4794,4795],{"class":165},"┣ 📂workflows\n",[155,4797,4798],{"class":157,"line":194},[155,4799,4800],{"class":165},"┃ ┣ 📜pr-labeler.yml # PR labeling workflow\n",[155,4802,4803],{"class":157,"line":210},[155,4804,4805],{"class":165},"┃ ┣ 📜release-dev.yml # Development release workflow\n",[155,4807,4808],{"class":157,"line":223},[155,4809,4810],{"class":165},"┃ ┗ 📜release-prod.yml # Production release workflow\n",[155,4812,4813],{"class":157,"line":237},[155,4814,4815],{"class":165},"┣ 📜pr-labeler.yml # Label configuration\n",[155,4817,4818],{"class":157,"line":243},[155,4819,4820],{"class":165},"┗ 📜release-drafter.yml # Release configuration\n",[480,4822,4824],{"id":4823},"customising-templates","Customising Templates",[480,4826,4828],{"id":4827},"modifying-pr-labels","Modifying PR Labels",[31,4830,4831,4832,143],{},"To add or modify label patterns, edit ",[58,4833,4834],{},".github\u002Fpr-labeler.yml",[145,4836,4840],{"className":4837,"code":4838,"filename":4675,"language":4839,"meta":151,"style":151},"language-yaml shiki shiki-themes material-theme-lighter one-light one-dark-pro","# Add new label\nenhancement: [\"enhance\u002F*\", \"improvement\u002F*\"]\n\n# Modify existing label\nfeature:\n  - \"feature\u002F*\"\n  - \"feat\u002F*\"\n  - \"new\u002F*\"\n","yaml",[58,4841,4842,4847,4876,4880,4885,4891,4903,4914],{"__ignoreMap":151},[155,4843,4844],{"class":157,"line":158},[155,4845,4846],{"class":176},"# Add new label\n",[155,4848,4849,4852,4854,4857,4859,4862,4864,4866,4868,4871,4873],{"class":157,"line":173},[155,4850,4851],{"class":586},"enhancement",[155,4853,143],{"class":169},[155,4855,4856],{"class":169}," [",[155,4858,618],{"class":274},[155,4860,4861],{"class":614},"enhance\u002F*",[155,4863,618],{"class":274},[155,4865,1818],{"class":169},[155,4867,611],{"class":274},[155,4869,4870],{"class":614},"improvement\u002F*",[155,4872,618],{"class":274},[155,4874,4875],{"class":169},"]\n",[155,4877,4878],{"class":157,"line":180},[155,4879,246],{"emptyLinePlaceholder":18},[155,4881,4882],{"class":157,"line":194},[155,4883,4884],{"class":176},"# Modify existing label\n",[155,4886,4887,4889],{"class":157,"line":210},[155,4888,4742],{"class":586},[155,4890,4710],{"class":169},[155,4892,4893,4896,4898,4901],{"class":157,"line":223},[155,4894,4895],{"class":169},"  -",[155,4897,611],{"class":274},[155,4899,4900],{"class":614},"feature\u002F*",[155,4902,2216],{"class":274},[155,4904,4905,4907,4909,4912],{"class":157,"line":237},[155,4906,4895],{"class":169},[155,4908,611],{"class":274},[155,4910,4911],{"class":614},"feat\u002F*",[155,4913,2216],{"class":274},[155,4915,4916,4918,4920,4923],{"class":157,"line":243},[155,4917,4895],{"class":169},[155,4919,611],{"class":274},[155,4921,4922],{"class":614},"new\u002F*",[155,4924,2216],{"class":274},[480,4926,4928],{"id":4927},"customising-release-notes","Customising Release Notes",[31,4930,4931,4932,143],{},"Edit ",[58,4933,4934],{},".github\u002Frelease-drafter.yml",[107,4936,4937],{},[90,4938,4939,143],{},[37,4940,4941],{},"Change Categories",[145,4943,4946],{"className":4837,"code":4944,"filename":4945,"language":4839,"meta":151,"style":151},"categories:\n- title: '🚀 New Features' # Modified emoji and title\n\nlabels:\n- 'feature'\n- 'enhancement'\n- title: '🔧 Improvements' # New category\n\nlabels:\n- 'improvement'\n","release-drafter.yml",[58,4947,4948,4955,4977,4981,4988,4999,5009,5027,5031,5037],{"__ignoreMap":151},[155,4949,4950,4953],{"class":157,"line":158},[155,4951,4952],{"class":586},"categories",[155,4954,4710],{"class":169},[155,4956,4957,4960,4963,4965,4968,4971,4974],{"class":157,"line":173},[155,4958,4959],{"class":169},"-",[155,4961,4962],{"class":586}," title",[155,4964,143],{"class":169},[155,4966,4967],{"class":274}," '",[155,4969,4970],{"class":614},"🚀 New Features",[155,4972,4973],{"class":274},"'",[155,4975,4976],{"class":176}," # Modified emoji and title\n",[155,4978,4979],{"class":157,"line":180},[155,4980,246],{"emptyLinePlaceholder":18},[155,4982,4983,4986],{"class":157,"line":194},[155,4984,4985],{"class":586},"labels",[155,4987,4710],{"class":169},[155,4989,4990,4992,4994,4996],{"class":157,"line":210},[155,4991,4959],{"class":169},[155,4993,4967],{"class":274},[155,4995,4742],{"class":614},[155,4997,4998],{"class":274},"'\n",[155,5000,5001,5003,5005,5007],{"class":157,"line":223},[155,5002,4959],{"class":169},[155,5004,4967],{"class":274},[155,5006,4851],{"class":614},[155,5008,4998],{"class":274},[155,5010,5011,5013,5015,5017,5019,5022,5024],{"class":157,"line":237},[155,5012,4959],{"class":169},[155,5014,4962],{"class":586},[155,5016,143],{"class":169},[155,5018,4967],{"class":274},[155,5020,5021],{"class":614},"🔧 Improvements",[155,5023,4973],{"class":274},[155,5025,5026],{"class":176}," # New category\n",[155,5028,5029],{"class":157,"line":243},[155,5030,246],{"emptyLinePlaceholder":18},[155,5032,5033,5035],{"class":157,"line":249},[155,5034,4985],{"class":586},[155,5036,4710],{"class":169},[155,5038,5039,5041,5043,5046],{"class":157,"line":266},[155,5040,4959],{"class":169},[155,5042,4967],{"class":274},[155,5044,5045],{"class":614},"improvement",[155,5047,4998],{"class":274},[107,5049,5050],{"start":173},[90,5051,5052,143],{},[37,5053,5054],{},"Modify Change Format",[145,5056,5059],{"className":4837,"code":5057,"filename":5058,"language":4839,"meta":151,"style":151},"# Add commit details\nchange-template: '- $TITLE (#$NUMBER)\\n $COMMIT_MESSAGES'\n","template format.yml",[58,5060,5061,5066],{"__ignoreMap":151},[155,5062,5063],{"class":157,"line":158},[155,5064,5065],{"class":176},"# Add commit details\n",[155,5067,5068,5071,5073,5075,5078],{"class":157,"line":173},[155,5069,5070],{"class":586},"change-template",[155,5072,143],{"class":169},[155,5074,4967],{"class":274},[155,5076,5077],{"class":614},"- $TITLE (#$NUMBER)\\n $COMMIT_MESSAGES",[155,5079,4998],{"class":274},[107,5081,5082],{"start":180},[90,5083,5084,143],{},[37,5085,5086],{},"Custom Release Template",[145,5088,5091],{"className":4837,"code":5089,"filename":5090,"language":4839,"meta":151,"style":151},"template: |\n\n## Release v$RESOLVED_VERSION\n### What's Changed\n$CHANGES\n\n### Contributors\n$CONTRIBUTORS\n\n### Additional Notes\n_Released on: $RELEASE_DATE_\n\n","Release Template.yml",[58,5092,5093,5102,5106,5111,5116,5121,5125,5130,5135,5139,5144],{"__ignoreMap":151},[155,5094,5095,5097,5099],{"class":157,"line":158},[155,5096,1405],{"class":586},[155,5098,143],{"class":169},[155,5100,5101],{"class":161}," |\n",[155,5103,5104],{"class":157,"line":173},[155,5105,246],{"emptyLinePlaceholder":18},[155,5107,5108],{"class":157,"line":180},[155,5109,5110],{"class":176},"## Release v$RESOLVED_VERSION\n",[155,5112,5113],{"class":157,"line":194},[155,5114,5115],{"class":176},"### What's Changed\n",[155,5117,5118],{"class":157,"line":210},[155,5119,5120],{"class":614},"$CHANGES\n",[155,5122,5123],{"class":157,"line":223},[155,5124,246],{"emptyLinePlaceholder":18},[155,5126,5127],{"class":157,"line":237},[155,5128,5129],{"class":176},"### Contributors\n",[155,5131,5132],{"class":157,"line":243},[155,5133,5134],{"class":614},"$CONTRIBUTORS\n",[155,5136,5137],{"class":157,"line":249},[155,5138,246],{"emptyLinePlaceholder":18},[155,5140,5141],{"class":157,"line":266},[155,5142,5143],{"class":176},"### Additional Notes\n",[155,5145,5146,5149,5151],{"class":157,"line":280},[155,5147,5148],{"class":586},"_Released on",[155,5150,143],{"class":169},[155,5152,5153],{"class":614}," $RELEASE_DATE_\n",[50,5155,5157],{"id":5156},"branch-naming-convention","Branch Naming Convention",[145,5159,5162],{"className":4773,"code":5160,"filename":5161,"language":2439,"meta":151,"style":151},"\u003Ctype>\u002F\u003Cdescription>\n\nTypes:\n\nfeature\u002F → New features (minor version)\n\nfix\u002F → Bug fixes (minor version)\n\nchore\u002F → Maintenance (patch version)\n\nbreaking\u002F → Breaking changes (major version)\n","Branch Naming Convention.md",[58,5163,5164,5169,5173,5178,5182,5187,5191,5196,5200,5205,5209],{"__ignoreMap":151},[155,5165,5166],{"class":157,"line":158},[155,5167,5168],{"class":165},"\u003Ctype>\u002F\u003Cdescription>\n",[155,5170,5171],{"class":157,"line":173},[155,5172,246],{"emptyLinePlaceholder":18},[155,5174,5175],{"class":157,"line":180},[155,5176,5177],{"class":165},"Types:\n",[155,5179,5180],{"class":157,"line":194},[155,5181,246],{"emptyLinePlaceholder":18},[155,5183,5184],{"class":157,"line":210},[155,5185,5186],{"class":165},"feature\u002F → New features (minor version)\n",[155,5188,5189],{"class":157,"line":223},[155,5190,246],{"emptyLinePlaceholder":18},[155,5192,5193],{"class":157,"line":237},[155,5194,5195],{"class":165},"fix\u002F → Bug fixes (minor version)\n",[155,5197,5198],{"class":157,"line":243},[155,5199,246],{"emptyLinePlaceholder":18},[155,5201,5202],{"class":157,"line":249},[155,5203,5204],{"class":165},"chore\u002F → Maintenance (patch version)\n",[155,5206,5207],{"class":157,"line":266},[155,5208,246],{"emptyLinePlaceholder":18},[155,5210,5211],{"class":157,"line":280},[155,5212,5213],{"class":165},"breaking\u002F → Breaking changes (major version)\n",[31,5215,5216],{},"Examples:",[145,5218,5223],{"className":5219,"code":5220,"filename":5221,"language":5222,"meta":151,"style":151},"language-txt shiki shiki-themes material-theme-lighter one-light one-dark-pro","feature\u002Fuser-authentication\n\nfix\u002Flogin-timeout\n\nchore\u002Fupdate-dependencies\n\nbreaking\u002Fapi-v2\n","Example Branch Name.md","txt",[58,5224,5225,5230,5234,5239,5243,5248,5252],{"__ignoreMap":151},[155,5226,5227],{"class":157,"line":158},[155,5228,5229],{},"feature\u002Fuser-authentication\n",[155,5231,5232],{"class":157,"line":173},[155,5233,246],{"emptyLinePlaceholder":18},[155,5235,5236],{"class":157,"line":180},[155,5237,5238],{},"fix\u002Flogin-timeout\n",[155,5240,5241],{"class":157,"line":194},[155,5242,246],{"emptyLinePlaceholder":18},[155,5244,5245],{"class":157,"line":210},[155,5246,5247],{},"chore\u002Fupdate-dependencies\n",[155,5249,5250],{"class":157,"line":223},[155,5251,246],{"emptyLinePlaceholder":18},[155,5253,5254],{"class":157,"line":237},[155,5255,5256],{},"breaking\u002Fapi-v2\n",[50,5258,5260],{"id":5259},"development-flow","Development Flow",[107,5262,5263],{},[90,5264,5265,143],{},[37,5266,5267],{},"Create Feature Branch",[145,5269,5273],{"className":5270,"code":5271,"language":5272,"meta":151,"style":151},"language-bash shiki shiki-themes material-theme-lighter one-light one-dark-pro","git checkout -b feature\u002Fnew-login\n","bash",[58,5274,5275],{"__ignoreMap":151},[155,5276,5277,5281,5284,5288],{"class":157,"line":158},[155,5278,5280],{"class":5279},"stT07","git",[155,5282,5283],{"class":614}," checkout",[155,5285,5287],{"class":5286},"s6NbW"," -b",[155,5289,5290],{"class":614}," feature\u002Fnew-login\n",[107,5292,5293],{"start":173},[90,5294,5295,143],{},[37,5296,5297],{},"Make Changes and Commit",[145,5299,5301],{"className":5270,"code":5300,"language":5272,"meta":151,"style":151},"git commit -m \"feat: Add OAuth login\"\n\ngit commit -m \"Add password reset\"\n",[58,5302,5303,5320,5324],{"__ignoreMap":151},[155,5304,5305,5307,5310,5313,5315,5318],{"class":157,"line":158},[155,5306,5280],{"class":5279},[155,5308,5309],{"class":614}," commit",[155,5311,5312],{"class":5286}," -m",[155,5314,611],{"class":274},[155,5316,5317],{"class":614},"feat: Add OAuth login",[155,5319,2216],{"class":274},[155,5321,5322],{"class":157,"line":173},[155,5323,246],{"emptyLinePlaceholder":18},[155,5325,5326,5328,5330,5332,5334,5337],{"class":157,"line":180},[155,5327,5280],{"class":5279},[155,5329,5309],{"class":614},[155,5331,5312],{"class":5286},[155,5333,611],{"class":274},[155,5335,5336],{"class":614},"Add password reset",[155,5338,2216],{"class":274},[107,5340,5341],{"start":180},[90,5342,5343,143],{},[37,5344,5345],{},"Create Pull Request",[87,5347,5348,5351],{},[90,5349,5350],{},"Title: \"Add new authentication system\"",[90,5352,5353],{},"Branch will automatically be labeled as \"feature\"",[107,5355,5356],{"start":194},[90,5357,5358,143],{},[37,5359,5360],{},"Merge Process",[87,5362,5363,5366],{},[90,5364,5365],{},"Dev: Creates draft release",[90,5367,5368],{},"Main: Publishes release automatically",[50,5370,5372],{"id":5371},"troubleshooting","Troubleshooting",[480,5374,5376],{"id":5375},"common-issues","Common Issues",[107,5378,5379],{},[90,5380,5381],{},[37,5382,5383],{},"PR Labels Not Applied",[87,5385,5386,5391,5394],{},[90,5387,5388,5389],{},"Verify branch name matches patterns in ",[58,5390,4675],{},[90,5392,5393],{},"Check workflow permissions in GitHub",[90,5395,5396],{},"Verify TOKEN secret is configured",[107,5398,5399],{"start":173},[90,5400,5401],{},[37,5402,5403],{},"Release Not Generated",[87,5405,5406,5414,5417],{},[90,5407,5408,5409,5411,5412,816],{},"Check branch matches workflow trigger (",[58,5410,4697],{}," or ",[58,5413,4717],{},[90,5415,5416],{},"Review workflow run logs for errors",[90,5418,5419,5422,5423,5425,5426,816],{},[58,5420,5421],{},".github"," dir with all files needs to be in both (",[58,5424,4697],{}," and ",[58,5427,4717],{},[107,5429,5430],{"start":180},[90,5431,5432],{},[37,5433,5434],{},"Incorrect Version Numbers",[87,5436,5437,5444,5447],{},[90,5438,5439,5440,5443],{},"Check PR labels match ",[58,5441,5442],{},"version-resolver"," configuration",[90,5445,5446],{},"Verify label application in PR",[90,5448,5449],{},"Review version resolution rules",[50,5451,5453],{"id":5452},"support-future-improvements","Support & Future Improvements",[87,5455,5456,5459],{},[90,5457,5458],{},"Review GitHub Actions logs",[90,5460,5461],{},[2391,5462,5463],{"href":5463,"rel":5464},"https:\u002F\u002Fhelp.shortcut.com\u002Fhc\u002Fen-us\u002Farticles\u002F207540323-Using-Branches-and-Pull-Requests-with-the-Shortcut-VCS-Integrations",[2395],[50,5466,2414],{"id":2413},[2416,5468,5469],{},"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 .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .su13H, html code.shiki .su13H{--shiki-light:#E53935;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sVH1b, html code.shiki .sVH1b{--shiki-light:#39ADB5;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .spZWa, html code.shiki .spZWa{--shiki-light:#91B859;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sQsOY, html code.shiki .sQsOY{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A626A4;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .stT07, html code.shiki .stT07{--shiki-light:#E2931D;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .s6NbW, html code.shiki .s6NbW{--shiki-light:#91B859;--shiki-default:#986801;--shiki-dark:#D19A66}",{"title":151,"searchDepth":173,"depth":173,"links":5471},[5472,5476,5483,5484,5485,5488,5489],{"id":482,"depth":173,"text":483,"children":5473},[5474,5475],{"id":4660,"depth":180,"text":4661},{"id":4681,"depth":180,"text":4682},{"id":4755,"depth":173,"text":4756,"children":5477},[5478,5479,5480,5481,5482],{"id":81,"depth":180,"text":82},{"id":4769,"depth":180,"text":4770},{"id":4823,"depth":180,"text":4824},{"id":4827,"depth":180,"text":4828},{"id":4927,"depth":180,"text":4928},{"id":5156,"depth":173,"text":5157},{"id":5259,"depth":173,"text":5260},{"id":5371,"depth":173,"text":5372,"children":5486},[5487],{"id":5375,"depth":180,"text":5376},{"id":5452,"depth":173,"text":5453},{"id":2413,"depth":173,"text":2414},"2024-12-01",{"slug":5492,"difficulty":5493,"featured":8,"icon":5494,"ogImage":5495,"tags":5497,"topic":5494},"commit-to-release","advanced","devops",{"alt":5496},"Automating GitHub Workflows",[5498,5499,5500],"dev-ops","ci-cd","automation","\u002Farticles\u002Fcommit-to-release",{"title":4634,"description":4639},"articles\u002Fcommit-to-release","0CgyLEDVNVyiRjb1mTYmQYsSlALIaKzf6gvaajtTPYE",{"id":5506,"title":5507,"author":6,"body":5508,"date":6297,"description":5512,"draft":8,"extension":2439,"image":6,"lastmod":6297,"meta":6298,"minRead":6,"navigation":18,"path":6305,"seo":6306,"stem":6307,"__hash__":6308},"articles\u002Farticles\u002Fopen-weather-proxy.md","Nuxt Server-Side Proxy for Open Weather Api",{"type":28,"value":5509,"toc":6287},[5510,5513,5517,5520,5524,5532,5537,5540,5551,5554,5558,5572,5576,5601,5605,5616,6049,6052,6067,6070,6074,6077,6264,6267,6274,6278,6284],[31,5511,5512],{},"A common problem when using open weather api is Cross-Origin Resource Sharing (CORS) issues. This typically happens when you're trying to make an API call from a web application running in a browser, and the browser blocks the request because the API server does not include the necessary CORS headers in its response. The quickest fix is to add a cors header however, as we do not control the api server we can not add a cors header even if we wanted too.",[50,5514,5516],{"id":5515},"solutions","Solutions",[31,5518,5519],{},"There are many ways of resolving this issue but below two are the ones I tested and have worked for me.",[50,5521,5523],{"id":5522},"cors-anywhere","CORS Anywhere",[31,5525,5526,5527,5531],{},"One service I found that worked for me was ",[2391,5528,5523],{"href":5529,"rel":5530},"https:\u002F\u002Fgithub.com\u002FRob--W\u002Fcors-anywhere",[2395]," which adds CORS headers to the proxied request. To use it, we will need to append the hosted NodeJs server url before the api url.",[536,5533,5534],{},[31,5535,5536],{},"Keep in mind that the public instance has a limited number of requests, so it's a good idea to host your own using the CORS Anywhere repository.",[31,5538,5539],{},"For example:",[145,5541,5544],{"className":5219,"code":5542,"language":5222,"meta":5543,"style":151},"https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002Fweather?q=london&APPID={apikey}\n\n","icon=lucide:globe label=\"Request URL\"",[58,5545,5546],{"__ignoreMap":151},[155,5547,5548],{"class":157,"line":158},[155,5549,5550],{},"https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002Fweather?q=london&APPID={apikey}\n",[31,5552,5553],{},"Personally, for small projects, I prefer not to juggle multiple codebases (maybe I'm just a bit lazy 🤣). With NuxtJs, you can get everything done with less fuss and even add some extra features. I'm sure you can do the same with NextJs and serverless functions.",[50,5555,5557],{"id":5556},"nuxt-server-side-proxy","Nuxt Server-Side Proxy",[31,5559,5560,5561,5564,5565,5568,5569],{},"To start create a file in the ",[58,5562,5563],{},"api"," folder on nuxt server directory. I named it ",[58,5566,5567],{},"weather.js",". As nuxt has a file based routing the endpoint will be ",[58,5570,5571],{},"\u002Fapi\u002Fweather",[480,5573,5575],{"id":5574},"file-structure","File structure",[145,5577,5579],{"className":4773,"code":5578,"language":2439,"meta":151,"style":151},"root\n├─ server\n│ ├─ api\n│ │ └─ weather.js\n",[58,5580,5581,5586,5591,5596],{"__ignoreMap":151},[155,5582,5583],{"class":157,"line":158},[155,5584,5585],{"class":165},"root\n",[155,5587,5588],{"class":157,"line":173},[155,5589,5590],{"class":165},"├─ server\n",[155,5592,5593],{"class":157,"line":180},[155,5594,5595],{"class":165},"│ ├─ api\n",[155,5597,5598],{"class":157,"line":194},[155,5599,5600],{"class":165},"│ │ └─ weather.js\n",[480,5602,5604],{"id":5603},"server-side","Server Side",[31,5606,5607,5608,5611,5612,5615],{},"In the code snippet below, I'm setting up a basic API handler to get weather data using the ",[58,5609,5610],{},"fetch"," function. If you're more into ",[58,5613,5614],{},"axios",", feel free to swap it in instead.",[556,5617,5618],{},[145,5619,5622],{"className":2533,"code":5620,"filename":5621,"language":2536,"meta":151,"style":151},"import { getQuery } from 'h3';\n\nexport default defineEventHandler(async (event) => {\n  \u002F\u002F Extract query parameters from the event using getQuery\n  const { query } = getQuery(event);\n\n  \u002F\u002F Access runtime configuration to retrieve the API key for OpenWeatherMap\n  const config = useRuntimeConfig();\n  const apiKey = config.private.openWeatherApiKey;\n\n  \u002F\u002F Construct the API URL for the weather request\n  const apiUrl = `https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002F${query}&units=metric&appid=${apiKey}`;\n\n  try {\n    const response = await fetch(apiUrl);\n    if (!response.ok) {\n      return {\n        statusCode: response.status,\n        body: { message: response.statusText },\n      };\n    }\n    const data = await response.json();\n    return {\n      status: 200,\n      message: 'Weather fetched successfully',\n      data,\n    };\n  } catch (error) {\n    return {\n      statusCode: 500,\n      body: { message: 'Internal Server Error' },\n    };\n  }\n});\n","server\u002Fapi\u002Fweather.js",[58,5623,5624,5645,5649,5674,5679,5702,5706,5711,5727,5750,5754,5759,5798,5802,5809,5834,5854,5861,5877,5900,5905,5909,5931,5937,5949,5965,5972,5977,5993,5999,6011,6033,6037,6041],{"__ignoreMap":151},[155,5625,5626,5628,5630,5633,5635,5637,5639,5641,5643],{"class":157,"line":158},[155,5627,2548],{"class":161},[155,5629,1964],{"class":169},[155,5631,5632],{"class":366}," getQuery",[155,5634,2566],{"class":169},[155,5636,2569],{"class":161},[155,5638,4967],{"class":274},[155,5640,480],{"class":614},[155,5642,4973],{"class":274},[155,5644,207],{"class":169},[155,5646,5647],{"class":157,"line":173},[155,5648,246],{"emptyLinePlaceholder":18},[155,5650,5651,5653,5655,5658,5660,5663,5665,5668,5670,5672],{"class":157,"line":180},[155,5652,569],{"class":161},[155,5654,573],{"class":572},[155,5656,5657],{"class":576}," defineEventHandler",[155,5659,363],{"class":165},[155,5661,5662],{"class":2610},"async",[155,5664,2674],{"class":169},[155,5666,5667],{"class":2619},"event",[155,5669,816],{"class":169},[155,5671,2664],{"class":2610},[155,5673,191],{"class":169},[155,5675,5676],{"class":157,"line":194},[155,5677,5678],{"class":176},"  \u002F\u002F Extract query parameters from the event using getQuery\n",[155,5680,5681,5683,5685,5688,5690,5692,5694,5696,5698,5700],{"class":157,"line":210},[155,5682,2629],{"class":2610},[155,5684,1964],{"class":169},[155,5686,5687],{"class":2632}," query",[155,5689,2566],{"class":169},[155,5691,2637],{"class":2636},[155,5693,5632],{"class":576},[155,5695,363],{"class":1983},[155,5697,5667],{"class":366},[155,5699,816],{"class":1983},[155,5701,207],{"class":169},[155,5703,5704],{"class":157,"line":223},[155,5705,246],{"emptyLinePlaceholder":18},[155,5707,5708],{"class":157,"line":237},[155,5709,5710],{"class":176},"  \u002F\u002F Access runtime configuration to retrieve the API key for OpenWeatherMap\n",[155,5712,5713,5715,5718,5720,5723,5725],{"class":157,"line":243},[155,5714,2629],{"class":2610},[155,5716,5717],{"class":2632}," config",[155,5719,2637],{"class":2636},[155,5721,5722],{"class":576}," useRuntimeConfig",[155,5724,2642],{"class":1983},[155,5726,207],{"class":169},[155,5728,5729,5731,5734,5736,5738,5740,5743,5745,5748],{"class":157,"line":249},[155,5730,2629],{"class":2610},[155,5732,5733],{"class":2632}," apiKey",[155,5735,2637],{"class":2636},[155,5737,5717],{"class":2677},[155,5739,1245],{"class":169},[155,5741,5742],{"class":2721},"private",[155,5744,1245],{"class":169},[155,5746,5747],{"class":366},"openWeatherApiKey",[155,5749,207],{"class":169},[155,5751,5752],{"class":157,"line":266},[155,5753,246],{"emptyLinePlaceholder":18},[155,5755,5756],{"class":157,"line":280},[155,5757,5758],{"class":176},"  \u002F\u002F Construct the API URL for the weather request\n",[155,5760,5761,5763,5766,5768,5771,5774,5778,5781,5783,5786,5788,5791,5793,5796],{"class":157,"line":292},[155,5762,2629],{"class":2610},[155,5764,5765],{"class":2632}," apiUrl",[155,5767,2637],{"class":2636},[155,5769,5770],{"class":274}," `",[155,5772,5773],{"class":614},"https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002F",[155,5775,5777],{"class":5776},"ssEfx","${",[155,5779,5780],{"class":366},"query",[155,5782,813],{"class":5776},[155,5784,5785],{"class":614},"&units=metric&appid=",[155,5787,5777],{"class":5776},[155,5789,5790],{"class":366},"apiKey",[155,5792,813],{"class":5776},[155,5794,5795],{"class":274},"`",[155,5797,207],{"class":169},[155,5799,5800],{"class":157,"line":304},[155,5801,246],{"emptyLinePlaceholder":18},[155,5803,5804,5807],{"class":157,"line":321},[155,5805,5806],{"class":161},"  try",[155,5808,191],{"class":169},[155,5810,5811,5814,5817,5819,5822,5825,5827,5830,5832],{"class":157,"line":337},[155,5812,5813],{"class":2610},"    const",[155,5815,5816],{"class":2632}," response",[155,5818,2637],{"class":2636},[155,5820,5821],{"class":161}," await",[155,5823,5824],{"class":576}," fetch",[155,5826,363],{"class":1983},[155,5828,5829],{"class":366},"apiUrl",[155,5831,816],{"class":1983},[155,5833,207],{"class":169},[155,5835,5836,5838,5840,5842,5845,5847,5850,5852],{"class":157,"line":351},[155,5837,2671],{"class":161},[155,5839,2674],{"class":1983},[155,5841,2992],{"class":2636},[155,5843,5844],{"class":2677},"response",[155,5846,1245],{"class":169},[155,5848,5849],{"class":366},"ok",[155,5851,2685],{"class":1983},[155,5853,170],{"class":169},[155,5855,5856,5859],{"class":157,"line":373},[155,5857,5858],{"class":161},"      return",[155,5860,191],{"class":169},[155,5862,5863,5866,5868,5870,5872,5875],{"class":157,"line":394},[155,5864,5865],{"class":586},"        statusCode",[155,5867,143],{"class":590},[155,5869,5816],{"class":2677},[155,5871,1245],{"class":169},[155,5873,5874],{"class":366},"status",[155,5876,621],{"class":169},[155,5878,5879,5882,5884,5886,5889,5891,5893,5895,5898],{"class":157,"line":406},[155,5880,5881],{"class":586},"        body",[155,5883,143],{"class":590},[155,5885,1964],{"class":169},[155,5887,5888],{"class":586}," message",[155,5890,143],{"class":590},[155,5892,5816],{"class":2677},[155,5894,1245],{"class":169},[155,5896,5897],{"class":366},"statusText",[155,5899,1970],{"class":169},[155,5901,5902],{"class":157,"line":428},[155,5903,5904],{"class":169},"      };\n",[155,5906,5907],{"class":157,"line":433},[155,5908,2810],{"class":169},[155,5910,5911,5913,5916,5918,5920,5922,5924,5927,5929],{"class":157,"line":438},[155,5912,5813],{"class":2610},[155,5914,5915],{"class":2632}," data",[155,5917,2637],{"class":2636},[155,5919,5821],{"class":161},[155,5921,5816],{"class":2677},[155,5923,1245],{"class":169},[155,5925,5926],{"class":576},"json",[155,5928,2642],{"class":1983},[155,5930,207],{"class":169},[155,5932,5933,5935],{"class":157,"line":456},[155,5934,3277],{"class":161},[155,5936,191],{"class":169},[155,5938,5939,5942,5944,5947],{"class":157,"line":470},[155,5940,5941],{"class":586},"      status",[155,5943,143],{"class":590},[155,5945,5946],{"class":231}," 200",[155,5948,621],{"class":169},[155,5950,5951,5954,5956,5958,5961,5963],{"class":157,"line":475},[155,5952,5953],{"class":586},"      message",[155,5955,143],{"class":590},[155,5957,4967],{"class":274},[155,5959,5960],{"class":614},"Weather fetched successfully",[155,5962,4973],{"class":274},[155,5964,621],{"class":169},[155,5966,5967,5970],{"class":157,"line":810},[155,5968,5969],{"class":366},"      data",[155,5971,621],{"class":169},[155,5973,5974],{"class":157,"line":1152},[155,5975,5976],{"class":169},"    };\n",[155,5978,5979,5981,5984,5986,5989,5991],{"class":157,"line":1167},[155,5980,2903],{"class":169},[155,5982,5983],{"class":161}," catch",[155,5985,2674],{"class":1983},[155,5987,5988],{"class":366},"error",[155,5990,2685],{"class":1983},[155,5992,170],{"class":169},[155,5994,5995,5997],{"class":157,"line":1182},[155,5996,3277],{"class":161},[155,5998,191],{"class":169},[155,6000,6001,6004,6006,6009],{"class":157,"line":1198},[155,6002,6003],{"class":586},"      statusCode",[155,6005,143],{"class":590},[155,6007,6008],{"class":231}," 500",[155,6010,621],{"class":169},[155,6012,6013,6016,6018,6020,6022,6024,6026,6029,6031],{"class":157,"line":1203},[155,6014,6015],{"class":586},"      body",[155,6017,143],{"class":590},[155,6019,1964],{"class":169},[155,6021,5888],{"class":586},[155,6023,143],{"class":590},[155,6025,4967],{"class":274},[155,6027,6028],{"class":614},"Internal Server Error",[155,6030,4973],{"class":274},[155,6032,1970],{"class":169},[155,6034,6035],{"class":157,"line":1211},[155,6036,5976],{"class":169},[155,6038,6039],{"class":157,"line":1216},[155,6040,240],{"class":169},[155,6042,6043,6045,6047],{"class":157,"line":1221},[155,6044,813],{"class":169},[155,6046,816],{"class":165},[155,6048,207],{"class":169},[31,6050,6051],{},"One cool thing I noticed about using this setup is that it hides both the API URL and the API key.",[145,6053,6055],{"className":5219,"code":6054,"language":5222,"meta":151,"style":151},"Original URL: https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002Fweather?q=London&units=metric&appid=${apiKey}\nMasked URL: https:\u002F\u002Fatmosdev.netlify.app\u002Fapi\u002Fweather?query=weather?q=London\n",[58,6056,6057,6062],{"__ignoreMap":151},[155,6058,6059],{"class":157,"line":158},[155,6060,6061],{},"Original URL: https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\u002Fweather?q=London&units=metric&appid=${apiKey}\n",[155,6063,6064],{"class":157,"line":173},[155,6065,6066],{},"Masked URL: https:\u002F\u002Fatmosdev.netlify.app\u002Fapi\u002Fweather?query=weather?q=London\n",[31,6068,6069],{},"So, not only does it simplify the URL, but it also keeps your API key under wraps.",[480,6071,6073],{"id":6072},"client-side","Client Side",[31,6075,6076],{},"Now, all you need to do is pass in the query and fetch the data on the client side, and you're good to go!",[145,6078,6081],{"className":2533,"code":6079,"filename":6080,"language":2536,"meta":151,"style":151},"const getWeather = async (event) => {\n  try {\n    const response = await $fetch(`\u002Fapi\u002Fweather?query=London`);\n    if (response.status === 200) {\n      weather.value = response.data;\n    } else {\n      console.error(\"No data returned from the API\");\n    }\n  } catch (error) {\n    console.error(\"Error fetching weather data:\", error);\n  }\n};\n","git-request.js",[58,6082,6083,6105,6111,6137,6158,6178,6188,6210,6214,6228,6255,6259],{"__ignoreMap":151},[155,6084,6085,6087,6090,6092,6095,6097,6099,6101,6103],{"class":157,"line":158},[155,6086,3922],{"class":2610},[155,6088,6089],{"class":2655}," getWeather",[155,6091,2637],{"class":2636},[155,6093,6094],{"class":2610}," async",[155,6096,2674],{"class":169},[155,6098,5667],{"class":2619},[155,6100,816],{"class":169},[155,6102,2664],{"class":2610},[155,6104,191],{"class":169},[155,6106,6107,6109],{"class":157,"line":173},[155,6108,5806],{"class":161},[155,6110,191],{"class":169},[155,6112,6113,6115,6117,6119,6121,6124,6126,6128,6131,6133,6135],{"class":157,"line":180},[155,6114,5813],{"class":2610},[155,6116,5816],{"class":2632},[155,6118,2637],{"class":2636},[155,6120,5821],{"class":161},[155,6122,6123],{"class":576}," $fetch",[155,6125,363],{"class":1983},[155,6127,5795],{"class":274},[155,6129,6130],{"class":614},"\u002Fapi\u002Fweather?query=London",[155,6132,5795],{"class":274},[155,6134,816],{"class":1983},[155,6136,207],{"class":169},[155,6138,6139,6141,6143,6145,6147,6149,6152,6154,6156],{"class":157,"line":194},[155,6140,2671],{"class":161},[155,6142,2674],{"class":1983},[155,6144,5844],{"class":2677},[155,6146,1245],{"class":169},[155,6148,5874],{"class":366},[155,6150,6151],{"class":2636}," ===",[155,6153,5946],{"class":231},[155,6155,2685],{"class":1983},[155,6157,170],{"class":169},[155,6159,6160,6163,6165,6167,6169,6171,6173,6176],{"class":157,"line":210},[155,6161,6162],{"class":2677},"      weather",[155,6164,1245],{"class":169},[155,6166,2682],{"class":366},[155,6168,2637],{"class":2636},[155,6170,5816],{"class":2677},[155,6172,1245],{"class":169},[155,6174,6175],{"class":366},"data",[155,6177,207],{"class":169},[155,6179,6180,6183,6186],{"class":157,"line":223},[155,6181,6182],{"class":169},"    }",[155,6184,6185],{"class":161}," else",[155,6187,191],{"class":169},[155,6189,6190,6193,6195,6197,6199,6201,6204,6206,6208],{"class":157,"line":237},[155,6191,6192],{"class":2677},"      console",[155,6194,1245],{"class":169},[155,6196,5988],{"class":576},[155,6198,363],{"class":1983},[155,6200,618],{"class":274},[155,6202,6203],{"class":614},"No data returned from the API",[155,6205,618],{"class":274},[155,6207,816],{"class":1983},[155,6209,207],{"class":169},[155,6211,6212],{"class":157,"line":243},[155,6213,2810],{"class":169},[155,6215,6216,6218,6220,6222,6224,6226],{"class":157,"line":249},[155,6217,2903],{"class":169},[155,6219,5983],{"class":161},[155,6221,2674],{"class":1983},[155,6223,5988],{"class":2894},[155,6225,2685],{"class":1983},[155,6227,170],{"class":169},[155,6229,6230,6233,6235,6237,6239,6241,6244,6246,6248,6251,6253],{"class":157,"line":266},[155,6231,6232],{"class":2677},"    console",[155,6234,1245],{"class":169},[155,6236,5988],{"class":576},[155,6238,363],{"class":1983},[155,6240,618],{"class":274},[155,6242,6243],{"class":614},"Error fetching weather data:",[155,6245,618],{"class":274},[155,6247,1818],{"class":169},[155,6249,6250],{"class":2894}," error",[155,6252,816],{"class":1983},[155,6254,207],{"class":169},[155,6256,6257],{"class":157,"line":280},[155,6258,240],{"class":169},[155,6260,6261],{"class":157,"line":292},[155,6262,6263],{"class":169},"};\n",[31,6265,6266],{},"Here is the API response data",[31,6268,6269],{},[6270,6271],"img",{"alt":6272,"src":6273},"weather api sample response","https:\u002F\u002Fik.imagekit.io\u002F3mh13v7xv4\u002Farticles\u002Fproxy-response.png?updatedAt=1723345992038",[50,6275,6277],{"id":6276},"deployed-app","Deployed App",[31,6279,6280],{},[2391,6281,6282],{"href":6282,"rel":6283},"https:\u002F\u002Fatmosapp.netlify.app\u002F",[2395],[2416,6285,6286],{},"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 .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sQsOY, html code.shiki .sQsOY{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A626A4;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .s8dPH, html code.shiki .s8dPH{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .sVH1b, html code.shiki .sVH1b{--shiki-light:#39ADB5;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .spZWa, html code.shiki .spZWa{--shiki-light:#91B859;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sH50Z, html code.shiki .sH50Z{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#E45649;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .spnjr, html code.shiki .spnjr{--shiki-light:#6182B8;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .sJvVP, html code.shiki .sJvVP{--shiki-light:#9C3EDA;--shiki-default:#A626A4;--shiki-dark:#C678DD}html pre.shiki code .s5f2p, html code.shiki .s5f2p{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#383A42;--shiki-default-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .sMm83, html code.shiki .sMm83{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#E5C07B}html pre.shiki code .syPST, html code.shiki .syPST{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .sA0eD, html code.shiki .sA0eD{--shiki-light:#E53935;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .scCn_, html code.shiki .scCn_{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E5C07B}html pre.shiki code .sDC5J, html code.shiki .sDC5J{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E5C07B}html pre.shiki code .ssEfx, html code.shiki .ssEfx{--shiki-light:#39ADB5;--shiki-default:#CA1243;--shiki-dark:#C678DD}html pre.shiki code .su13H, html code.shiki .su13H{--shiki-light:#E53935;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .saKOp, html code.shiki .saKOp{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#ABB2BF}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .svfkx, html code.shiki .svfkx{--shiki-light:#90A4AE;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .sWjah, html code.shiki .sWjah{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E06C75}",{"title":151,"searchDepth":173,"depth":173,"links":6288},[6289,6290,6291,6296],{"id":5515,"depth":173,"text":5516},{"id":5522,"depth":173,"text":5523},{"id":5556,"depth":173,"text":5557,"children":6292},[6293,6294,6295],{"id":5574,"depth":180,"text":5575},{"id":5603,"depth":180,"text":5604},{"id":6072,"depth":180,"text":6073},{"id":6276,"depth":173,"text":6277},"2024-08-11",{"slug":6299,"difficulty":6300,"icon":2443,"ogImage":6301,"tags":6303,"topic":2443},"open-weather-proxy","beginner",{"alt":6302,"color":6},"Nuxt Proxy Server for Open Weather",[2443,5563,6304],"proxy-server","\u002Farticles\u002Fopen-weather-proxy",{"title":5507,"description":5512},"articles\u002Fopen-weather-proxy","OZtZ9GAMVbyyszVj8tlet23mvrnXkIH3VHGJiU_TR8M",{"id":6310,"title":6311,"author":6,"body":6312,"date":6688,"description":6320,"draft":8,"extension":2439,"image":6,"lastmod":6688,"meta":6689,"minRead":6,"navigation":18,"path":6696,"seo":6697,"stem":6698,"__hash__":6699},"articles\u002Farticles\u002Fprimevue-style-override.md","PrimeVue Style Override",{"type":28,"value":6313,"toc":6679},[6314,6318,6321,6325,6332,6336,6473,6487,6491,6579,6582,6586,6663,6666,6670,6676],[50,6315,6317],{"id":6316},"intro","Intro",[31,6319,6320],{},"The PrimeVue UI component library provides a wide range of components with their own design. In some cases, we need to customize them to better suit our own needs. There are different ways we can override the default styles of PrimeVue, but we need to keep a few things in mind to reduce headaches later down the line 😅.",[50,6322,6324],{"id":6323},"examples","Examples",[31,6326,6327,6328,6331],{},"When working with CSS, we sometimes use the ",[58,6329,6330],{},"!important"," rule to override existing styles. Although it might get the job done in most cases, it can also create a lot of style conflicts as a project grows. Therefore, custom styles should be put into scoped styles, not in a global style. Funny enough, sometimes even scoped styles don't work 😝. But there are still other workarounds we know but might have forgotten about. I wanted to give a refresher.",[480,6333,6335],{"id":6334},"scoped","Scoped",[145,6337,6342],{"className":6338,"code":6339,"filename":6340,"language":6341,"meta":151,"style":151},"language-scss shiki shiki-themes material-theme-lighter one-light one-dark-pro","\u003Cstyle scoped>\n\u002F\u002F Primarily works for single element components\n.p-inputtext {\n  background-color: #f0f4f8;\n  border: 2px solid transparent;\n  border-radius: 5px;\n  padding: 10px 15px;\n  font-size: 16px;\n  color: #333;\n}\n\u003C\u002Fstyle>\n","main.scss","scss",[58,6343,6344,6354,6359,6368,6382,6402,6415,6434,6448,6461,6465],{"__ignoreMap":151},[155,6345,6346,6348,6351],{"class":157,"line":158},[155,6347,1402],{"class":165},[155,6349,2416],{"class":6350},"sJvnO",[155,6352,6353],{"class":165}," scoped>\n",[155,6355,6356],{"class":157,"line":173},[155,6357,6358],{"class":176},"\u002F\u002F Primarily works for single element components\n",[155,6360,6361,6363,6366],{"class":157,"line":180},[155,6362,1245],{"class":183},[155,6364,6365],{"class":187},"p-inputtext",[155,6367,191],{"class":169},[155,6369,6370,6372,6374,6376,6380],{"class":157,"line":194},[155,6371,1259],{"class":197},[155,6373,143],{"class":169},[155,6375,4054],{"class":183},[155,6377,6379],{"class":6378},"stV9d","f0f4f8",[155,6381,207],{"class":169},[155,6383,6384,6387,6389,6392,6394,6397,6400],{"class":157,"line":210},[155,6385,6386],{"class":197},"  border",[155,6388,143],{"class":169},[155,6390,6391],{"class":231}," 2",[155,6393,316],{"class":315},[155,6395,6396],{"class":203}," solid",[155,6398,6399],{"class":203}," transparent",[155,6401,207],{"class":169},[155,6403,6404,6406,6408,6411,6413],{"class":157,"line":223},[155,6405,1790],{"class":197},[155,6407,143],{"class":169},[155,6409,6410],{"class":231}," 5",[155,6412,316],{"class":315},[155,6414,207],{"class":169},[155,6416,6417,6420,6422,6425,6427,6430,6432],{"class":157,"line":237},[155,6418,6419],{"class":197},"  padding",[155,6421,143],{"class":169},[155,6423,6424],{"class":231}," 10",[155,6426,316],{"class":315},[155,6428,6429],{"class":231}," 15",[155,6431,316],{"class":315},[155,6433,207],{"class":169},[155,6435,6436,6439,6441,6444,6446],{"class":157,"line":243},[155,6437,6438],{"class":197},"  font-size",[155,6440,143],{"class":169},[155,6442,6443],{"class":231}," 16",[155,6445,316],{"class":315},[155,6447,207],{"class":169},[155,6449,6450,6452,6454,6456,6459],{"class":157,"line":249},[155,6451,2234],{"class":197},[155,6453,143],{"class":169},[155,6455,4054],{"class":183},[155,6457,6458],{"class":6378},"333",[155,6460,207],{"class":169},[155,6462,6463],{"class":157,"line":266},[155,6464,478],{"class":169},[155,6466,6467,6469,6471],{"class":157,"line":280},[155,6468,1609],{"class":165},[155,6470,2416],{"class":6350},[155,6472,1408],{"class":165},[31,6474,6475,6476,6479,6480,6483,6484,6486],{},"In Vue, we can use a selector called ",[58,6477,6478],{},":deep()"," to override child component styles when they have nested elements, such as the ",[58,6481,6482],{},"TabView"," component. If you want to change the tab header text color, just putting it into scoped styles will not work. We need to wrap the class with the ",[58,6485,6478],{}," selector to override the style.",[480,6488,6490],{"id":6489},"deep-selector","Deep Selector",[145,6492,6494],{"className":6338,"code":6493,"filename":6340,"language":6341,"meta":151,"style":151},"\u003Cstyle scoped>\n.p-tabview-header a {\n  color: brown; \u002F\u002F won't have any effect\n}\n\n:deep(.p-tabview-header a) {\n  color: brown; \u002F\u002F will change the color to brown\n}\n\u003C\u002Fstyle>\n",[58,6495,6496,6504,6516,6531,6535,6539,6554,6567,6571],{"__ignoreMap":151},[155,6497,6498,6500,6502],{"class":157,"line":158},[155,6499,1402],{"class":165},[155,6501,2416],{"class":6350},[155,6503,6353],{"class":165},[155,6505,6506,6508,6511,6514],{"class":157,"line":173},[155,6507,1245],{"class":183},[155,6509,6510],{"class":187},"p-tabview-header",[155,6512,6513],{"class":6350}," a",[155,6515,191],{"class":169},[155,6517,6518,6520,6522,6526,6528],{"class":157,"line":180},[155,6519,2234],{"class":197},[155,6521,143],{"class":169},[155,6523,6525],{"class":6524},"soO3g"," brown",[155,6527,2764],{"class":169},[155,6529,6530],{"class":176}," \u002F\u002F won't have any effect\n",[155,6532,6533],{"class":157,"line":194},[155,6534,478],{"class":169},[155,6536,6537],{"class":157,"line":210},[155,6538,246],{"emptyLinePlaceholder":18},[155,6540,6541,6544,6546,6548,6550,6552],{"class":157,"line":223},[155,6542,6543],{"class":165},":deep(",[155,6545,1245],{"class":183},[155,6547,6510],{"class":187},[155,6549,6513],{"class":6350},[155,6551,2685],{"class":165},[155,6553,170],{"class":169},[155,6555,6556,6558,6560,6562,6564],{"class":157,"line":237},[155,6557,2234],{"class":197},[155,6559,143],{"class":169},[155,6561,6525],{"class":6524},[155,6563,2764],{"class":169},[155,6565,6566],{"class":176}," \u002F\u002F will change the color to brown\n",[155,6568,6569],{"class":157,"line":243},[155,6570,478],{"class":169},[155,6572,6573,6575,6577],{"class":157,"line":249},[155,6574,1609],{"class":165},[155,6576,2416],{"class":6350},[155,6578,1408],{"class":165},[31,6580,6581],{},"However, there are some components where even these two methods won't work. The reason behind it is that those components are appended to the body. We need to add a custom class and then apply the style so that it doesn't conflict with other components. An important note is to maintain specificity, or else it won't work.",[480,6583,6585],{"id":6584},"custom-class","Custom Class",[145,6587,6589],{"className":6338,"code":6588,"filename":6340,"language":6341,"meta":151,"style":151},"\u003Cstyle lang=\"scss\">\n.custom-modal {\n  background-color: red; \u002F\u002F won't have any effect\n}\n.custom-modal .p-dialog-content {\n  background-color: red;\n}\n\u003C\u002Fstyle>\n",[58,6590,6591,6600,6609,6623,6627,6641,6651,6655],{"__ignoreMap":151},[155,6592,6593,6595,6597],{"class":157,"line":158},[155,6594,1402],{"class":165},[155,6596,2416],{"class":6350},[155,6598,6599],{"class":165}," lang=\"scss\">\n",[155,6601,6602,6604,6607],{"class":157,"line":173},[155,6603,1245],{"class":183},[155,6605,6606],{"class":187},"custom-modal",[155,6608,191],{"class":169},[155,6610,6611,6613,6615,6619,6621],{"class":157,"line":180},[155,6612,1259],{"class":197},[155,6614,143],{"class":169},[155,6616,6618],{"class":6617},"sUz_E"," red",[155,6620,2764],{"class":169},[155,6622,6530],{"class":176},[155,6624,6625],{"class":157,"line":194},[155,6626,478],{"class":169},[155,6628,6629,6631,6633,6636,6639],{"class":157,"line":210},[155,6630,1245],{"class":183},[155,6632,6606],{"class":187},[155,6634,6635],{"class":183}," .",[155,6637,6638],{"class":187},"p-dialog-content",[155,6640,191],{"class":169},[155,6642,6643,6645,6647,6649],{"class":157,"line":223},[155,6644,1259],{"class":197},[155,6646,143],{"class":169},[155,6648,6618],{"class":6617},[155,6650,207],{"class":169},[155,6652,6653],{"class":157,"line":237},[155,6654,478],{"class":169},[155,6656,6657,6659,6661],{"class":157,"line":243},[155,6658,1609],{"class":165},[155,6660,2416],{"class":6350},[155,6662,1408],{"class":165},[31,6664,6665],{},"All the above methods can be used with any component library. Lastly, PrimeVue provides a pass-through method where we can easily pass in styles and PrimeFlex classes to customize the components based on our needs.",[50,6667,6669],{"id":6668},"explanation","Explanation",[31,6671,6672],{},[2391,6673,6674],{"href":6674,"rel":6675},"https:\u002F\u002Fprimevue.org\u002Fpassthrough\u002F",[2395],[2416,6677,6678],{},"html pre.shiki code .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sJvnO, html code.shiki .sJvnO{--shiki-light:#E2931D;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .svDm9, html code.shiki .svDm9{--shiki-light:#39ADB5;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .s6wAS, html code.shiki .s6wAS{--shiki-light:#E2931D;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sGRuu, html code.shiki .sGRuu{--shiki-light:#8796B0;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .stV9d, html code.shiki .stV9d{--shiki-light:#90A4AE;--shiki-default:#0184BC;--shiki-dark:#D19A66}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sLhkd, html code.shiki .sLhkd{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#E06C75}html pre.shiki code .sngOx, html code.shiki .sngOx{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#D19A66}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 .soO3g, html code.shiki .soO3g{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#ABB2BF}html pre.shiki code .sUz_E, html code.shiki .sUz_E{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#D19A66}",{"title":151,"searchDepth":173,"depth":173,"links":6680},[6681,6682,6687],{"id":6316,"depth":173,"text":6317},{"id":6323,"depth":173,"text":6324,"children":6683},[6684,6685,6686],{"id":6334,"depth":180,"text":6335},{"id":6489,"depth":180,"text":6490},{"id":6584,"depth":180,"text":6585},{"id":6668,"depth":173,"text":6669},"2024-08-03",{"slug":6690,"difficulty":6300,"icon":1395,"ogImage":6691,"tags":6692,"topic":6695},"primevue-style-override",{"alt":6311},[6341,6693,6694],"prime-vue","tips-tricks","primevue","\u002Farticles\u002Fprimevue-style-override",{"title":6311,"description":6320},"articles\u002Fprimevue-style-override","KcEFsHaT1b6ELNK_7mWaOf3G3gZXkuUCD71puwHeM9I",{"id":6701,"title":6702,"author":6,"body":6703,"date":7398,"description":7399,"draft":8,"extension":2439,"image":6,"lastmod":7398,"meta":7400,"minRead":6,"navigation":18,"path":7406,"seo":7407,"stem":7408,"__hash__":7409},"articles\u002Farticles\u002Funique-css-custom-property.md","Unique approach of CSS custom property great flexibility and modularity",{"type":28,"value":6704,"toc":7390},[6705,6719,6723,6726,6879,6882,6888,6891,6992,7006,7170,7173,7178,7350,7355,7358,7362,7365,7371,7377,7381,7387],[31,6706,6707,6708,5425,6711,6714,6715,6718],{},"CSS Custom Properties offers great flexibility and modularity to a stylesheet. Allows developers to centralize values and simplify maintaining and updating multiple elements simultaneously across the entire project. Custom properties can go from simple ",[58,6709,6710],{},"color",[58,6712,6713],{},"shadow"," values to dynamic changes to styles based on user interactions or other events using JavaScript. Recently, I came across an example by ",[37,6716,6717],{},"Lea Verou"," that used custom property in a way that was quite unique. So, let's see the approach.",[50,6720,6722],{"id":6721},"introduction","Introduction",[31,6724,6725],{},"Suppose we have multiple cards with different background colors, button variants, and hover effects like the image above. Typically, the best approach will be to have a class for the card element with all the default styling and then use individual classes for the different cards and change the colors one by one, as shown in the example below.",[145,6727,6729],{"className":147,"code":6728,"filename":149,"language":150,"meta":151,"style":151},".card {\n  position: relative;\n  min-height: 200px;\n  background-color: #f0f0f0;\n  padding: 20px;\n  border-radius: 5px;\n  background-color: white;\n  display: flex;\n  flex-direction: column;\n  gap: 10px;\n\n  &.js {\n    background-color: #fefce8;\n  }\n}\n",[58,6730,6731,6740,6750,6763,6776,6789,6801,6812,6824,6836,6849,6853,6858,6871,6875],{"__ignoreMap":151},[155,6732,6733,6735,6738],{"class":157,"line":158},[155,6734,1245],{"class":183},[155,6736,6737],{"class":187},"card",[155,6739,191],{"class":169},[155,6741,6742,6744,6746,6748],{"class":157,"line":173},[155,6743,1649],{"class":197},[155,6745,143],{"class":169},[155,6747,204],{"class":203},[155,6749,207],{"class":169},[155,6751,6752,6755,6757,6759,6761],{"class":157,"line":180},[155,6753,6754],{"class":197},"  min-height",[155,6756,143],{"class":169},[155,6758,5946],{"class":231},[155,6760,316],{"class":315},[155,6762,207],{"class":169},[155,6764,6765,6767,6769,6771,6774],{"class":157,"line":194},[155,6766,1259],{"class":197},[155,6768,143],{"class":169},[155,6770,4054],{"class":183},[155,6772,6773],{"class":6378},"f0f0f0",[155,6775,207],{"class":169},[155,6777,6778,6780,6782,6785,6787],{"class":157,"line":210},[155,6779,6419],{"class":197},[155,6781,143],{"class":169},[155,6783,6784],{"class":231}," 20",[155,6786,316],{"class":315},[155,6788,207],{"class":169},[155,6790,6791,6793,6795,6797,6799],{"class":157,"line":223},[155,6792,1790],{"class":197},[155,6794,143],{"class":169},[155,6796,6410],{"class":231},[155,6798,316],{"class":315},[155,6800,207],{"class":169},[155,6802,6803,6805,6807,6810],{"class":157,"line":237},[155,6804,1259],{"class":197},[155,6806,143],{"class":169},[155,6808,6809],{"class":6617}," white",[155,6811,207],{"class":169},[155,6813,6814,6817,6819,6822],{"class":157,"line":243},[155,6815,6816],{"class":197},"  display",[155,6818,143],{"class":169},[155,6820,6821],{"class":203}," flex",[155,6823,207],{"class":169},[155,6825,6826,6829,6831,6834],{"class":157,"line":249},[155,6827,6828],{"class":197},"  flex-direction",[155,6830,143],{"class":169},[155,6832,6833],{"class":203}," column",[155,6835,207],{"class":169},[155,6837,6838,6841,6843,6845,6847],{"class":157,"line":266},[155,6839,6840],{"class":197},"  gap",[155,6842,143],{"class":169},[155,6844,6424],{"class":231},[155,6846,316],{"class":315},[155,6848,207],{"class":169},[155,6850,6851],{"class":157,"line":280},[155,6852,246],{"emptyLinePlaceholder":18},[155,6854,6855],{"class":157,"line":292},[155,6856,6857],{"class":165},"  &.js {\n",[155,6859,6860,6862,6864,6866,6869],{"class":157,"line":304},[155,6861,354],{"class":197},[155,6863,143],{"class":169},[155,6865,4054],{"class":183},[155,6867,6868],{"class":6378},"fefce8",[155,6870,207],{"class":169},[155,6872,6873],{"class":157,"line":321},[155,6874,240],{"class":169},[155,6876,6877],{"class":157,"line":337},[155,6878,478],{"class":165},[31,6880,6881],{},"However, there is a much easier way you can achieve the same result. You need to first understand the concept, which may not seem simple at first, but it makes more sense when you understand it.",[50,6883,6885],{"id":6884},"pseudo-private-custom-property-approach",[37,6886,6887],{},"Pseudo-private custom property approach:",[31,6889,6890],{},"The aim is to mimic the behaviour of private properties in JavaScript within the realm of CSS. The analogy drawn here is to JavaScript, where developers used naming conventions (like underscores or other prefixes) to signify private properties before introducing actual private properties in the language. Similarly, in CSS, this creates a distinction between the properties used internally and exposed. Although the private custom properties aren’t private in practicality, they are put in place for a clear distinction.",[145,6892,6894],{"className":147,"code":6893,"filename":149,"language":150,"meta":151,"style":151},".card {\n  --_background: var(--background, white);\n  --_border: var(--border, #333);\n  --_button-hover: var(--button, #333);\n  --_shadow: var(--shadow, white);\n}\n",[58,6895,6896,6904,6924,6946,6968,6988],{"__ignoreMap":151},[155,6897,6898,6900,6902],{"class":157,"line":158},[155,6899,1245],{"class":183},[155,6901,6737],{"class":187},[155,6903,191],{"class":169},[155,6905,6906,6909,6911,6913,6915,6918,6920,6922],{"class":157,"line":173},[155,6907,6908],{"class":366},"  --_background",[155,6910,143],{"class":169},[155,6912,360],{"class":359},[155,6914,363],{"class":169},[155,6916,6917],{"class":366},"--background",[155,6919,1818],{"class":169},[155,6921,6809],{"class":6617},[155,6923,370],{"class":169},[155,6925,6926,6929,6931,6933,6935,6938,6940,6942,6944],{"class":157,"line":180},[155,6927,6928],{"class":366},"  --_border",[155,6930,143],{"class":169},[155,6932,360],{"class":359},[155,6934,363],{"class":169},[155,6936,6937],{"class":366},"--border",[155,6939,1818],{"class":169},[155,6941,4054],{"class":183},[155,6943,6458],{"class":6378},[155,6945,370],{"class":169},[155,6947,6948,6951,6953,6955,6957,6960,6962,6964,6966],{"class":157,"line":194},[155,6949,6950],{"class":366},"  --_button-hover",[155,6952,143],{"class":169},[155,6954,360],{"class":359},[155,6956,363],{"class":169},[155,6958,6959],{"class":366},"--button",[155,6961,1818],{"class":169},[155,6963,4054],{"class":183},[155,6965,6458],{"class":6378},[155,6967,370],{"class":169},[155,6969,6970,6973,6975,6977,6979,6982,6984,6986],{"class":157,"line":210},[155,6971,6972],{"class":366},"  --_shadow",[155,6974,143],{"class":169},[155,6976,360],{"class":359},[155,6978,363],{"class":169},[155,6980,6981],{"class":366},"--shadow",[155,6983,1818],{"class":169},[155,6985,6809],{"class":6617},[155,6987,370],{"class":169},[155,6989,6990],{"class":157,"line":223},[155,6991,478],{"class":169},[31,6993,6994,6995,6998,6999,7001,7002,7005],{},"For this example we will change the background, border, button hover and shadow color. So, we define the respective custom properties with an underscore like ",[58,6996,6997],{},"--_background"," and set variable which is exposed ",[58,7000,6917],{}," in the card class. Here, we can set fallback values, which also act as a default value for each of the cards. Now, the only thing is to set the private properties internally, such as changing the ",[58,7003,7004],{},"background-color"," property with the private property and doing the same with the rest of the properties.",[145,7007,7009],{"className":147,"code":7008,"filename":149,"language":150,"meta":151,"style":151},".card {\n  background-color: var(--_background);\n  &::after {\n    background-color: var(--_shadow);\n  }\n  .btn {\n    background-color: var(--_border);\n    &:hover {\n      border-color: var(--_border);\n      background-color: var(--_button-hover);\n    }\n  }\n  img {\n    border: 4px solid var(--_border);\n  }\n}\n",[58,7010,7011,7019,7033,7043,7058,7062,7071,7086,7096,7109,7125,7129,7133,7140,7162,7166],{"__ignoreMap":151},[155,7012,7013,7015,7017],{"class":157,"line":158},[155,7014,1245],{"class":183},[155,7016,6737],{"class":187},[155,7018,191],{"class":169},[155,7020,7021,7023,7025,7027,7029,7031],{"class":157,"line":173},[155,7022,1259],{"class":197},[155,7024,143],{"class":169},[155,7026,360],{"class":359},[155,7028,363],{"class":169},[155,7030,6997],{"class":366},[155,7032,370],{"class":169},[155,7034,7035,7038,7040],{"class":157,"line":180},[155,7036,7037],{"class":165},"  &",[155,7039,143],{"class":169},[155,7041,7042],{"class":165},":after {\n",[155,7044,7045,7048,7051,7053,7056],{"class":157,"line":194},[155,7046,7047],{"class":165},"    background-color: ",[155,7049,7050],{"class":359},"var",[155,7052,363],{"class":169},[155,7054,7055],{"class":366},"--_shadow",[155,7057,370],{"class":169},[155,7059,7060],{"class":157,"line":210},[155,7061,240],{"class":169},[155,7063,7064,7066,7069],{"class":157,"line":223},[155,7065,184],{"class":183},[155,7067,7068],{"class":187},"btn",[155,7070,191],{"class":169},[155,7072,7073,7075,7077,7079,7081,7084],{"class":157,"line":237},[155,7074,354],{"class":197},[155,7076,143],{"class":169},[155,7078,360],{"class":359},[155,7080,363],{"class":169},[155,7082,7083],{"class":366},"--_border",[155,7085,370],{"class":169},[155,7087,7088,7091,7093],{"class":157,"line":243},[155,7089,7090],{"class":165},"    &",[155,7092,143],{"class":169},[155,7094,7095],{"class":165},"hover {\n",[155,7097,7098,7101,7103,7105,7107],{"class":157,"line":249},[155,7099,7100],{"class":165},"      border-color: ",[155,7102,7050],{"class":359},[155,7104,363],{"class":169},[155,7106,7083],{"class":366},[155,7108,370],{"class":169},[155,7110,7111,7114,7116,7118,7120,7123],{"class":157,"line":266},[155,7112,7113],{"class":197},"      background-color",[155,7115,143],{"class":169},[155,7117,360],{"class":359},[155,7119,363],{"class":169},[155,7121,7122],{"class":366},"--_button-hover",[155,7124,370],{"class":169},[155,7126,7127],{"class":157,"line":280},[155,7128,2810],{"class":169},[155,7130,7131],{"class":157,"line":292},[155,7132,240],{"class":165},[155,7134,7135,7138],{"class":157,"line":304},[155,7136,7137],{"class":6350},"  img",[155,7139,191],{"class":169},[155,7141,7142,7145,7147,7150,7152,7154,7156,7158,7160],{"class":157,"line":321},[155,7143,7144],{"class":197},"    border",[155,7146,143],{"class":169},[155,7148,7149],{"class":231}," 4",[155,7151,316],{"class":315},[155,7153,6396],{"class":203},[155,7155,360],{"class":359},[155,7157,363],{"class":169},[155,7159,7083],{"class":366},[155,7161,370],{"class":169},[155,7163,7164],{"class":157,"line":337},[155,7165,240],{"class":169},[155,7167,7168],{"class":157,"line":351},[155,7169,478],{"class":165},[31,7171,7172],{},"As the default structure is set, to apply styles, all you need to do is set your desired value to the properties that are exposed, and if no style is set, then it will apply the fallback values. Here is an example with and without style.",[31,7174,7175],{},[37,7176,7177],{},"Code:",[145,7179,7181],{"className":147,"code":7180,"filename":149,"language":150,"meta":151,"style":151},".js {\n  --shadow: var(--clr-yellow-dark);\n  --background: var(--clr-yellow);\n  --border: var(--clr-yellow-dark);\n  --button: var(--clr-yellow);\n}\n.python {\n  \u002F* no value set in this card *\u002F\n}\n\n.ruby {\n  --shadow: var(--clr-red-dark);\n  --background: var(--clr-red);\n  --border: var(--clr-red-dark);\n  --button: var(--clr-red);\n}\n",[58,7182,7183,7191,7207,7223,7238,7253,7257,7266,7271,7275,7279,7288,7303,7318,7332,7346],{"__ignoreMap":151},[155,7184,7185,7187,7189],{"class":157,"line":158},[155,7186,1245],{"class":183},[155,7188,2536],{"class":187},[155,7190,191],{"class":169},[155,7192,7193,7196,7198,7200,7202,7205],{"class":157,"line":173},[155,7194,7195],{"class":366},"  --shadow",[155,7197,143],{"class":169},[155,7199,360],{"class":359},[155,7201,363],{"class":169},[155,7203,7204],{"class":366},"--clr-yellow-dark",[155,7206,370],{"class":169},[155,7208,7209,7212,7214,7216,7218,7221],{"class":157,"line":180},[155,7210,7211],{"class":366},"  --background",[155,7213,143],{"class":169},[155,7215,360],{"class":359},[155,7217,363],{"class":169},[155,7219,7220],{"class":366},"--clr-yellow",[155,7222,370],{"class":169},[155,7224,7225,7228,7230,7232,7234,7236],{"class":157,"line":194},[155,7226,7227],{"class":366},"  --border",[155,7229,143],{"class":169},[155,7231,360],{"class":359},[155,7233,363],{"class":169},[155,7235,7204],{"class":366},[155,7237,370],{"class":169},[155,7239,7240,7243,7245,7247,7249,7251],{"class":157,"line":210},[155,7241,7242],{"class":366},"  --button",[155,7244,143],{"class":169},[155,7246,360],{"class":359},[155,7248,363],{"class":169},[155,7250,7220],{"class":366},[155,7252,370],{"class":169},[155,7254,7255],{"class":157,"line":223},[155,7256,478],{"class":169},[155,7258,7259,7261,7264],{"class":157,"line":237},[155,7260,1245],{"class":183},[155,7262,7263],{"class":187},"python",[155,7265,191],{"class":169},[155,7267,7268],{"class":157,"line":243},[155,7269,7270],{"class":176},"  \u002F* no value set in this card *\u002F\n",[155,7272,7273],{"class":157,"line":249},[155,7274,478],{"class":169},[155,7276,7277],{"class":157,"line":266},[155,7278,246],{"emptyLinePlaceholder":18},[155,7280,7281,7283,7286],{"class":157,"line":280},[155,7282,1245],{"class":183},[155,7284,7285],{"class":187},"ruby",[155,7287,191],{"class":169},[155,7289,7290,7292,7294,7296,7298,7301],{"class":157,"line":292},[155,7291,7195],{"class":366},[155,7293,143],{"class":169},[155,7295,360],{"class":359},[155,7297,363],{"class":169},[155,7299,7300],{"class":366},"--clr-red-dark",[155,7302,370],{"class":169},[155,7304,7305,7307,7309,7311,7313,7316],{"class":157,"line":304},[155,7306,7211],{"class":366},[155,7308,143],{"class":169},[155,7310,360],{"class":359},[155,7312,363],{"class":169},[155,7314,7315],{"class":366},"--clr-red",[155,7317,370],{"class":169},[155,7319,7320,7322,7324,7326,7328,7330],{"class":157,"line":321},[155,7321,7227],{"class":366},[155,7323,143],{"class":169},[155,7325,360],{"class":359},[155,7327,363],{"class":169},[155,7329,7300],{"class":366},[155,7331,370],{"class":169},[155,7333,7334,7336,7338,7340,7342,7344],{"class":157,"line":337},[155,7335,7242],{"class":366},[155,7337,143],{"class":169},[155,7339,360],{"class":359},[155,7341,363],{"class":169},[155,7343,7315],{"class":366},[155,7345,370],{"class":169},[155,7347,7348],{"class":157,"line":351},[155,7349,478],{"class":169},[31,7351,7352],{},[37,7353,7354],{},"Preview:",[31,7356,7357],{},"You can see that with this approach, you are only setting values to the custom properties and having the option for a set of default values in place. For details explanation checkout the reference section.",[50,7359,7361],{"id":7360},"layout-change","Layout Change:",[31,7363,7364],{},"Although changing colors is okay, you can change the entire layout by defining another custom property. By adding data attributes and JavaScript a lot can be done. Checkout CodePen for the whole code.",[480,7366,7368],{"id":7367},"codepen",[37,7369,7370],{},"CodePen:",[7372,7373],"code-pen",{"description":7374,"id":7375,"title":7376},"A demonstration of using CSS custom properties for dynamic layout changes.","NWJqGRv","CSS Custom Property Demo",[50,7378,7380],{"id":7379},"reference","Reference",[31,7382,7383],{},[2391,7384,7385],{"href":7385,"rel":7386},"https:\u002F\u002Flea.verou.me\u002Fblog\u002F2021\u002F10\u002Fcustom-properties-with-defaults\u002F",[2395],[2416,7388,7389],{},"html pre.shiki code .svDm9, html code.shiki .svDm9{--shiki-light:#39ADB5;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .s6wAS, html code.shiki .s6wAS{--shiki-light:#E2931D;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sGRuu, html code.shiki .sGRuu{--shiki-light:#8796B0;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sngOx, html code.shiki .sngOx{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#D19A66}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sLhkd, html code.shiki .sLhkd{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#E06C75}html pre.shiki code .stV9d, html code.shiki .stV9d{--shiki-light:#90A4AE;--shiki-default:#0184BC;--shiki-dark:#D19A66}html pre.shiki code .sUz_E, html code.shiki .sUz_E{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}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 .s8dPH, html code.shiki .s8dPH{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .sTDPv, html code.shiki .sTDPv{--shiki-light:#6182B8;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .sJvnO, html code.shiki .sJvnO{--shiki-light:#E2931D;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}",{"title":151,"searchDepth":173,"depth":173,"links":7391},[7392,7393,7394,7397],{"id":6721,"depth":173,"text":6722},{"id":6884,"depth":173,"text":6887},{"id":7360,"depth":173,"text":7361,"children":7395},[7396],{"id":7367,"depth":180,"text":7370},{"id":7379,"depth":173,"text":7380},"2023-12-29","CSS Custom Properties offers great flexibility and modularity to a stylesheet. Allows developers to centralize values, simplify maintaining and updating multiple elements at once across the entire project. The use of custom properties can go from simple color, shadow values to do dynamic changes to styles based on user interactions or other events using JavaScript.",{"slug":7401,"difficulty":2442,"icon":150,"ogImage":7402,"tags":7404,"topic":150},"unique-css-custom-property",{"alt":7403},"CSS custom",[7405,6694,6341],"strategy","\u002Farticles\u002Funique-css-custom-property",{"title":6702,"description":7399},"articles\u002Funique-css-custom-property","RQpcXCpdnK2TrGHi795n1e7JkOBquGfXiyRL3kPTikQ",{"id":7411,"title":7412,"author":6,"body":7413,"date":8544,"description":7417,"draft":8,"extension":2439,"image":6,"lastmod":8544,"meta":8545,"minRead":6,"navigation":18,"path":8552,"seo":8553,"stem":8554,"__hash__":8555},"articles\u002Farticles\u002Fnode-jwt-token.md","What is a JSON Web Token?",{"type":28,"value":7414,"toc":8538},[7415,7418,7425,7431,7435,7441,7449,7503,7511,7604,7612,7670,7677,7687,7691,7694,7704,7743,7757,7775,7778,7817,7820,7842,8166,8172,8405,8409,8412,8461,8468,8474,8480,8486,8489,8533,8535],[31,7416,7417],{},"JSON Web Token is a self-contained and compact way for transmitting pieces of information between parties securing as a JSON object. Information is digitally signed so it can be verified. For digital signing, a secret (with the HMAC algorithm) or a public\u002Fprivate key pair using RSA or ECDSA.",[31,7419,7420,7421,7424],{},"One common use case for JWT is for client authorization. Once a user is logged in the server checks the user's credentials and sends a response, including a JSON web token, signed by the server's ",[37,7422,7423],{},"secret key",". Upon logging in, each request from the user will contain the JWT sent by the server. This helps the server validate that the user is the same user who logged in and is authorized to access resources\u002Fservices.",[31,7426,7427,7428,7430],{},"Another good use of JSON web token is data transmission among different parties. As the tokens are signed with a ",[37,7429,7423],{},", the payload can be verified if it was tampered.",[480,7432,7434],{"id":7433},"structure-of-json-web-token","Structure of JSON Web token",[31,7436,7437,7438],{},"JSON Web Tokens are divided into three parts and separated by a dot ",[58,7439,7440],{},"(.)",[107,7442,7443],{},[90,7444,7445,7448],{},[37,7446,7447],{},"Header :"," The header contains information about what algorithm is being used and also the type of the token being used, in this case it's JWT.",[145,7450,7453],{"className":2533,"code":7451,"filename":7452,"language":2536,"meta":151,"style":151},"{\n\"alg\": \"HS256\",\n\"typ\": \"JWT\",\n}\n","JSON Web Tokens",[58,7454,7455,7459,7479,7499],{"__ignoreMap":151},[155,7456,7457],{"class":157,"line":158},[155,7458,170],{"class":169},[155,7460,7461,7463,7466,7468,7470,7472,7475,7477],{"class":157,"line":173},[155,7462,618],{"class":274},[155,7464,7465],{"class":614},"alg",[155,7467,618],{"class":274},[155,7469,1984],{"class":1983},[155,7471,618],{"class":274},[155,7473,7474],{"class":614},"HS256",[155,7476,618],{"class":274},[155,7478,621],{"class":169},[155,7480,7481,7483,7486,7488,7490,7492,7495,7497],{"class":157,"line":180},[155,7482,618],{"class":274},[155,7484,7485],{"class":614},"typ",[155,7487,618],{"class":274},[155,7489,1984],{"class":1983},[155,7491,618],{"class":274},[155,7493,7494],{"class":614},"JWT",[155,7496,618],{"class":274},[155,7498,621],{"class":169},[155,7500,7501],{"class":157,"line":194},[155,7502,478],{"class":169},[107,7504,7505],{"start":173},[90,7506,7507,7510],{},[37,7508,7509],{},"Payload:"," The payload portion contains the users' information and some additional information to verify\u002Fidentify the user and grant access to specific resources. It is also a good practice to expire your tokens so that someone else can't use your token to gain access. For this, token expire information can also be added within the payload.",[145,7512,7515],{"className":2533,"code":7513,"filename":7514,"language":2536,"meta":151,"style":151},"{\n  \"_id\": \"6574765161\",\n  \"name\": \"Jackie Chan\",\n  \"iat\": \"1516239022\",\n  \"exp\": \"1615673602\"\n}\n","Sample Payload",[58,7516,7517,7521,7542,7562,7582,7600],{"__ignoreMap":151},[155,7518,7519],{"class":157,"line":158},[155,7520,170],{"class":169},[155,7522,7523,7526,7529,7531,7533,7535,7538,7540],{"class":157,"line":173},[155,7524,7525],{"class":274},"  \"",[155,7527,7528],{"class":614},"_id",[155,7530,618],{"class":274},[155,7532,1984],{"class":1983},[155,7534,618],{"class":274},[155,7536,7537],{"class":614},"6574765161",[155,7539,618],{"class":274},[155,7541,621],{"class":169},[155,7543,7544,7546,7549,7551,7553,7555,7558,7560],{"class":157,"line":180},[155,7545,7525],{"class":274},[155,7547,7548],{"class":614},"name",[155,7550,618],{"class":274},[155,7552,1984],{"class":1983},[155,7554,618],{"class":274},[155,7556,7557],{"class":614},"Jackie Chan",[155,7559,618],{"class":274},[155,7561,621],{"class":169},[155,7563,7564,7566,7569,7571,7573,7575,7578,7580],{"class":157,"line":194},[155,7565,7525],{"class":274},[155,7567,7568],{"class":614},"iat",[155,7570,618],{"class":274},[155,7572,1984],{"class":1983},[155,7574,618],{"class":274},[155,7576,7577],{"class":614},"1516239022",[155,7579,618],{"class":274},[155,7581,621],{"class":169},[155,7583,7584,7586,7589,7591,7593,7595,7598],{"class":157,"line":210},[155,7585,7525],{"class":274},[155,7587,7588],{"class":614},"exp",[155,7590,618],{"class":274},[155,7592,1984],{"class":1983},[155,7594,618],{"class":274},[155,7596,7597],{"class":614},"1615673602",[155,7599,2216],{"class":274},[155,7601,7602],{"class":157,"line":223},[155,7603,478],{"class":169},[107,7605,7606],{"start":180},[90,7607,7608,7611],{},[37,7609,7610],{},"Signature:"," Lastly, the signature part is a combination of three Base64-URL strings that are separated by dots. This can be easily passed while being more compact when compared to XML-based standards such as SAML and can later be verified.",[145,7613,7616],{"className":2533,"code":7614,"filename":7615,"language":2536,"meta":151,"style":151},"HMACSHA256(base64UrlEncode(header) + \".\" + base64UrlEncode(payload), \"json-web-token-following\");\n","Signature Structure",[58,7617,7618],{"__ignoreMap":151},[155,7619,7620,7623,7625,7628,7630,7633,7635,7638,7640,7642,7644,7647,7650,7652,7655,7657,7659,7661,7664,7666,7668],{"class":157,"line":158},[155,7621,7622],{"class":576},"HMACSHA256",[155,7624,363],{"class":165},[155,7626,7627],{"class":576},"base64UrlEncode",[155,7629,363],{"class":165},[155,7631,7632],{"class":2894},"header",[155,7634,2685],{"class":165},[155,7636,7637],{"class":2636},"+",[155,7639,611],{"class":274},[155,7641,1245],{"class":614},[155,7643,618],{"class":274},[155,7645,7646],{"class":2636}," +",[155,7648,7649],{"class":576}," base64UrlEncode",[155,7651,363],{"class":165},[155,7653,7654],{"class":2894},"payload",[155,7656,816],{"class":165},[155,7658,1818],{"class":169},[155,7660,611],{"class":274},[155,7662,7663],{"class":614},"json-web-token-following",[155,7665,618],{"class":274},[155,7667,816],{"class":165},[155,7669,207],{"class":169},[31,7671,7672,7673,7676],{},"The token structure looks something like: ",[58,7674,7675],{},"header.payload.signature"," The token itself :",[145,7678,7681],{"className":5219,"code":7679,"filename":7680,"language":5222,"meta":151,"style":151},"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2NTc0NzY1MTYxIiwibmFtZSI6IkphY2tpZSBDaGFuIiwiaWF0IjoiMTUxNjIzOTAyMiIsImV4cCI6IjE2MTU2NzM2MDIifQ._ar1JLdQErmVNSyqVjMW8FolQwlkhADNyEFjMgiEgCM\n","JWT token",[58,7682,7683],{"__ignoreMap":151},[155,7684,7685],{"class":157,"line":158},[155,7686,7679],{},[480,7688,7690],{"id":7689},"example-of-json-web-tokens","Example of JSON Web tokens",[31,7692,7693],{},"For this example, I'm using my project, which already includes user login and registration functionality. So I will be explaining how to verify JWT tokens and protect routes using tokens.",[31,7695,7696,7697],{},"You can find the project from ",[2391,7698,7701],{"href":7699,"rel":7700},"https:\u002F\u002Fgithub.com\u002Fratul16\u002Fnode-express-auth-registration",[2395],[37,7702,7703],{},"Github",[145,7705,7708],{"className":5270,"code":7706,"language":5272,"meta":7707,"style":151},"  # clone repo\n  git clone https:\u002F\u002Fgithub.com\u002Fratul16\u002Fnode-express-auth-registration.git\n\n  # navigate to directorycd node-express-auth-registration\n  cd node-express-auth-registration\n","icon=devicon-plain:bash",[58,7709,7710,7715,7726,7730,7735],{"__ignoreMap":151},[155,7711,7712],{"class":157,"line":158},[155,7713,7714],{"class":176},"  # clone repo\n",[155,7716,7717,7720,7723],{"class":157,"line":173},[155,7718,7719],{"class":5279},"  git",[155,7721,7722],{"class":614}," clone",[155,7724,7725],{"class":614}," https:\u002F\u002Fgithub.com\u002Fratul16\u002Fnode-express-auth-registration.git\n",[155,7727,7728],{"class":157,"line":180},[155,7729,246],{"emptyLinePlaceholder":18},[155,7731,7732],{"class":157,"line":194},[155,7733,7734],{"class":176},"  # navigate to directorycd node-express-auth-registration\n",[155,7736,7737,7740],{"class":157,"line":210},[155,7738,7739],{"class":359},"  cd",[155,7741,7742],{"class":614}," node-express-auth-registration\n",[31,7744,7745,7746,7749,7750,7753,7754,7756],{},"Create a ",[58,7747,7748],{},".env"," file and store your ",[37,7751,7752],{},"MongoDB"," url and ",[37,7755,7423],{}," and your are good to go.",[145,7758,7763],{"className":7759,"code":7760,"language":7761,"meta":7762,"style":151},"language-env shiki shiki-themes material-theme-lighter one-light one-dark-pro","MONGODB = \"mongodb-url\"\nTOKEN_SECRET = \"your-secret-key\"\n","env","label=\"env variables\" icon=devicon:dotenv",[58,7764,7765,7770],{"__ignoreMap":151},[155,7766,7767],{"class":157,"line":158},[155,7768,7769],{},"MONGODB = \"mongodb-url\"\n",[155,7771,7772],{"class":157,"line":173},[155,7773,7774],{},"TOKEN_SECRET = \"your-secret-key\"\n",[31,7776,7777],{},"Finally",[145,7779,7781],{"className":5270,"code":7780,"language":5272,"meta":7707,"style":151},"# install dependencies\n$ npm install\n\n# serve with hot reload at localhost:3000\n$ npm start\n",[58,7782,7783,7788,7799,7803,7808],{"__ignoreMap":151},[155,7784,7785],{"class":157,"line":158},[155,7786,7787],{"class":176},"# install dependencies\n",[155,7789,7790,7793,7796],{"class":157,"line":173},[155,7791,7792],{"class":5279},"$",[155,7794,7795],{"class":614}," npm",[155,7797,7798],{"class":614}," install\n",[155,7800,7801],{"class":157,"line":180},[155,7802,246],{"emptyLinePlaceholder":18},[155,7804,7805],{"class":157,"line":194},[155,7806,7807],{"class":176},"# serve with hot reload at localhost:3000\n",[155,7809,7810,7812,7814],{"class":157,"line":210},[155,7811,7792],{"class":5279},[155,7813,7795],{"class":614},[155,7815,7816],{"class":614}," start\n",[31,7818,7819],{},"As discussed above, each request from the user has to contain the JSON web token to have access to resources. Here will demonstrate a similar scenario, if the request header doesn't contain a valid token, then the user's access will be denied.",[31,7821,7822,7823,7826,7827,7830,7831,7834,7835,7838,7839,7841],{},"In the ",[58,7824,7825],{},"auth"," function, we check if the request header contains the token. If not, we send a response with a ",[37,7828,7829],{},"status code 401",", which means access is denied. But if the token exists in the request header, then we are verifying it within the try-catch. ",[37,7832,7833],{},"jsonwebtoken"," has a built-in function for token verification, which requires the ",[58,7836,7837],{},"token"," and ",[58,7840,7423],{}," as shown below. If it's an invalid token, we will send a response with status code 400; else, we are returning the token as verified.",[556,7843,7844],{},[145,7845,7848],{"className":2533,"code":7846,"filename":7847,"language":2536,"meta":151,"style":151},"const JWT = require('jsonwebtoken');\n\nfunction auth(req, res, next) {\n  const token = req.header('auth-header');\n\n\u002F\u002F checking if token exists or not if (!token)\nreturn res.send({\n      statusCode: 401,\n      message: \"Access Denied\"\n  });\n\ntoken verification {\ntry {\n      const verified = JWT.verify(token, process.env.TOKEN_SECRET);\n      req.user = verified;\n      next();\n  } catch (error) {\n      res.send({\n          statusCode: 400,\n          message: \"Invalid Token\"\n      });\n  }\n}\n\nmodule.exports = auth;\n","tokenVerify.js",[58,7849,7850,7874,7878,7904,7933,7937,7942,7958,7969,7982,7990,7994,8003,8010,8050,8066,8075,8089,8102,8114,8128,8137,8141,8145,8149],{"__ignoreMap":151},[155,7851,7852,7854,7857,7859,7862,7864,7866,7868,7870,7872],{"class":157,"line":158},[155,7853,3922],{"class":2610},[155,7855,7856],{"class":2632}," JWT",[155,7858,2637],{"class":2636},[155,7860,7861],{"class":576}," require",[155,7863,363],{"class":165},[155,7865,4973],{"class":274},[155,7867,7833],{"class":614},[155,7869,4973],{"class":274},[155,7871,816],{"class":165},[155,7873,207],{"class":169},[155,7875,7876],{"class":157,"line":173},[155,7877,246],{"emptyLinePlaceholder":18},[155,7879,7880,7883,7886,7888,7891,7893,7896,7898,7900,7902],{"class":157,"line":180},[155,7881,7882],{"class":2610},"function",[155,7884,7885],{"class":576}," auth",[155,7887,363],{"class":169},[155,7889,7890],{"class":2619},"req",[155,7892,1818],{"class":169},[155,7894,7895],{"class":2619}," res",[155,7897,1818],{"class":169},[155,7899,3209],{"class":2619},[155,7901,816],{"class":169},[155,7903,191],{"class":169},[155,7905,7906,7908,7911,7913,7916,7918,7920,7922,7924,7927,7929,7931],{"class":157,"line":194},[155,7907,2629],{"class":2610},[155,7909,7910],{"class":2632}," token",[155,7912,2637],{"class":2636},[155,7914,7915],{"class":2677}," req",[155,7917,1245],{"class":169},[155,7919,7632],{"class":576},[155,7921,363],{"class":1983},[155,7923,4973],{"class":274},[155,7925,7926],{"class":614},"auth-header",[155,7928,4973],{"class":274},[155,7930,816],{"class":1983},[155,7932,207],{"class":169},[155,7934,7935],{"class":157,"line":210},[155,7936,246],{"emptyLinePlaceholder":18},[155,7938,7939],{"class":157,"line":223},[155,7940,7941],{"class":176},"\u002F\u002F checking if token exists or not if (!token)\n",[155,7943,7944,7947,7949,7951,7954,7956],{"class":157,"line":237},[155,7945,7946],{"class":161},"return",[155,7948,7895],{"class":2677},[155,7950,1245],{"class":169},[155,7952,7953],{"class":576},"send",[155,7955,363],{"class":1983},[155,7957,170],{"class":169},[155,7959,7960,7962,7964,7967],{"class":157,"line":243},[155,7961,6003],{"class":586},[155,7963,143],{"class":590},[155,7965,7966],{"class":231}," 401",[155,7968,621],{"class":169},[155,7970,7971,7973,7975,7977,7980],{"class":157,"line":249},[155,7972,5953],{"class":586},[155,7974,143],{"class":590},[155,7976,611],{"class":274},[155,7978,7979],{"class":614},"Access Denied",[155,7981,2216],{"class":274},[155,7983,7984,7986,7988],{"class":157,"line":266},[155,7985,2903],{"class":169},[155,7987,816],{"class":1983},[155,7989,207],{"class":169},[155,7991,7992],{"class":157,"line":280},[155,7993,246],{"emptyLinePlaceholder":18},[155,7995,7996,7998,8001],{"class":157,"line":292},[155,7997,7837],{"class":2894},[155,7999,8000],{"class":2894}," verification",[155,8002,191],{"class":169},[155,8004,8005,8008],{"class":157,"line":304},[155,8006,8007],{"class":161},"try",[155,8009,191],{"class":169},[155,8011,8012,8015,8018,8020,8022,8024,8027,8029,8031,8033,8036,8038,8040,8042,8046,8048],{"class":157,"line":321},[155,8013,8014],{"class":2610},"      const",[155,8016,8017],{"class":2632}," verified",[155,8019,2637],{"class":2636},[155,8021,7856],{"class":2632},[155,8023,1245],{"class":169},[155,8025,8026],{"class":576},"verify",[155,8028,363],{"class":1983},[155,8030,7837],{"class":2894},[155,8032,1818],{"class":169},[155,8034,8035],{"class":2677}," process",[155,8037,1245],{"class":169},[155,8039,7761],{"class":2721},[155,8041,1245],{"class":169},[155,8043,8045],{"class":8044},"srkOc","TOKEN_SECRET",[155,8047,816],{"class":1983},[155,8049,207],{"class":169},[155,8051,8052,8055,8057,8060,8062,8064],{"class":157,"line":337},[155,8053,8054],{"class":2677},"      req",[155,8056,1245],{"class":169},[155,8058,8059],{"class":366},"user",[155,8061,2637],{"class":2636},[155,8063,8017],{"class":2894},[155,8065,207],{"class":169},[155,8067,8068,8071,8073],{"class":157,"line":351},[155,8069,8070],{"class":576},"      next",[155,8072,2642],{"class":1983},[155,8074,207],{"class":169},[155,8076,8077,8079,8081,8083,8085,8087],{"class":157,"line":373},[155,8078,2903],{"class":169},[155,8080,5983],{"class":161},[155,8082,2674],{"class":1983},[155,8084,5988],{"class":2894},[155,8086,2685],{"class":1983},[155,8088,170],{"class":169},[155,8090,8091,8094,8096,8098,8100],{"class":157,"line":394},[155,8092,8093],{"class":2677},"      res",[155,8095,1245],{"class":169},[155,8097,7953],{"class":576},[155,8099,363],{"class":1983},[155,8101,170],{"class":169},[155,8103,8104,8107,8109,8112],{"class":157,"line":406},[155,8105,8106],{"class":586},"          statusCode",[155,8108,143],{"class":590},[155,8110,8111],{"class":231}," 400",[155,8113,621],{"class":169},[155,8115,8116,8119,8121,8123,8126],{"class":157,"line":428},[155,8117,8118],{"class":586},"          message",[155,8120,143],{"class":590},[155,8122,611],{"class":274},[155,8124,8125],{"class":614},"Invalid Token",[155,8127,2216],{"class":274},[155,8129,8130,8133,8135],{"class":157,"line":433},[155,8131,8132],{"class":169},"      }",[155,8134,816],{"class":1983},[155,8136,207],{"class":169},[155,8138,8139],{"class":157,"line":438},[155,8140,240],{"class":169},[155,8142,8143],{"class":157,"line":456},[155,8144,478],{"class":169},[155,8146,8147],{"class":157,"line":470},[155,8148,246],{"emptyLinePlaceholder":18},[155,8150,8151,8155,8157,8160,8162,8164],{"class":157,"line":475},[155,8152,8154],{"class":8153},"siYUK","module",[155,8156,1245],{"class":169},[155,8158,8159],{"class":8153},"exports",[155,8161,2637],{"class":2636},[155,8163,7885],{"class":2894},[155,8165,207],{"class":169},[31,8167,8168,8169,8171],{},"Now in the post route, we need to import ",[58,8170,7847],{}," script and pass it as a parameter. A try-catch will check if it is verified.",[145,8173,8176],{"className":2533,"code":8174,"filename":8175,"language":2536,"meta":151,"style":151},"\u002F\u002F Post Route\nconst router = require(\"express\").Router();\nconst postSchema = require(\"..\u002Fmodels\u002FPost\");\nconst verify = require(\".\u002FtokenVerify\");\n\nrouter.get(\"\u002F\", verify, async (req, res) => {\n  try {\n    const posts = await postSchema.find();\n    res.send(posts);\n  } catch (err) {\n    res.send({ message: err });\n  }\n});\n","post.js",[58,8177,8178,8183,8214,8238,8262,8266,8306,8312,8334,8352,8367,8393,8397],{"__ignoreMap":151},[155,8179,8180],{"class":157,"line":158},[155,8181,8182],{"class":176},"\u002F\u002F Post Route\n",[155,8184,8185,8187,8190,8192,8194,8196,8198,8201,8203,8205,8207,8210,8212],{"class":157,"line":173},[155,8186,3922],{"class":2610},[155,8188,8189],{"class":2632}," router",[155,8191,2637],{"class":2636},[155,8193,7861],{"class":576},[155,8195,363],{"class":165},[155,8197,618],{"class":274},[155,8199,8200],{"class":614},"express",[155,8202,618],{"class":274},[155,8204,816],{"class":165},[155,8206,1245],{"class":169},[155,8208,8209],{"class":576},"Router",[155,8211,2642],{"class":165},[155,8213,207],{"class":169},[155,8215,8216,8218,8221,8223,8225,8227,8229,8232,8234,8236],{"class":157,"line":180},[155,8217,3922],{"class":2610},[155,8219,8220],{"class":2632}," postSchema",[155,8222,2637],{"class":2636},[155,8224,7861],{"class":576},[155,8226,363],{"class":165},[155,8228,618],{"class":274},[155,8230,8231],{"class":614},"..\u002Fmodels\u002FPost",[155,8233,618],{"class":274},[155,8235,816],{"class":165},[155,8237,207],{"class":169},[155,8239,8240,8242,8245,8247,8249,8251,8253,8256,8258,8260],{"class":157,"line":194},[155,8241,3922],{"class":2610},[155,8243,8244],{"class":2632}," verify",[155,8246,2637],{"class":2636},[155,8248,7861],{"class":576},[155,8250,363],{"class":165},[155,8252,618],{"class":274},[155,8254,8255],{"class":614},".\u002FtokenVerify",[155,8257,618],{"class":274},[155,8259,816],{"class":165},[155,8261,207],{"class":169},[155,8263,8264],{"class":157,"line":210},[155,8265,246],{"emptyLinePlaceholder":18},[155,8267,8268,8270,8272,8275,8277,8279,8282,8284,8286,8288,8290,8292,8294,8296,8298,8300,8302,8304],{"class":157,"line":223},[155,8269,3188],{"class":2677},[155,8271,1245],{"class":169},[155,8273,8274],{"class":576},"get",[155,8276,363],{"class":165},[155,8278,618],{"class":274},[155,8280,8281],{"class":614},"\u002F",[155,8283,618],{"class":274},[155,8285,1818],{"class":169},[155,8287,8244],{"class":2894},[155,8289,1818],{"class":169},[155,8291,6094],{"class":2610},[155,8293,2674],{"class":169},[155,8295,7890],{"class":2619},[155,8297,1818],{"class":169},[155,8299,7895],{"class":2619},[155,8301,816],{"class":169},[155,8303,2664],{"class":2610},[155,8305,191],{"class":169},[155,8307,8308,8310],{"class":157,"line":237},[155,8309,5806],{"class":161},[155,8311,191],{"class":169},[155,8313,8314,8316,8319,8321,8323,8325,8327,8330,8332],{"class":157,"line":243},[155,8315,5813],{"class":2610},[155,8317,8318],{"class":2632}," posts",[155,8320,2637],{"class":2636},[155,8322,5821],{"class":161},[155,8324,8220],{"class":2677},[155,8326,1245],{"class":169},[155,8328,8329],{"class":576},"find",[155,8331,2642],{"class":1983},[155,8333,207],{"class":169},[155,8335,8336,8339,8341,8343,8345,8348,8350],{"class":157,"line":249},[155,8337,8338],{"class":2677},"    res",[155,8340,1245],{"class":169},[155,8342,7953],{"class":576},[155,8344,363],{"class":1983},[155,8346,8347],{"class":2894},"posts",[155,8349,816],{"class":1983},[155,8351,207],{"class":169},[155,8353,8354,8356,8358,8360,8363,8365],{"class":157,"line":266},[155,8355,2903],{"class":169},[155,8357,5983],{"class":161},[155,8359,2674],{"class":1983},[155,8361,8362],{"class":2894},"err",[155,8364,2685],{"class":1983},[155,8366,170],{"class":169},[155,8368,8369,8371,8373,8375,8377,8380,8382,8384,8387,8389,8391],{"class":157,"line":280},[155,8370,8338],{"class":2677},[155,8372,1245],{"class":169},[155,8374,7953],{"class":576},[155,8376,363],{"class":1983},[155,8378,8379],{"class":169},"{",[155,8381,5888],{"class":586},[155,8383,143],{"class":590},[155,8385,8386],{"class":2894}," err",[155,8388,2566],{"class":169},[155,8390,816],{"class":1983},[155,8392,207],{"class":169},[155,8394,8395],{"class":157,"line":292},[155,8396,240],{"class":169},[155,8398,8399,8401,8403],{"class":157,"line":304},[155,8400,813],{"class":169},[155,8402,816],{"class":165},[155,8404,207],{"class":169},[50,8406,8408],{"id":8407},"now-lets-test-it-out","Now lets test it out!",[31,8410,8411],{},"I am using postman to test the API, and you can use the tool your comfortable with. After setting up the project and registering a user. Now login with the user's email and password. If everything goes well, you will see a response like this.",[145,8413,8416],{"className":2533,"code":8414,"language":2536,"meta":8415,"style":151},"{\n    \"statusCode\": 200,\n    \"message\": \"Logged In !!\"\n}\n","label=\"response\" icon=devicon:javascript",[58,8417,8418,8422,8439,8457],{"__ignoreMap":151},[155,8419,8420],{"class":157,"line":158},[155,8421,170],{"class":169},[155,8423,8424,8427,8430,8432,8434,8437],{"class":157,"line":173},[155,8425,8426],{"class":274},"    \"",[155,8428,8429],{"class":614},"statusCode",[155,8431,618],{"class":274},[155,8433,1984],{"class":1983},[155,8435,8436],{"class":231},"200",[155,8438,621],{"class":169},[155,8440,8441,8443,8446,8448,8450,8452,8455],{"class":157,"line":180},[155,8442,8426],{"class":274},[155,8444,8445],{"class":614},"message",[155,8447,618],{"class":274},[155,8449,1984],{"class":1983},[155,8451,618],{"class":274},[155,8453,8454],{"class":614},"Logged In !!",[155,8456,2216],{"class":274},[155,8458,8459],{"class":157,"line":194},[155,8460,478],{"class":169},[31,8462,8463,8464,8467],{},"And now, if you check the header, you will see the ",[58,8465,8466],{},"auth-token"," key with the token value. Now you can store and use this token to the sent request.",[31,8469,8470],{},[6270,8471],{"alt":8472,"src":8473},"header with token","https:\u002F\u002Fik.imagekit.io\u002F3mh13v7xv4\u002Farticles\u002Fjson-web-token\u002Ftoken.jpg",[31,8475,8476,8477,8479],{},"Now that we have the token, let try requesting some data. We need to include the token in the header as ",[58,8478,7926],{}," and send the request. After that, we will see all the posts that are stored in the database.",[31,8481,8482],{},[6270,8483],{"alt":8484,"src":8485},"post request response","https:\u002F\u002Fik.imagekit.io\u002F3mh13v7xv4\u002Farticles\u002Fjson-web-token\u002Fpost.jpg",[31,8487,8488],{},"But if the token has tampered with, then the request will be invalid and get a response.",[145,8490,8492],{"className":2533,"code":8491,"language":2536,"meta":8415,"style":151},"{\n    \"statusCode\": 400,\n    \"message\": \"Invalid Token\"\n}\n",[58,8493,8494,8498,8513,8529],{"__ignoreMap":151},[155,8495,8496],{"class":157,"line":158},[155,8497,170],{"class":169},[155,8499,8500,8502,8504,8506,8508,8511],{"class":157,"line":173},[155,8501,8426],{"class":274},[155,8503,8429],{"class":614},[155,8505,618],{"class":274},[155,8507,1984],{"class":1983},[155,8509,8510],{"class":231},"400",[155,8512,621],{"class":169},[155,8514,8515,8517,8519,8521,8523,8525,8527],{"class":157,"line":180},[155,8516,8426],{"class":274},[155,8518,8445],{"class":614},[155,8520,618],{"class":274},[155,8522,1984],{"class":1983},[155,8524,618],{"class":274},[155,8526,8125],{"class":614},[155,8528,2216],{"class":274},[155,8530,8531],{"class":157,"line":194},[155,8532,478],{"class":169},[50,8534,2414],{"id":2413},[2416,8536,8537],{},"html pre.shiki code .sB4Xn, html code.shiki .sB4Xn{--shiki-light:#39ADB5;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sVH1b, html code.shiki .sVH1b{--shiki-light:#39ADB5;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .spZWa, html code.shiki .spZWa{--shiki-light:#91B859;--shiki-default:#50A14F;--shiki-dark:#98C379}html pre.shiki code .sA0eD, html code.shiki .sA0eD{--shiki-light:#E53935;--shiki-default:#383A42;--shiki-dark:#ABB2BF}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 .spnjr, html code.shiki .spnjr{--shiki-light:#6182B8;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .sM89C, html code.shiki .sM89C{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#ABB2BF}html pre.shiki code .sWjah, html code.shiki .sWjah{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E06C75}html pre.shiki code .syPST, html code.shiki .syPST{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .seacL, html code.shiki .seacL{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0A1A7;--shiki-default-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic}html pre.shiki code .stT07, html code.shiki .stT07{--shiki-light:#E2931D;--shiki-default:#4078F2;--shiki-dark:#61AFEF}html pre.shiki code .sTDPv, html code.shiki .sTDPv{--shiki-light:#6182B8;--shiki-default:#0184BC;--shiki-dark:#56B6C2}html pre.shiki code .sJvVP, html code.shiki .sJvVP{--shiki-light:#9C3EDA;--shiki-default:#A626A4;--shiki-dark:#C678DD}html pre.shiki code .sMm83, html code.shiki .sMm83{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#E5C07B}html pre.shiki code .s5f2p, html code.shiki .s5f2p{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#383A42;--shiki-default-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic}html pre.shiki code .scCn_, html code.shiki .scCn_{--shiki-light:#90A4AE;--shiki-default:#383A42;--shiki-dark:#E5C07B}html pre.shiki code .sQsOY, html code.shiki .sQsOY{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A626A4;--shiki-default-font-style:inherit;--shiki-dark:#C678DD;--shiki-dark-font-style:inherit}html pre.shiki code .su13H, html code.shiki .su13H{--shiki-light:#E53935;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .saKOp, html code.shiki .saKOp{--shiki-light:#39ADB5;--shiki-default:#0184BC;--shiki-dark:#ABB2BF}html pre.shiki code .sriKn, html code.shiki .sriKn{--shiki-light:#F76D47;--shiki-default:#986801;--shiki-dark:#D19A66}html pre.shiki code .sDC5J, html code.shiki .sDC5J{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E5C07B}html pre.shiki code .srkOc, html code.shiki .srkOc{--shiki-light:#90A4AE;--shiki-default:#986801;--shiki-dark:#E06C75}html pre.shiki code .s8dPH, html code.shiki .s8dPH{--shiki-light:#90A4AE;--shiki-default:#E45649;--shiki-dark:#E06C75}html pre.shiki code .siYUK, html code.shiki .siYUK{--shiki-light:#39ADB5;--shiki-default:#E45649;--shiki-dark:#E5C07B}",{"title":151,"searchDepth":173,"depth":173,"links":8539},[8540,8541,8542,8543],{"id":7433,"depth":180,"text":7434},{"id":7689,"depth":180,"text":7690},{"id":8407,"depth":173,"text":8408},{"id":2413,"depth":173,"text":2414},"2021-04-14",{"slug":8546,"difficulty":2442,"icon":8547,"ogImage":8548,"tags":8549,"topic":8547},"node-jwt-token","node",{"alt":8546},[8550,8551,8547],"jwt","web-token","\u002Farticles\u002Fnode-jwt-token",{"title":7412,"description":7417},"articles\u002Fnode-jwt-token","g5KqKoy0VamwxJrxQS86Nk_RMm31NCANZBUzbZ9gavg",{"id":4,"title":5,"author":6,"body":6,"date":6,"description":7,"draft":8,"extension":9,"image":6,"lastmod":6,"meta":8557,"minRead":6,"navigation":18,"path":19,"seo":8560,"stem":21,"__hash__":22},{"links":8558},[8559],{"label":13,"icon":14,"to":15,"variant":16,"color":17},{"title":5,"description":7},1778820754208]