[{"data":1,"prerenderedAt":2032},["ShallowReactive",2],{"projects-all":3},[4,446,1173,1284,1528,1757,1827,1872,1950],{"id":5,"title":6,"additionalTags":7,"body":8,"description":420,"excerpt":421,"extension":422,"featured":423,"meta":424,"name":427,"navigation":423,"openSource":428,"path":429,"projectDate":430,"projectFolder":73,"seo":431,"sitemap":432,"status":436,"stem":437,"subtitle":438,"tags":439,"thumbnail":444,"__hash__":445},"projects/projects/7.you-tz.md","You Tz",[],{"type":9,"value":10,"toc":402},"minimark",[11,15,26,31,34,40,47,52,55,65,68,75,79,82,88,92,95,136,139,147,150,154,157,161,164,168,171,202,205,209,248,251,254,273,276,280,306,310,330,334,351,355],[12,13],"stats-table",{":stats":14},"[{\"label\": \"release date\", \"value\": \"2026\"}]",[16,17,18],"p",{},[19,20],"img",{"alt":21,"className":22,"src":24,"width":25},"Screenshot",[23],"w-full","/projects/you-tz/now.png",640,[27,28,30],"h2",{"id":29},"the-problem","The Problem",[16,32,33],{},"Every Front-end developer has been there... you have a date string — say:",[16,35,36],{},[37,38,39],"code",{},"2026-05-08T15:42:51.714709",[16,41,42,43,46],{},"and you go to display it in relative time format that should say \"just now\" but instead shows \"in X hours.\" The eagle-eyed would have spotted the missing ",[37,44,45],{},"Z"," suffix (or similar offset). While still a valid ISO 8601 date format; most date libraries will silently coerce into local time instead of UTC without a specified offset.",[48,49,51],"h3",{"id":50},"zulu-or-bust","Zulu or bust",[16,53,54],{},"The primary use case that motivated you-tz is the \"missing Z problem.\" Consider:",[56,57,62],"pre",{"className":58,"code":60,"language":61},[59],"language-text","2026-05-08T15:42:51.714709      ← no Z, parsed as local time\n2026-05-08T15:42:51.714709Z     ← Z present, parsed as UTC\n","text",[37,63,60],{"__ignoreMap":64},"",[16,66,67],{},"These look almost identical. But depending on your timezone, they can be hours apart. And different libraries handle the ambiguity differently — some assume local time, some assume UTC, some require explicit configuration.",[16,69,70,74],{},[71,72,73],"strong",{},"you-tz"," makes this difference visible. You paste a string, and the library comparison immediately show which ones interpreted it as local time versus UTC depending of how you're using it.",[48,76,78],{"id":77},"how-it-works","How it works",[16,80,81],{},"Paste any ISO string, see how it is handled in popular JavaScript date libraries, and visualize it on a world map across timezones of your choosing.",[16,83,84,85,87],{},"Whether you're just jumping into an existing project and seeing something weird or switching your date library; I built ",[71,86,73],{}," to help debug these exact issues.",[48,89,91],{"id":90},"cross-library-comparison","Cross-Library Comparison",[16,93,94],{},"The core of you-tz is a side-by-side comparison of how different date libraries handle the same input. The project currently supports:",[96,97,98,105,111,117,123],"ul",{},[99,100,101,104],"li",{},[71,102,103],{},"Moment.js"," — the classic, now deprecated, but still relevant",[99,106,107,110],{},[71,108,109],{},"date-fns"," — the modern functional approach",[99,112,113,116],{},[71,114,115],{},"Luxon"," — Moment's successor with built-in timezone support",[99,118,119,122],{},[71,120,121],{},"Day.js"," — the lightweight drop-in Moment replacement",[99,124,125,128,129,132,133],{},[71,126,127],{},"Vanilla JS"," — native JS ",[37,130,131],{},"Date"," and ",[37,134,135],{},"Intl",[16,137,138],{},"and in the works:",[96,140,141],{},[99,142,143,146],{},[71,144,145],{},"Temporal API"," — the upcoming ECMAScript standard",[16,148,149],{},"This is exactly the kind of comparison that takes 15 minutes of console or debugging work and turns it into a single glance.",[48,151,153],{"id":152},"world-map-visualization","World Map Visualization",[16,155,156],{},"Using MapLibre, you-tz plots selected timezones on a world map. Markers are positioned by GMT offset and labeled with timezone names. You can add or remove timezones to see how the same instant looks across different parts of the world.",[27,158,160],{"id":159},"building-with-ai","Building with AI",[16,162,163],{},"I utilized OpenCode + various different AI models during the initial planning, development and prototyping phases.",[48,165,167],{"id":166},"planning-phase","Planning Phase",[16,169,170],{},"Before writing any code, I used AI to help structure the architecture. The initial conversation covered:",[96,172,173,176,179,196,199],{},[99,174,175],{},"What the project needed to accomplish",[99,177,178],{},"How the UI should be organized (landing page → debug view)",[99,180,181,182,185,186,185,189,185,192,195],{},"Which composables to extract (",[37,183,184],{},"useDateParsing",", ",[37,187,188],{},"useTimezones",[37,190,191],{},"useLibraries",[37,193,194],{},"useTheme",")",[99,197,198],{},"The routing strategy (regex-based routes for ISO strings)",[99,200,201],{},"How to handle URL serialization for shareability",[16,203,204],{},"Having an AI that could reason about Vue 3 patterns, Pinia stores, and route configuration in real time meant I could iterate on architecture decisions without context-switching between documentation tabs.",[48,206,208],{"id":207},"rapid-prototyping","Rapid Prototyping",[16,210,211,212,185,215,185,218,185,221,224,225,228,229,232,233,185,236,239,240,243,244,247],{},"The individual library components — ",[37,213,214],{},"LibMoment.vue",[37,216,217],{},"LibDateFns.vue",[37,219,220],{},"LibLuxon.vue",[37,222,223],{},"LibDayjs.vue"," — all follow the same pattern: a ",[37,226,227],{},"\u003Cscript setup>"," that defines ",[37,230,231],{},"rows"," with ",[37,234,235],{},"category",[37,237,238],{},"method",", and ",[37,241,242],{},"result"," fields, passed to a shared ",[37,245,246],{},"LibTable.vue"," component.",[16,249,250],{},"This pattern emerged through AI-assisted iteration. The first version of the Luxon component might have used a different structure. By the time we got to Day.js, the pattern was stable, and the AI could generate new library components that were immediately consistent with the existing ones.",[16,252,253],{},"When I decided to add Vanilla JS and Temporal API support, the AI was able to:",[255,256,257,260,267,270],"ol",{},[99,258,259],{},"Create new components following the established pattern",[99,261,262,263,266],{},"Implement relative time logic for Vanilla JS (no library — just ",[37,264,265],{},"Date.now()"," math)",[99,268,269],{},"Set up dynamic polyfill loading for the Temporal API",[99,271,272],{},"Update the library registry, imports, and template rendering",[16,274,275],{},"This is the kind of work that would take hours of manual copy-paste-refactor. With AI assistance, it took minutes — and the result was immediately consistent with the existing codebase.",[27,277,279],{"id":278},"lessons-learned","Lessons Learned",[255,281,282,288,294,300],{},[99,283,284,287],{},[71,285,286],{},"AI excels at pattern replication."," Once a pattern is established (like the date library component structure), AI can generate new instances with high consistency.",[99,289,290,293],{},[71,291,292],{},"AI is strongest when you have a clear mental model."," I knew what the app should do and how it should be structured. AI helped me translate that vision into code faster than I could alone.",[99,295,296,299],{},[71,297,298],{},"AI struggles with \"the last 10%.\""," Edge cases, specific browser behavior, and Tailwind CSS quirks still required manual debugging. AI gets you to 90% quickly; the last 10% is where domain knowledge matters.",[99,301,302,305],{},[71,303,304],{},"The planning conversations were as valuable as the code generation."," Talking through architecture decisions with an AI forced me to articulate my thinking, which often revealed gaps in my own design.",[27,307,309],{"id":308},"whats-next","What's Next",[96,311,312,318,324],{},[99,313,314,317],{},[71,315,316],{},"More date libraries"," — Still highly experimental the Temporal API is on track to becoming the defacto replacement for using the standard Date API.",[99,319,320,323],{},[71,321,322],{},"Expanded library comparisons"," — I want to add more categories to the comparison tables. For example how different libraries handle date manipulation, like checking greater than or less than.",[99,325,326,329],{},[71,327,328],{},"i18n"," - I'd like to add internationalization to make this tool more accessible.",[27,331,333],{"id":332},"try-it","Try It",[16,335,336,337,344,345,350],{},"The project is currently live at ",[338,339,343],"a",{"href":340,"rel":341},"https://you-tz.com",[342],"nofollow","you-tz.com",". Paste any ISO string, quickly sanity-check it against the most popular Date libraries, and share the result with your team. You can also use ",[338,346,349],{"href":347,"rel":348},"https://you-tz.com/now",[342],"you-tz.com/now"," to use the current time as a starting snapshot.",[27,352,354],{"id":353},"technologies-utilized","Technologies Utilized",[356,357,358,368],"table",{},[359,360,361],"thead",{},[362,363,364],"tr",{},[365,366,367],"th",{},"Frontend",[369,370,371,377,382,387,392,397],"tbody",{},[362,372,373],{},[374,375,376],"td",{},"Vue 3",[362,378,379],{},[374,380,381],{},"Tailwind",[362,383,384],{},[374,385,386],{},"TypeScript",[362,388,389],{},[374,390,391],{},"MapLibre",[362,393,394],{},[374,395,396],{},"Pinia w/ persisted state",[362,398,399],{},[374,400,401],{},"Vite+",{"title":64,"searchDepth":403,"depth":403,"links":404},2,[405,412,416,417,418,419],{"id":29,"depth":403,"text":30,"children":406},[407,409,410,411],{"id":50,"depth":408,"text":51},3,{"id":77,"depth":408,"text":78},{"id":90,"depth":408,"text":91},{"id":152,"depth":408,"text":153},{"id":159,"depth":403,"text":160,"children":413},[414,415],{"id":166,"depth":408,"text":167},{"id":207,"depth":408,"text":208},{"id":278,"depth":403,"text":279},{"id":308,"depth":403,"text":309},{"id":332,"depth":403,"text":333},{"id":353,"depth":403,"text":354},"A tool to help developers visualize date parsing across timezones and popular JavaScript date libraries.",null,"md",true,{"items":425},[426],"/projects/you-tz/home-dark.jpg","You-TZ",false,"/projects/you-tz","2026-05-27T00:00:00.000Z",{"description":420},{"loc":429,"lastmod":433,"changefreq":434,"priority":435},"2026-05-27","monthly",0.8,"draft","projects/7.you-tz","Timezones = fun",[440,441,442,443,109,115,381,386],"Vue","AI","Tooling","Moment","/projects/you-tz/thumb.webp","-KwIi-6g14QwpJhxgTdfS06tREUNViY_X97r8V9X_JY",{"id":447,"title":448,"additionalTags":449,"body":450,"description":1152,"excerpt":421,"extension":422,"featured":423,"meta":1153,"name":448,"navigation":423,"openSource":428,"path":1159,"projectDate":1160,"projectFolder":1161,"seo":1162,"sitemap":1163,"status":1165,"stem":1166,"subtitle":1167,"tags":1168,"thumbnail":1171,"__hash__":1172},"projects/projects/1.portfolio-refresh.md","Portfolio Refresh",[],{"type":9,"value":451,"toc":1145},[452,455,458,462,482,486,489,493,496,499,502,506,510,513,516,898,901,1038,1045,1066,1073,1102,1104,1141],[12,453],{":stats":454},"[{\"label\": \"release date\", \"value\": \"2025\"}]",[16,456,457],{},"Welcome to my 2025 refreshed portfolio.",[27,459,461],{"id":460},"goals","Goals",[255,463,464,470,476],{},[99,465,466,469],{},[71,467,468],{},"Speed"," - It had to be fast and I wanted to get as close to a perfect Lighthouse score as possible.",[99,471,472,475],{},[71,473,474],{},"Modern"," - I wanted to utilize the latest tech, Nuxt, Tailwind, and GSAP for subtle animations & micro-interactions.",[99,477,478,481],{},[71,479,480],{},"Learn Something New"," - Get out of my comfort zone and try new things.",[27,483,485],{"id":484},"results","Results",[487,488],"app-lighthouse-results",{},[27,490,492],{"id":491},"process","Process",[16,494,495],{},"I knew from the very beginning I wanted to stick with Vue but I wanted to take it a step further and explore the Nuxt ecosystem which up to this point I hadn't really had a chance or reason to use.",[16,497,498],{},"Choosing Nuxt lead me to Nuxt UI which brought with it Tailwind, which was another tech that I had minimal experience with but that I wanted to get more familiar with.",[16,500,501],{},"I also knew I wanted to host on Vercel's Edge network as I felt that would get me closer to that perfect Lighthouse score.",[27,503,505],{"id":504},"animations","Animations",[507,508],"app-sticker",{":replayable":509},"true",[16,511,512],{},"The opening sticker animation was made using an SVG that I designed in Adobe Illustrator and then animated the writing in GSAP.",[16,514,515],{},"The entire writing animation is a mere 6 lines of code.",[56,517,521],{"className":518,"code":519,"language":520,"meta":64,"style":64},"language-vue shiki shiki-themes material-theme-lighter monokai monokai","\u003Cscript setup>\nonMounted(() => {\n    gsap.set(\"#sig-1\", { drawSVG: '0%' });\n    gsap.set(\"#sig-2\", { drawSVG: '0%' });\n    const tl = gsap.timeline({ \n        defaults: { duration: .6, delay: .3, ease: 'power1.inOut' } });\n    tl.to('#sticker', { y: 0, opacity: 1 });\n    tl.to(\"#sig-1\", { drawSVG: '-100%', delay: 0.4 });\n    tl.to(\"#sig-2\", { drawSVG: '100%', delay: -.01 });\n})\n\u003C/script>\n","vue",[37,522,523,543,563,616,654,683,734,782,829,879,888],{"__ignoreMap":64},[524,525,528,532,536,540],"span",{"class":526,"line":527},"line",1,[524,529,531],{"class":530},"sqipZ","\u003C",[524,533,535],{"class":534},"sDhRb","script",[524,537,539],{"class":538},"s4WCV"," setup",[524,541,542],{"class":530},">\n",[524,544,545,549,553,556,560],{"class":526,"line":403},[524,546,548],{"class":547},"sj8bM","onMounted",[524,550,552],{"class":551},"s--uY","(",[524,554,555],{"class":530},"()",[524,557,559],{"class":558},"sMInQ"," =>",[524,561,562],{"class":530}," {\n",[524,564,565,568,571,574,577,581,585,587,590,593,596,599,602,605,608,611,613],{"class":526,"line":408},[524,566,567],{"class":551},"    gsap",[524,569,570],{"class":530},".",[524,572,573],{"class":547},"set",[524,575,552],{"class":576},"sFVGM",[524,578,580],{"class":579},"sl1cq","\"",[524,582,584],{"class":583},"seZNR","#sig-1",[524,586,580],{"class":579},[524,588,589],{"class":530},",",[524,591,592],{"class":530}," {",[524,594,595],{"class":576}," drawSVG",[524,597,598],{"class":530},":",[524,600,601],{"class":579}," '",[524,603,604],{"class":583},"0%",[524,606,607],{"class":579},"'",[524,609,610],{"class":530}," }",[524,612,195],{"class":576},[524,614,615],{"class":530},";\n",[524,617,619,621,623,625,627,629,632,634,636,638,640,642,644,646,648,650,652],{"class":526,"line":618},4,[524,620,567],{"class":551},[524,622,570],{"class":530},[524,624,573],{"class":547},[524,626,552],{"class":576},[524,628,580],{"class":579},[524,630,631],{"class":583},"#sig-2",[524,633,580],{"class":579},[524,635,589],{"class":530},[524,637,592],{"class":530},[524,639,595],{"class":576},[524,641,598],{"class":530},[524,643,601],{"class":579},[524,645,604],{"class":583},[524,647,607],{"class":579},[524,649,610],{"class":530},[524,651,195],{"class":576},[524,653,615],{"class":530},[524,655,657,660,663,667,670,672,675,677,680],{"class":526,"line":656},5,[524,658,659],{"class":558},"    const",[524,661,662],{"class":551}," tl",[524,664,666],{"class":665},"s-IWT"," =",[524,668,669],{"class":551}," gsap",[524,671,570],{"class":530},[524,673,674],{"class":547},"timeline",[524,676,552],{"class":576},[524,678,679],{"class":530},"{",[524,681,682],{"class":576}," \n",[524,684,686,689,691,693,696,698,702,704,707,709,712,714,717,719,721,724,726,728,730,732],{"class":526,"line":685},6,[524,687,688],{"class":576},"        defaults",[524,690,598],{"class":530},[524,692,592],{"class":530},[524,694,695],{"class":576}," duration",[524,697,598],{"class":530},[524,699,701],{"class":700},"sfpNJ"," .6",[524,703,589],{"class":530},[524,705,706],{"class":576}," delay",[524,708,598],{"class":530},[524,710,711],{"class":700}," .3",[524,713,589],{"class":530},[524,715,716],{"class":576}," ease",[524,718,598],{"class":530},[524,720,601],{"class":579},[524,722,723],{"class":583},"power1.inOut",[524,725,607],{"class":579},[524,727,610],{"class":530},[524,729,610],{"class":530},[524,731,195],{"class":576},[524,733,615],{"class":530},[524,735,737,740,742,745,747,749,752,754,756,758,761,763,766,768,771,773,776,778,780],{"class":526,"line":736},7,[524,738,739],{"class":551},"    tl",[524,741,570],{"class":530},[524,743,744],{"class":547},"to",[524,746,552],{"class":576},[524,748,607],{"class":579},[524,750,751],{"class":583},"#sticker",[524,753,607],{"class":579},[524,755,589],{"class":530},[524,757,592],{"class":530},[524,759,760],{"class":576}," y",[524,762,598],{"class":530},[524,764,765],{"class":700}," 0",[524,767,589],{"class":530},[524,769,770],{"class":576}," opacity",[524,772,598],{"class":530},[524,774,775],{"class":700}," 1",[524,777,610],{"class":530},[524,779,195],{"class":576},[524,781,615],{"class":530},[524,783,785,787,789,791,793,795,797,799,801,803,805,807,809,812,814,816,818,820,823,825,827],{"class":526,"line":784},8,[524,786,739],{"class":551},[524,788,570],{"class":530},[524,790,744],{"class":547},[524,792,552],{"class":576},[524,794,580],{"class":579},[524,796,584],{"class":583},[524,798,580],{"class":579},[524,800,589],{"class":530},[524,802,592],{"class":530},[524,804,595],{"class":576},[524,806,598],{"class":530},[524,808,601],{"class":579},[524,810,811],{"class":583},"-100%",[524,813,607],{"class":579},[524,815,589],{"class":530},[524,817,706],{"class":576},[524,819,598],{"class":530},[524,821,822],{"class":700}," 0.4",[524,824,610],{"class":530},[524,826,195],{"class":576},[524,828,615],{"class":530},[524,830,832,834,836,838,840,842,844,846,848,850,852,854,856,859,861,863,865,867,870,873,875,877],{"class":526,"line":831},9,[524,833,739],{"class":551},[524,835,570],{"class":530},[524,837,744],{"class":547},[524,839,552],{"class":576},[524,841,580],{"class":579},[524,843,631],{"class":583},[524,845,580],{"class":579},[524,847,589],{"class":530},[524,849,592],{"class":530},[524,851,595],{"class":576},[524,853,598],{"class":530},[524,855,601],{"class":579},[524,857,858],{"class":583},"100%",[524,860,607],{"class":579},[524,862,589],{"class":530},[524,864,706],{"class":576},[524,866,598],{"class":530},[524,868,869],{"class":665}," -",[524,871,872],{"class":700},".01",[524,874,610],{"class":530},[524,876,195],{"class":576},[524,878,615],{"class":530},[524,880,882,885],{"class":526,"line":881},10,[524,883,884],{"class":530},"}",[524,886,887],{"class":551},")\n",[524,889,891,894,896],{"class":526,"line":890},11,[524,892,893],{"class":530},"\u003C/",[524,895,535],{"class":534},[524,897,542],{"class":530},[16,899,900],{},"The sticker's dropshadow was made using an SVG filter:",[56,902,906],{"className":903,"code":904,"language":905,"meta":64,"style":64},"language-html shiki shiki-themes material-theme-lighter monokai monokai","\u003Csvg ...>\n  \u003Cdefs>\n      \u003Cfilter id=\"shadow\">\n          \u003CfeDropShadow dx=\"0\" dy=\"6\" stdDeviation=\"7\" flood-opacity=\"0.3\" />\n      \u003C/filter>\n  \u003C/defs>\n\u003C/svg>\n","html",[37,907,908,920,930,953,1012,1021,1030],{"__ignoreMap":64},[524,909,910,912,915,918],{"class":526,"line":527},[524,911,531],{"class":530},[524,913,914],{"class":534},"svg",[524,916,917],{"class":538}," ...",[524,919,542],{"class":530},[524,921,922,925,928],{"class":526,"line":403},[524,923,924],{"class":530},"  \u003C",[524,926,927],{"class":534},"defs",[524,929,542],{"class":530},[524,931,932,935,938,941,944,946,949,951],{"class":526,"line":408},[524,933,934],{"class":530},"      \u003C",[524,936,937],{"class":534},"filter",[524,939,940],{"class":538}," id",[524,942,943],{"class":530},"=",[524,945,580],{"class":579},[524,947,948],{"class":583},"shadow",[524,950,580],{"class":579},[524,952,542],{"class":530},[524,954,955,958,961,964,966,968,971,973,976,978,980,983,985,988,990,992,995,997,1000,1002,1004,1007,1009],{"class":526,"line":618},[524,956,957],{"class":530},"          \u003C",[524,959,960],{"class":534},"feDropShadow",[524,962,963],{"class":538}," dx",[524,965,943],{"class":530},[524,967,580],{"class":579},[524,969,970],{"class":583},"0",[524,972,580],{"class":579},[524,974,975],{"class":538}," dy",[524,977,943],{"class":530},[524,979,580],{"class":579},[524,981,982],{"class":583},"6",[524,984,580],{"class":579},[524,986,987],{"class":538}," stdDeviation",[524,989,943],{"class":530},[524,991,580],{"class":579},[524,993,994],{"class":583},"7",[524,996,580],{"class":579},[524,998,999],{"class":538}," flood-opacity",[524,1001,943],{"class":530},[524,1003,580],{"class":579},[524,1005,1006],{"class":583},"0.3",[524,1008,580],{"class":579},[524,1010,1011],{"class":530}," />\n",[524,1013,1014,1017,1019],{"class":526,"line":656},[524,1015,1016],{"class":530},"      \u003C/",[524,1018,937],{"class":534},[524,1020,542],{"class":530},[524,1022,1023,1026,1028],{"class":526,"line":685},[524,1024,1025],{"class":530},"  \u003C/",[524,1027,927],{"class":534},[524,1029,542],{"class":530},[524,1031,1032,1034,1036],{"class":526,"line":736},[524,1033,893],{"class":530},[524,1035,914],{"class":534},[524,1037,542],{"class":530},[16,1039,1040,1041,1044],{},"and then applied onto the ",[37,1042,1043],{},"\u003Csvg/>"," using a regular style attribute:",[56,1046,1048],{"className":903,"code":1047,"language":905,"meta":64,"style":64},"\u003Csvg style=\"filter: url('#shadow'); ...\n",[37,1049,1050],{"__ignoreMap":64},[524,1051,1052,1054,1056,1059,1061,1063],{"class":526,"line":527},[524,1053,531],{"class":530},[524,1055,914],{"class":534},[524,1057,1058],{"class":538}," style",[524,1060,943],{"class":530},[524,1062,580],{"class":579},[524,1064,1065],{"class":583},"filter: url('#shadow'); ...\n",[16,1067,1068,1069,1072],{},"The ",[37,1070,1071],{},"v-gsap-nuxt"," module makes it even easier to animate DOM elements simply through specialized attributes.\nThis is method I used on the work history page to animate the history entries in as the page scrolls.",[56,1074,1078],{"className":1075,"code":1076,"language":1077,"meta":64,"style":64},"language-vue-html shiki shiki-themes material-theme-lighter monokai monokai","\u003Celement v-gsap.whenVisible.once.stagger.from=\"{ opacity: 0, x: -10, stagger: 0.2 }\" >\n","vue-html",[37,1079,1080],{"__ignoreMap":64},[524,1081,1082,1084,1087,1090,1092,1094,1097,1099],{"class":526,"line":527},[524,1083,531],{"class":530},[524,1085,1086],{"class":534},"element",[524,1088,1089],{"class":538}," v-gsap.whenVisible.once.stagger.from",[524,1091,943],{"class":530},[524,1093,580],{"class":579},[524,1095,1096],{"class":583},"{ opacity: 0, x: -10, stagger: 0.2 }",[524,1098,580],{"class":579},[524,1100,1101],{"class":530}," >\n",[27,1103,354],{"id":353},[356,1105,1106,1112],{},[359,1107,1108],{},[362,1109,1110],{},[365,1111,367],{},[369,1113,1114,1119,1123,1128,1132,1137],{},[362,1115,1116],{},[374,1117,1118],{},"Nuxt",[362,1120,1121],{},[374,1122,376],{},[362,1124,1125],{},[374,1126,1127],{},"Nuxt UI",[362,1129,1130],{},[374,1131,381],{},[362,1133,1134],{},[374,1135,1136],{},"GSAP",[362,1138,1139],{},[374,1140,386],{},[1142,1143,1144],"style",{},"html pre.shiki code .sqipZ, html code.shiki .sqipZ{--shiki-light:#39ADB5;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sDhRb, html code.shiki .sDhRb{--shiki-light:#E53935;--shiki-default:#F92672;--shiki-dark:#F92672}html pre.shiki code .s4WCV, html code.shiki .s4WCV{--shiki-light:#9C3EDA;--shiki-default:#A6E22E;--shiki-dark:#A6E22E}html pre.shiki code .sj8bM, html code.shiki .sj8bM{--shiki-light:#6182B8;--shiki-default:#A6E22E;--shiki-dark:#A6E22E}html pre.shiki code .s--uY, html code.shiki .s--uY{--shiki-light:#90A4AE;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sMInQ, html code.shiki .sMInQ{--shiki-light:#9C3EDA;--shiki-light-font-style:inherit;--shiki-default:#66D9EF;--shiki-default-font-style:italic;--shiki-dark:#66D9EF;--shiki-dark-font-style:italic}html pre.shiki code .sFVGM, html code.shiki .sFVGM{--shiki-light:#E53935;--shiki-default:#F8F8F2;--shiki-dark:#F8F8F2}html pre.shiki code .sl1cq, html code.shiki .sl1cq{--shiki-light:#39ADB5;--shiki-default:#E6DB74;--shiki-dark:#E6DB74}html pre.shiki code .seZNR, html code.shiki .seZNR{--shiki-light:#91B859;--shiki-default:#E6DB74;--shiki-dark:#E6DB74}html pre.shiki code .s-IWT, html code.shiki .s-IWT{--shiki-light:#39ADB5;--shiki-default:#F92672;--shiki-dark:#F92672}html pre.shiki code .sfpNJ, html code.shiki .sfpNJ{--shiki-light:#F76D47;--shiki-default:#AE81FF;--shiki-dark:#AE81FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":64,"searchDepth":403,"depth":403,"links":1146},[1147,1148,1149,1150,1151],{"id":460,"depth":403,"text":461},{"id":484,"depth":403,"text":485},{"id":491,"depth":403,"text":492},{"id":504,"depth":403,"text":505},{"id":353,"depth":403,"text":354},"Rebuilding my website with modern tech.",{"items":1154},[1155,1156,1157,1158],"/projects/crateos/home-dark.jpg","/projects/crateos/home.jpg","/projects/crateos/recall.jpg","/projects/crateos/recall-dark.jpg","/projects/portfolio-refresh","2025-05-01T00:00:00.000Z","portfolio",{"description":1152},{"loc":1159,"lastmod":1164,"changefreq":434,"priority":435},"2025-05-18","published","projects/1.portfolio-refresh","Gotta go fast",[1169,1118,1136,381,386,1170],"VueJS","Git","/projects/portfolio/thumb.webp","M4YhF6ek6gmJCn2-LHVMfJOplsjQLkCtoWvC89T_Iho",{"id":1174,"title":1175,"additionalTags":1176,"body":1177,"description":1266,"excerpt":421,"extension":422,"featured":423,"meta":1267,"name":1185,"navigation":423,"openSource":428,"path":1270,"projectDate":1271,"projectFolder":1272,"seo":1273,"sitemap":1274,"status":1165,"stem":1275,"subtitle":1276,"tags":1277,"thumbnail":1282,"__hash__":1283},"projects/projects/2.crateos-recalls.md","Crateos Recalls",[],{"type":9,"value":1178,"toc":1264},[1179,1191,1196,1199,1205,1208,1260],[16,1180,1181,1186,1187,570],{},[338,1182,1185],{"href":1183,"rel":1184},"https://recalls.crateos.com",[342],"CrateOS Recalls"," is a web application that\nI created to make it easier to discover product recalls. I wanted to get out of my comfort zone and learn new technologies along the way.\nTutorials and documentation are great but I feel I learn best by ",[1188,1189,1190],"em",{},"building",[1192,1193],"problem-solution",{"problem":1194,"solution":1195},"The recall process is often confusing, time consuming, and parents are too busy to dedicate the time & effort.","Make the recall discovery process easier and enable tailored recall alerts on a per-company basis.",[16,1197,1198],{},"The result is a Solo-SaaS project and the culmination of my experience in designing and developing web applications.",[1200,1201],"player",{"posterDesc":1202,"posterSrc":1203,"src":1204},"A brief walkthrough of the CrateOS Recalls app.","https://www.crateos.com/images/demo-poster.gif","https://www.crateos.com/media/crateos-recalls-promo-720.mp4",[1206,1207,354],"h4",{"id":353},[356,1209,1210,1219],{},[359,1211,1212],{},[362,1213,1214,1216],{},[365,1215,367],{},[365,1217,1218],{},"Backend",[369,1220,1221,1228,1236,1244,1252],{},[362,1222,1223,1225],{},[374,1224,376],{},[374,1226,1227],{},"ExpressJS",[362,1229,1230,1233],{},[374,1231,1232],{},"Composition API",[374,1234,1235],{},"Loopback",[362,1237,1238,1241],{},[374,1239,1240],{},"Pinia",[374,1242,1243],{},"PostgreSQL",[362,1245,1246,1249],{},[374,1247,1248],{},"VueUse",[374,1250,1251],{},"ElasticSearch",[362,1253,1254,1257],{},[374,1255,1256],{},"Bulma / Buefy",[374,1258,1259],{},"NodeJS",[1261,1262],"image-carousel",{":items":1263},"[\"/projects/crateos/home-dark.jpg\",\"/projects/crateos/home.jpg\",\"/projects/crateos/recall.jpg\", \"/projects/crateos/recall-dark.jpg\"]",{"title":64,"searchDepth":403,"depth":403,"links":1265},[],"Tailored CPSC product recalls for parents & busy people.",{"url":1268,"items":1269},"https://crateos.com",[1155,1156,1157,1158],"/projects/crateos-recalls","2025-01-01T00:00:00.000Z","crateos",{"description":1266},{"loc":1270,"lastmod":1164,"changefreq":434,"priority":435},"projects/2.crateos-recalls","Solo Founder + Full Stack + Design  + Branding",[1169,1278,1279,386,1280,367,1218,1281,1170],"Bulma","SCSS","Postgres","PWA","/projects/crateos/thumb.webp","HNKsQ-a0MIt814lvY_ffinVj9rvm7M40Gg6QueWmYe0",{"id":1285,"title":1286,"additionalTags":1287,"body":1291,"description":1510,"excerpt":421,"extension":422,"featured":428,"meta":1511,"name":1512,"navigation":423,"openSource":428,"path":1513,"projectDate":1514,"projectFolder":1515,"seo":1516,"sitemap":1517,"status":64,"stem":1518,"subtitle":1519,"tags":1520,"thumbnail":1526,"__hash__":1527},"projects/projects/4.headlight.md","Headlight",[1288,1289,1290],"typescript","testing","leadership",{"type":9,"value":1292,"toc":1504},[1293,1301,1312,1316,1319,1324,1328,1338,1341,1345,1348,1430,1432,1501],[16,1294,1295,1300],{},[338,1296,1299],{"href":1297,"rel":1298},"https://headlight.com",[342],"HeadLight"," is a suite of advanced digital construction management applications.",[16,1302,1303,1304,1307,1308,1311],{},"For over 9 years at HeadLight (previously Pavia Systems) my involvement included ",[71,1305,1306],{},"UI/UX design"," for the native iOS application\nand leading the ",[71,1309,1310],{},"front-end development"," for the HeadLight Suite of web applications.",[48,1313,1315],{"id":1314},"wireframe-to-final-product","Wireframe to Final Product",[16,1317,1318],{},"I was involved from the very beginning with designing mockups for the native IOS app and through to building & shipping web applications.",[1320,1321],"app-before-after",{"after":1322,"before":1323},"/projects/headlight/after.webp","/projects/headlight/before.webp",[48,1325,1327],{"id":1326},"measuring-success","Measuring Success",[16,1329,1330,1331,1334,1335,570],{},"The FieldBook apps would enable field personnel to capture ",[71,1332,1333],{},"millions of Observations"," across ",[71,1336,1337],{},"tens of thousands of construction projects",[16,1339,1340],{},"While the native iOS app was used primarily used for capturing in the field.\nThe web app which had feature-parity and was specifically geared for accessing project data by office personnel.",[48,1342,1344],{"id":1343},"from-app-to-comprehensive-suite","From App to Comprehensive Suite",[16,1346,1347],{},"Moving to a shared code architecture, which AngularJS's module system was very well suited for,\nenabled us to quickly build and ship a entire suite specialized applications covering many aspects of e-construction.",[356,1349,1350,1360],{},[359,1351,1352],{},[362,1353,1354,1357],{},[365,1355,1356],{},"AngularJS Apps",[365,1358,1359],{},"VueJS Apps",[369,1361,1362,1370,1378,1386,1394,1402,1409,1416,1423],{},[362,1363,1364,1367],{},[374,1365,1366],{},"FieldBook",[374,1368,1369],{},"Contract Admin",[362,1371,1372,1375],{},[374,1373,1374],{},"Tracker",[374,1376,1377],{},"SamplePlan v2",[362,1379,1380,1383],{},[374,1381,1382],{},"Portal",[374,1384,1385],{},"Materials v2",[362,1387,1388,1391],{},[374,1389,1390],{},"Vault",[374,1392,1393],{},"Dashboards",[362,1395,1396,1399],{},[374,1397,1398],{},"SamplePlan",[374,1400,1401],{},"Covid-19 Safety",[362,1403,1404,1407],{},[374,1405,1406],{},"Profile Mgmt",[374,1408],{},[362,1410,1411,1414],{},[374,1412,1413],{},"Customer Mgmt",[374,1415],{},[362,1417,1418,1421],{},[374,1419,1420],{},"Project Mgmt",[374,1422],{},[362,1424,1425,1428],{},[374,1426,1427],{},"Materials",[374,1429],{},[48,1431,354],{"id":353},[356,1433,1434,1443],{},[359,1435,1436],{},[362,1437,1438,1440],{},[365,1439,367],{},[365,1441,1442],{},"Testing",[369,1444,1445,1453,1460,1468,1475,1481,1488,1495],{},[362,1446,1447,1450],{},[374,1448,1449],{},"AngularJS",[374,1451,1452],{},"Mocha",[362,1454,1455,1457],{},[374,1456,1169],{},[374,1458,1459],{},"Jest",[362,1461,1462,1465],{},[374,1463,1464],{},"Bootstrap",[374,1466,1467],{},"Chai",[362,1469,1470,1472],{},[374,1471,1170],{},[374,1473,1474],{},"Karma",[362,1476,1477,1479],{},[374,1478,1279],{},[374,1480],{},[362,1482,1483,1486],{},[374,1484,1485],{},"Gulp",[374,1487],{},[362,1489,1490,1493],{},[374,1491,1492],{},"Grunt",[374,1494],{},[362,1496,1497,1499],{},[374,1498,386],{},[374,1500],{},[1261,1502],{":items":1503},"[\"/projects/headlight/hl-01.png\",\"/projects/headlight/hl-02.png\",\"/projects/headlight/hl-03.png\"]",{"title":64,"searchDepth":403,"depth":403,"links":1505},[1506,1507,1508,1509],{"id":1314,"depth":408,"text":1315},{"id":1326,"depth":408,"text":1327},{"id":1343,"depth":408,"text":1344},{"id":353,"depth":408,"text":354},"Comprehensive suite of e-construction web applications.",{"url":1297},"HeadLight Suite","/projects/headlight","2024-05-01T00:00:00.000Z","headlight",{"description":1510},{"loc":1513,"lastmod":1164,"changefreq":434,"priority":435},"projects/4.headlight","UI/UX + Front-end development + Leadership",[1449,1169,1464,1279,386,1452,1474,1459,1521,1170,1522,1523,1524,1525],"Parcel","Docker","Quasar","Capacitor","Cordova","/projects/headlight/thumb.webp","C6IrPdywUI3yeY_Y3xi-qn4k9HG2M7F-6-4VRdEcWOc",{"id":1529,"title":1530,"additionalTags":1531,"body":1532,"description":1737,"excerpt":421,"extension":422,"featured":423,"meta":1738,"name":1739,"navigation":423,"openSource":428,"path":1740,"projectDate":1741,"projectFolder":1742,"seo":1743,"sitemap":1744,"status":1165,"stem":1746,"subtitle":1747,"tags":1748,"thumbnail":1755,"__hash__":1756},"projects/projects/3.shooting-gallery-for-playdate.md","Shooting Gallery For Playdate",[],{"type":9,"value":1533,"toc":1730},[1534,1537,1541,1544,1550,1554,1563,1571,1592,1597,1601,1608,1623,1628,1637,1642,1649,1658,1663,1672,1681,1685,1688,1699,1706,1710,1720],[12,1535],{":stats":1536},"[{\"label\": \"release date\", \"value\": \"2023\"}, {\"label\": \"rating\", \"stars\":5 }, {\"label\": \"downloads\", \"value\": \"390+\"}, {\"label\": \"URL\", \"value\": \"itch.io\", \"url\": \"https://limitlis.itch.io/shooting-gallery\"}]",[48,1538,1540],{"id":1539},"step-right-up","Step right up!",[16,1542,1543],{},"Aim for the middle and test your mettle against a volley of tricky targets, diabolical ducks, and bewitched bombs as they float tauntingly across your playdate. Use PowerUps to your advantage to reach the top of the high score leaderboard.\nSet a high score and then hand the playdate to a friend to see if they can beat it.",[1545,1546,1547],"blockquote",{},[16,1548,1549],{},"\"incredibly high polish on the concept\" - LedBetter Games",[48,1551,1553],{"id":1552},"inspiration","Inspiration",[16,1555,1556,1557,1562],{},"From the day it was first announced I knew I wanted to make a game for the yellow ",[338,1558,1561],{"href":1559,"rel":1560},"https://play.date/",[342],"Playdate"," console and immediately pre-ordered one.",[16,1564,1565,1566,570],{},"Having never written a single line of Lua, I went from designing and building to self-publishing and releasing my first indie game on ",[338,1567,1570],{"href":1568,"rel":1569},"https://limitlis.itch.io/shooting-gallery",[342],"itch.io",[1572,1573,1578],"div",{"className":1574},[1575,1576,1577],"h-auto","w-auto","aspect-3-2",[16,1579,1580],{},[19,1581],{"alt":1582,"className":1583,"src":1590,"width":1591},"Gameplay",[1584,1585,1586,23,1587,1588,1577,1589],"not-prose","rounded","h-48","md:h-full","md:h-48","object-contain","/projects/playdate/gameplay.gif",400,[1545,1593,1594],{},[16,1595,1596],{},"\"I like the duck game\" – My kids",[48,1598,1600],{"id":1599},"gameplay-mechanics","Gameplay Mechanics",[16,1602,1603],{},[338,1604,1607],{"href":64,"className":1605},[1606],"text-lg","PowerUps",[16,1609,1610,1621],{},[19,1611],{"alt":1612,"className":1613,"src":1618,"width":1619,"style":1620},"Time Bonus",[1614,1615,1616,1617],"inline-flex","p-1","object-cover","pointer-none","/projects/playdate/time-bonus.gif",30,"margin: 0; margin-right: 10px; zoom: 1.5; background-color: #b1aea7; aspect-ratio: 1; width: 40px;",[71,1622,1612],{},[96,1624,1625],{},[99,1626,1627],{},"Adds seconds to the clock to extend your current game.",[16,1629,1630,1634],{},[19,1631],{"alt":1612,"className":1632,"src":1633,"width":1619,"style":1620},[1614,1615,1616,1617],"/projects/playdate/phantom-ammo.gif",[71,1635,1636],{},"Phantom Ammo",[96,1638,1639],{},[99,1640,1641],{},"Shoot to stop at a random number and that amount of phantom ammo will be added without a reloading or resetting your hit streak.",[1545,1643,1644],{},[16,1645,1646],{},[1188,1647,1648],{},"Reloading will be prevented until all phantom rounds are spent.",[16,1650,1651,1655],{},[19,1652],{"alt":1612,"className":1653,"src":1654,"width":1619,"style":1620},[1614,1615,1616,1617],"/projects/playdate/point-bomb.png",[71,1656,1657],{},"Point Bombs",[96,1659,1660],{},[99,1661,1662],{},"Shoot one and a bomb card will appear in your hit streak. Clear the card before the reload counter reaches 0 and receive the points.\nOtherwise those points will be removed from your current score.",[16,1664,1665,1670],{},[19,1666],{"alt":1667,"className":1668,"src":1669,"width":1619,"style":1620},"Shiny Targets",[1614,1615,1616,1617],"/projects/playdate/shiny-target.webp",[71,1671,1667],{},[96,1673,1674],{},[99,1675,1676,1677,1680],{},"Shiny targets will ",[71,1678,1679],{},"2X"," the score for the first three hits, being worth 2, 4, 6, 8 or 10 depending on your accuracy.",[48,1682,1684],{"id":1683},"development-challenges","Development Challenges",[16,1686,1687],{},"Getting the duck's movement just right was pretty challenging early on while I was still figuring out the SDK. I had a general idea of how I wanted the movement to be\nbut most importantly it had to feel mechanical — as if driven by gears. The SDK has built in support for making arcs but getting the random\nmovement took some math to get just right.",[16,1689,1690,1691,1694,1695,1698],{},"Here's a small diagram I made to help me figure out where to place the next arc based on a random ",[71,1692,1693],{},"radius","\nand the duck's current ",[71,1696,1697],{},"X"," position.",[16,1700,1701],{},[19,1702],{"alt":1703,"className":1704,"src":1705,"width":1591},"Arc Math",[23],"/projects/playdate/arcmath.webp",[48,1707,1709],{"id":1708},"nerdy-stats","Nerdy Stats",[16,1711,1712,1713,1719],{},"For source control I set up a local ",[338,1714,1718],{"href":1715,"rel":1716,"target":1717},"https://about.gitea.com/",[342],"_blank","Gittea"," instance on my home Network Attached Storage (NAS).",[1721,1722,1723],"client-only",{},[1724,1725,1729],"iframe",{"frameBorder":970,"src":1726,"width":1727,"height":1728},"https://itch.io/embed/1837225?border_width=2&bg_color=18181c&fg_color=a3a5aa&link_color=1fcd9f&border_color=26262f",554,169,"\u003Ca href=\"https://limitlis.itch.io/shooting-gallery\">SHOOTING GALLERY for Playdate by limitlis\u003C/a>",{"title":64,"searchDepth":403,"depth":403,"links":1731},[1732,1733,1734,1735,1736],{"id":1539,"depth":408,"text":1540},{"id":1552,"depth":408,"text":1553},{"id":1599,"depth":408,"text":1600},{"id":1683,"depth":408,"text":1684},{"id":1708,"depth":408,"text":1709},"A carnival inspired game for the Playdate console.",{"url":1568},"Shooting Gallery","/projects/shooting-gallery-for-playdate","2023-10-01T00:00:00.000Z","playdate",{"description":1737},{"loc":1740,"lastmod":1745,"changefreq":434,"priority":435},"2026-02-22","projects/3.shooting-gallery-for-playdate","Game Design & Development",[1749,1750,1751,1752,1753,1754,1170],"Lua","Playdate SDK","Graphic Design","SFX","Game design","Game Development","/projects/playdate/thumb.webp","SWFGBuIzL6R-vQDU-pYf1OPGxJ4y2MXQOD3Ws87fMV0",{"id":1758,"title":1759,"additionalTags":1760,"body":1761,"description":1809,"excerpt":421,"extension":422,"featured":428,"meta":1810,"name":1811,"navigation":423,"openSource":428,"path":1812,"projectDate":1813,"projectFolder":1814,"seo":1815,"sitemap":1816,"status":436,"stem":1817,"subtitle":1818,"tags":1819,"thumbnail":1825,"__hash__":1826},"projects/projects/5.enamel-pin.md","Enamel Pin",[],{"type":9,"value":1762,"toc":1804},[1763,1766,1770,1773,1779,1783,1786,1789,1791,1794,1801],[12,1764],{":stats":1765},"[{\"label\": \"Farthest Backer\", \"value\": \"> 8,000 miles\"}]",[27,1767,1769],{"id":1768},"overview","Overview",[16,1771,1772],{},"\"Don't @ me bro\" is an enamel pin that I designed and was meant as a tongue-in-cheek take on how disruptive notifications can be when\nworking from home became a reality for many during the Covid pandemic.",[16,1774,1775],{},[19,1776],{"alt":1777,"src":1778},"Enamel pin and packaging","/projects/enamel-pin/pin-01.jpg",[27,1780,1782],{"id":1781},"challenges","Challenges",[16,1784,1785],{},"By far the biggest issue that came up was that my pin manufacturer made a mistake with the color of the phosphorescence.\nUnfortunately this was't made apparent until the pins arrived at my door.",[16,1787,1788],{},"I had to approach my backers with the bad news, apologized for the error and offered refunds but everyone was still excited even with the standard green glow color.",[27,1790,485],{"id":484},[16,1792,1793],{},"From Seattle to backers across the world with the farthest pin going over 8,000 miles away to Singapore.\nOverall the campaign was a success and I learned a lot along the way.",[16,1795,1796],{},[19,1797],{"alt":1798,"src":1799,"className":1800},"Pins shipped across the world","/projects/enamel-pin/map.webp",[23],[1261,1802],{":items":1803},"[ \"/projects/enamel-pin/pin-02.jpg\", \"/projects/enamel-pin/pin-04.jpg\", \"/projects/enamel-pin/pin-03.gif\", \"/projects/enamel-pin/pin-05.webp\",\"/projects/enamel-pin/pin-07.webp\"]",{"title":64,"searchDepth":403,"depth":403,"links":1805},[1806,1807,1808],{"id":1768,"depth":403,"text":1769},{"id":1781,"depth":403,"text":1782},{"id":484,"depth":403,"text":485},"Glow-in-the-dark enamel pin design",{},"Don't @ Me - Enamel Pin","/projects/enamel-pin","2020-07-01T00:00:00.000Z","enamel-pin",{"description":1809},{"loc":1159,"lastmod":1164,"changefreq":434,"priority":435},"projects/5.enamel-pin","Graphic design + illustration + crowd funding",[1820,1751,1821,1822,1823,1824],"Illustration","Motion Graphics","Crowdfunding","Order fulfillment","Kickstarter","/projects/enamel-pin/thumb.webp","8cqe7-ZK4DA4zU8cyKfppwXFIsDpv6JG8D0myKNwzIU",{"id":1828,"title":1829,"additionalTags":1830,"body":1831,"description":1858,"excerpt":421,"extension":422,"featured":428,"meta":1859,"name":1829,"navigation":423,"openSource":428,"path":1860,"projectDate":1861,"projectFolder":1862,"seo":1863,"sitemap":1864,"status":436,"stem":1865,"subtitle":1866,"tags":1867,"thumbnail":1870,"__hash__":1871},"projects/projects/3.stohke.md","Stohke",[],{"type":9,"value":1832,"toc":1856},[1833,1836,1843,1846,1849,1853],[16,1834,1835],{},"Stohke was a social network whose aim was to bring the world's best brands, athletes and causes to your fingertips.",[16,1837,1838],{},[19,1839],{"alt":1840,"className":1841,"src":1842},"'Stohke mobile app redesign'",[1584,23],"/projects/stohke/app-promo-images.webp",[16,1844,1845],{},"I started contracting on my free time and pitching in on their existing AngularJS application.",[16,1847,1848],{},"I would eventually lead the UI/UX design and front-end development that would transition Stohke from a simple app into a comprehensive social platform with hybrid iOS and Android apps.",[1320,1850],{"after":1851,"before":1852},"/projects/stohke/after.webp","/projects/stohke/before.webp",[1261,1854],{":items":1855},"[\"/projects/stohke/stohke-01.jpg\",\"/projects/stohke/stohke-02.jpg\",\"/projects/stohke/stohke-03.jpg\",\"/projects/stohke/stohke-04.jpg\"]",{"title":64,"searchDepth":403,"depth":403,"links":1857},[],"An social network for outdoor & action sports enthusiasts.",{"wip":423},"/projects/stohke","2015-12-01T00:00:00.000Z","stohke",{"description":1858},{"loc":1860,"lastmod":1164,"changefreq":434,"priority":435},"projects/3.stohke","UI/UX + front-end development",[1449,1464,1279,1751,1868,1821,1869,1170],"UI/UX Design","Wireframes","/projects/stohke/thumb.webp","Zafp00lb_MWuW56-W2-OHHk-koipE3dBDQmeS-aBeI4",{"id":1873,"title":1874,"additionalTags":1875,"body":1876,"description":1939,"excerpt":421,"extension":422,"featured":428,"meta":1940,"name":1884,"navigation":423,"openSource":428,"path":1941,"projectDate":1942,"projectFolder":1943,"seo":1944,"sitemap":1945,"status":64,"stem":1946,"subtitle":1866,"tags":1947,"thumbnail":1948,"__hash__":1949},"projects/projects/4.classflow.md","Classflow",[],{"type":9,"value":1877,"toc":1936},[1878,1886,1889],[16,1879,1880,1885],{},[338,1881,1884],{"href":1882,"rel":1883,"target":1717},"https://www.classflow.com",[342],"ClassFlow"," by Promethean (sunset late 2023) was a cloud-based teaching and learning platform that makes lesson planning easier and lesson delivery more dynamic.",[16,1887,1888],{},"Complete with a specialized view for students, the two work in unison to provide a robust solution for lesson planning, delivering as well as student interaction and feedback.",[1261,1890,1892,1894],{":items":1891},"[\"/projects/classflow/classflow-01.png\",\"/projects/classflow/classflow-02.png\",\"/projects/classflow/classflow-03.png\",\"/projects/classflow/classflow-04.png\",\"/projects/classflow/classflow-05.png\"]",[48,1893,354],{"id":353},[356,1895,1896,1902],{},[359,1897,1898],{},[362,1899,1900],{},[365,1901,367],{},[369,1903,1904,1909,1914,1918,1923,1928,1932],{},[362,1905,1906],{},[374,1907,1908],{},"KendoUI",[362,1910,1911],{},[374,1912,1913],{},"JS",[362,1915,1916],{},[374,1917,1464],{},[362,1919,1920],{},[374,1921,1922],{},"jQuery",[362,1924,1925],{},[374,1926,1927],{},"LESS",[362,1929,1930],{},[374,1931,1485],{},[362,1933,1934],{},[374,1935,1492],{},{"title":64,"searchDepth":403,"depth":403,"links":1937},[1938],{"id":353,"depth":408,"text":354},"Cloud-based classroom lesson delivery software",{"wip":423},"/projects/classflow","2014-10-01T00:00:00.000Z","classflow",{"description":1939},{"loc":1941,"lastmod":1164,"changefreq":434,"priority":435},"projects/4.classflow",[1908,1464,1927,1751,1868,1170],"/projects/classflow/thumb.webp","g8eif127LAL3Tm_EJtcxJEciFa9NP0_YVCV4GyaMzz8",{"id":1951,"title":1952,"additionalTags":1953,"body":1954,"description":2019,"excerpt":421,"extension":422,"featured":428,"meta":2020,"name":1952,"navigation":423,"openSource":428,"path":2021,"projectDate":2022,"projectFolder":2023,"seo":2024,"sitemap":2025,"status":421,"stem":2026,"subtitle":2027,"tags":2028,"thumbnail":2030,"__hash__":2031},"projects/projects/6.sushi-stacks.md","Sushi Stacks",[],{"type":9,"value":1955,"toc":2016},[1956,1959,1966,1969,1973,1988,1993,1996,2002,2005],[12,1957],{":stats":1958},"[{\"label\": \"release date\", \"value\": \"2013\"}]",[16,1960,1961],{},[19,1962],{"alt":1963,"src":1964,"className":1965},"Join the Sushi Revolution","/projects/sushi/header.jpg",[23],[16,1967,1968],{},"I developed Sushi Stacks as fun way to tally up your meal total made specifically for use at conveyor-belt sushi restaurants.",[48,1970,1972],{"id":1971},"a-dish-best-served-cold","A dish best served cold",[16,1974,1975,1976,185,1978,185,1981,1983,1984,1987],{},"First of its kind, when released it was the only app that works for practically any conveyor-belt sushi restaurant and retains the experience of stacking your plates and calculates as you go.\nThis hybrid app was made with ",[71,1977,1449],{},[71,1979,1980],{},"jQuery Mobile",[71,1982,1525],{}," and used ",[71,1985,1986],{},"Firebase"," as a realtime datastore. Released on both Apple App Store and Google Play Store.",[1261,1989],{":items":1990,"className":1991},"[\"/projects/sushi/ss-add.gif\",\"/projects/sushi/ss-remove.gif\",\"/projects/sushi/ss-summary.png\", \"/projects/sushi/ss-main.png\", \"/projects/sushi/ss-browse.png\"]",[1992],"max-w-md",[16,1994,1995],{},"I would love to someday dust off and revisit this project as it was a lot of fun.\nI even started designing more plate types with only CSS that I could include like drinks and bowls. Though these days with SVG being better supported that's probably a better choice.",[16,1997,1998],{},[19,1999],{"alt":2000,"src":2001},"More stuff to stack","/projects/sushi/sushi-stacks-new-dish-types.jpg",[16,2003,2004],{},"Check out this martini glass!",[1721,2006,2007],{},[1724,2008,2015],{"height":2009,"style":2010,"scrolling":2011,"title":2012,"src":2013,"frameBorder":2011,"loading":2014,"allowTransparency":509,"allowFullScreen":509},300,"width: 100%;","no","CSS Martini Glass","https://codepen.io/limitlis/embed/OJXNdz?default-tab=html%2Cresult&theme-id=dark","lazy","\n  See the Pen \u003Ca href=\"https://codepen.io/limitlis/pen/OJXNdz\">\n  CSS Martini Glass\u003C/a> by Cesar Vargas (\u003Ca href=\"https://codepen.io/limitlis\">@limitlis\u003C/a>)\n  on \u003Ca href=\"https://codepen.io\">CodePen\u003C/a>.\n",{"title":64,"searchDepth":403,"depth":403,"links":2017},[2018],{"id":1971,"depth":408,"text":1972},"A fun app made for conveyor-belt sushi lovers.",{},"/projects/sushi-stacks","2013-12-01T00:00:00.000Z","sushi",{"description":2019},{"loc":2021,"lastmod":1164,"changefreq":434,"priority":435},"projects/6.sushi-stacks","Web Development + Hybrid App development",[1449,1751,1986,2029,1525,1922],"Hybrid App","/projects/sushi/thumb.webp","wxp_QiHS-IZSwZrVmeEzzbLXmPaaNNruF110dfD_y5Q",1780955968229]