[{"data":1,"prerenderedAt":1595},["ShallowReactive",2],{"docs-navigation":3,"doc-\u002Fteaching\u002Fapps-dev\u002Factivities\u002Fsemester-project":229,"surround-\u002Fteaching\u002Fapps-dev\u002Factivities\u002Fsemester-project":1396,"notes-index":1401},[4,88,171,182,192,203,218],{"title":5,"path":6,"stem":7,"children":8},"Dev","\u002Fdev","1.dev",[9,12,26,36,50,56,78],{"title":10,"path":6,"stem":11},"Development","1.dev\u002Findex",{"title":13,"path":14,"stem":15,"children":16},"Laravel","\u002Fdev\u002Flaravel","1.dev\u002F1.laravel\u002Findex",[17,18,22],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21},"Eloquent Relationships","\u002Fdev\u002Flaravel\u002Feloquent-relationships","1.dev\u002F1.laravel\u002F1.eloquent-relationships",{"title":23,"path":24,"stem":25},"Laravel Homestead","\u002Fdev\u002Flaravel\u002Flaravel-homestead","1.dev\u002F1.laravel\u002F2.laravel-homestead",{"title":27,"path":28,"stem":29,"children":30},"Bash","\u002Fdev\u002Fbash","1.dev\u002F13.bash\u002Findex",[31,32],{"title":27,"path":28,"stem":29},{"title":33,"path":34,"stem":35},"My Bash RC","\u002Fdev\u002Fbash\u002Fbash-rc","1.dev\u002F13.bash\u002F2.bash-rc",{"title":37,"path":38,"stem":39,"children":40},"Clean Code","\u002Fdev\u002Fclean-code","1.dev\u002F15.clean-code\u002Findex",[41,42,46],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45},"Naming Things","\u002Fdev\u002Fclean-code\u002Fnaming-things","1.dev\u002F15.clean-code\u002F1.naming-things",{"title":47,"path":48,"stem":49},"Services Return, Callers Present","\u002Fdev\u002Fclean-code\u002Fservices-return-callers-present","1.dev\u002F15.clean-code\u002F2.services-return-callers-present",{"title":51,"path":52,"stem":53,"children":54},"AI Prompting","\u002Fdev\u002Fai-prompting","1.dev\u002F17.ai-prompting\u002Findex",[55],{"title":51,"path":52,"stem":53},{"title":57,"path":58,"stem":59,"children":60},"C#","\u002Fdev\u002Fcsharp","1.dev\u002F2.csharp\u002Findex",[61,62,66,70,74],{"title":57,"path":58,"stem":59},{"title":63,"path":64,"stem":65},"C# Basics","\u002Fdev\u002Fcsharp\u002Fcsharp-basics","1.dev\u002F2.csharp\u002F1.csharp-basics",{"title":67,"path":68,"stem":69},"Classes & Models","\u002Fdev\u002Fcsharp\u002Fclasses-and-models","1.dev\u002F2.csharp\u002F2.classes-and-models",{"title":71,"path":72,"stem":73},"Services & Helpers","\u002Fdev\u002Fcsharp\u002Fservices-and-helpers","1.dev\u002F2.csharp\u002F3.services-and-helpers",{"title":75,"path":76,"stem":77},"Project Structure","\u002Fdev\u002Fcsharp\u002Fproject-structure","1.dev\u002F2.csharp\u002F4.project-structure",{"title":79,"path":80,"stem":81,"children":82},"Git","\u002Fdev\u002Fgit","1.dev\u002F9.git\u002Findex",[83,84],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87},"Git Cheat Sheet","\u002Fdev\u002Fgit\u002Fgit-cheat-sheet","1.dev\u002F9.git\u002F1.git-cheat-sheet",{"title":89,"path":90,"stem":91,"children":92},"Teaching","\u002Fteaching","2.teaching",[93,95],{"title":89,"path":90,"stem":94},"2.teaching\u002Findex",{"title":96,"path":97,"stem":98,"children":99},"AppsDev","\u002Fteaching\u002Fapps-dev","2.teaching\u002F1.apps-dev\u002Findex",[100,101,119,137,147,161],{"title":96,"path":97,"stem":98},{"title":102,"path":103,"stem":104,"children":105},"Lesson Plans","\u002Fteaching\u002Fapps-dev\u002Flesson-plans","2.teaching\u002F1.apps-dev\u002F1.lesson-plans\u002Findex",[106,107,111,115],{"title":102,"path":103,"stem":104},{"title":108,"path":109,"stem":110},"Coding with AI","\u002Fteaching\u002Fapps-dev\u002Flesson-plans\u002Fcoding-with-ai","2.teaching\u002F1.apps-dev\u002F1.lesson-plans\u002F1.coding-with-ai",{"title":112,"path":113,"stem":114},"Coding with AI: Prompts & Reading JavaScript","\u002Fteaching\u002Fapps-dev\u002Flesson-plans\u002Fprompts-and-reading-js","2.teaching\u002F1.apps-dev\u002F1.lesson-plans\u002F2.prompts-and-reading-js",{"title":116,"path":117,"stem":118},"JavaScript for Beginners","\u002Fteaching\u002Fapps-dev\u002Flesson-plans\u002Fjavascript-for-beginners","2.teaching\u002F1.apps-dev\u002F1.lesson-plans\u002F3.javascript-for-beginners",{"title":120,"path":121,"stem":122,"children":123},"Activities","\u002Fteaching\u002Fapps-dev\u002Factivities","2.teaching\u002F1.apps-dev\u002F2.activities\u002Findex",[124,125,129,133],{"title":120,"path":121,"stem":122},{"title":126,"path":127,"stem":128},"Dynamic Portfolio Website","\u002Fteaching\u002Fapps-dev\u002Factivities\u002Fdynamic-portfolio-website","2.teaching\u002F1.apps-dev\u002F2.activities\u002F2.dynamic-portfolio-website",{"title":130,"path":131,"stem":132},"Mini Product Store","\u002Fteaching\u002Fapps-dev\u002Factivities\u002Fmini-product-store","2.teaching\u002F1.apps-dev\u002F2.activities\u002F3.mini-product-store",{"title":134,"path":135,"stem":136},"Semester Project","\u002Fteaching\u002Fapps-dev\u002Factivities\u002Fsemester-project","2.teaching\u002F1.apps-dev\u002F2.activities\u002F4.semester-project",{"title":138,"path":139,"stem":140,"children":141},"Exercises","\u002Fteaching\u002Fapps-dev\u002Fexercises","2.teaching\u002F1.apps-dev\u002F4.exercises\u002Findex",[142,143],{"title":138,"path":139,"stem":140},{"title":144,"path":145,"stem":146},"Read & Predict","\u002Fteaching\u002Fapps-dev\u002Fexercises\u002Fread-and-predict","2.teaching\u002F1.apps-dev\u002F4.exercises\u002F1.read-and-predict",{"title":148,"path":149,"stem":150,"children":151},"AI Prompts","\u002Fteaching\u002Fapps-dev\u002Fai-prompts","2.teaching\u002F1.apps-dev\u002F7.ai-prompts\u002Findex",[152,153,157],{"title":148,"path":149,"stem":150},{"title":154,"path":155,"stem":156},"Prompt Flow","\u002Fteaching\u002Fapps-dev\u002Fai-prompts\u002Fbasic-prompting","2.teaching\u002F1.apps-dev\u002F7.ai-prompts\u002F1.basic-prompting",{"title":158,"path":159,"stem":160},"Using OpenCode CLI Instead of Copy-Pasting from ChatGPT","\u002Fteaching\u002Fapps-dev\u002Fai-prompts\u002Fopencode-cli","2.teaching\u002F1.apps-dev\u002F7.ai-prompts\u002F2.opencode-cli",{"title":162,"path":163,"stem":164,"children":165},"Cheat Sheets","\u002Fteaching\u002Fapps-dev\u002Fcheat-sheets","2.teaching\u002F1.apps-dev\u002F8.cheat-sheets\u002Findex",[166,167],{"title":162,"path":163,"stem":164},{"title":168,"path":169,"stem":170},"How to Collaborate on GitHub","\u002Fteaching\u002Fapps-dev\u002Fcheat-sheets\u002Fgithub-collaboration","2.teaching\u002F1.apps-dev\u002F8.cheat-sheets\u002F1.github-collaboration",{"title":172,"path":173,"stem":174,"children":175},"Snippets","\u002Fsnippets","3.snippets",[176,178],{"title":172,"path":173,"stem":177},"3.snippets\u002Findex",{"title":179,"path":180,"stem":181},"Debounce and Throttle","\u002Fsnippets\u002Fdebounce-and-throttle","3.snippets\u002F1.debounce-and-throttle",{"title":162,"path":183,"stem":184,"children":185},"\u002Fcheat-sheets","4.cheat-sheets",[186,188],{"title":162,"path":183,"stem":187},"4.cheat-sheets\u002Findex",{"title":189,"path":190,"stem":191},"Vim Cheat Sheet","\u002Fcheat-sheets\u002Fvim-cheat-sheet","4.cheat-sheets\u002F1.vim-cheat-sheet",{"title":193,"path":194,"stem":195,"children":196},"Templates","\u002Ftemplates","5.templates",[197,199],{"title":193,"path":194,"stem":198},"5.templates\u002Findex",{"title":200,"path":201,"stem":202},"Pull Request Template","\u002Ftemplates\u002Fpull-request-template","5.templates\u002F1.pull-request-template",{"title":204,"path":205,"stem":206,"children":207},"Meta","\u002Fmeta","6.meta",[208,210,214],{"title":204,"path":205,"stem":209},"6.meta\u002Findex",{"title":211,"path":212,"stem":213},"Authoring Guide","\u002Fmeta\u002Fauthoring-guide","6.meta\u002F1.authoring-guide",{"title":215,"path":216,"stem":217},"Markdown Showcase","\u002Fmeta\u002Fmarkdown-showcase","6.meta\u002F2.markdown-showcase",{"title":219,"path":220,"stem":221,"children":222},"Troubleshooting","\u002Ftroubleshooting","7.troubleshooting",[223,225],{"title":219,"path":220,"stem":224},"7.troubleshooting\u002Findex",{"title":226,"path":227,"stem":228},"Fixing CORS Errors","\u002Ftroubleshooting\u002Fcors-errors","7.troubleshooting\u002F1.cors-errors",{"id":230,"title":134,"body":231,"category":120,"createdAt":1373,"description":1374,"draft":1375,"extension":1376,"featured":1375,"keywords":1377,"links":1384,"meta":1385,"navigation":1285,"path":135,"readingTime":1386,"seo":1387,"stem":136,"tags":1388,"updatedAt":1373,"__hash__":1395},"docs\u002F2.teaching\u002F1.apps-dev\u002F2.activities\u002F4.semester-project.md",{"type":232,"value":233,"toc":1332},"minimark",[234,251,262,268,273,363,367,370,480,484,491,494,528,540,544,547,615,619,625,631,642,646,703,707,733,738,742,745,853,856,860,869,873,971,975,1046,1051,1055,1058,1171,1180,1184,1187,1195,1198,1201,1242,1252,1256,1262,1265,1270,1274,1328],[235,236,237,238,242,243,246,247,250],"p",{},"This is the project you'll be working on for the rest of the semester. You'll\nwork in ",[239,240,241],"strong",{},"teams of four",", build ",[239,244,245],{},"one frontend application",", keep everything in\n",[239,248,249],{},"one shared GitHub repository",", and use AI to help you build it.",[235,252,253,254,257,258,261],{},"The first deliverable is not code. It's a ",[239,255,256],{},"pitch presentation",", due\n",[239,259,260],{},"Saturday, August 8",".",[263,264,265],"note",{},[235,266,267],{},"AI will get you to \"it works\" faster than you expect. That's not the finish\nline. The rest of the semester is scope, polish, and the hundred small things\nthat separate a demo from something a person would actually use.",[269,270,272],"h2",{"id":271},"the-rules","The Rules",[274,275,276,289],"table",{},[277,278,279],"thead",{},[280,281,282,286],"tr",{},[283,284,285],"th",{},"Rule",[283,287,288],{},"Detail",[290,291,292,303,313,323,333,343,353],"tbody",{},[280,293,294,300],{},[295,296,297],"td",{},[239,298,299],{},"Team size",[295,301,302],{},"Exactly four members",[280,304,305,310],{},[295,306,307],{},[239,308,309],{},"GitHub",[295,311,312],{},"Every member needs their own account",[280,314,315,320],{},[295,316,317],{},[239,318,319],{},"Repository",[295,321,322],{},"One per team, all four added as collaborators",[280,324,325,330],{},[295,326,327],{},[239,328,329],{},"Contribution",[295,331,332],{},"Every member must have commits under their own account",[280,334,335,340],{},[295,336,337],{},[239,338,339],{},"Stack",[295,341,342],{},"Frontend only — vanilla JS, or a JavaScript framework",[280,344,345,350],{},[295,346,347],{},[239,348,349],{},"AI",[295,351,352],{},"OpenCode, ChatGPT, Claude, Copilot — use whatever you want",[280,354,355,360],{},[295,356,357],{},[239,358,359],{},"Scope",[295,361,362],{},"Big enough to fill a semester, even with AI helping",[269,364,366],{"id":365},"team-setup","Team Setup",[235,368,369],{},"Do all of this before the pitch. It's fifteen minutes of work and it proves your\nteam is real.",[371,372,374,379,382,389,393,400,414,418,425,435,439,442,467,471,477],"steps",{"level":373},"3",[375,376,378],"h3",{"id":377},"everyone-creates-a-github-account","Everyone creates a GitHub account",[235,380,381],{},"All four members. Use an email you'll still have access to in December.",[235,383,384,385,388],{},"Write down each member's ",[239,386,387],{},"username"," — you'll need it for the pitch slide and\nI'll use it to check contributions.",[375,390,392],{"id":391},"one-member-creates-the-repository","One member creates the repository",[235,394,395,396,261],{},"Pick a member to own the repo. Create it on GitHub with a ",[397,398,399],"code",{},"README.md",[235,401,402,403,406,407,410,411,261],{},"Name it something recognizable — ",[397,404,405],{},"cafe-order-system",", not ",[397,408,409],{},"project"," or\n",[397,412,413],{},"finalproject2",[375,415,417],{"id":416},"add-the-other-three-as-collaborators","Add the other three as collaborators",[235,419,420,421,424],{},"In the repository: ",[239,422,423],{},"Settings → Collaborators → Add people",", then enter each\nteammate's username.",[426,427,428],"warning",{},[235,429,430,431,434],{},"Collaborators must ",[239,432,433],{},"accept the invitation"," by email or from their GitHub\nnotifications. An invitation that was never accepted means that person cannot\npush, and they will discover this at the worst possible moment.",[375,436,438],{"id":437},"everyone-clones-the-repo","Everyone clones the repo",[235,440,441],{},"Each member, on their own machine:",[443,444,449],"pre",{"className":445,"code":446,"language":447,"meta":448,"style":448},"language-bash shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","git clone https:\u002F\u002Fgithub.com\u002FUSERNAME\u002FREPO-NAME.git\n","bash","",[397,450,451],{"__ignoreMap":448},[452,453,456,460,464],"span",{"class":454,"line":455},"line",1,[452,457,459],{"class":458},"sYn-s","git",[452,461,463],{"class":462},"sTbE_"," clone",[452,465,466],{"class":462}," https:\u002F\u002Fgithub.com\u002FUSERNAME\u002FREPO-NAME.git\n",[375,468,470],{"id":469},"everyone-makes-one-commit","Everyone makes one commit",[235,472,473,474,476],{},"Before the pitch, each of the four members adds their name to the ",[397,475,399],{},"\nand pushes. Four names, four separate commits, four different accounts.",[235,478,479],{},"This is your proof that all four of you can actually push to the repo. Find out\nnow, not in week six.",[269,481,483],{"id":482},"what-counts-as-big-enough","What Counts as Big Enough",[235,485,486,487,490],{},"Your project must take the whole semester ",[239,488,489],{},"with AI helping you",". That's a\nhigher bar than you think, because AI is fast at exactly the part you're\nimagining right now.",[235,492,493],{},"A project is big enough if it has:",[495,496,497,504,510,516,522],"ul",{},[498,499,500,503],"li",{},[239,501,502],{},"At least five distinct screens or views"," — not five sections of one page.",[498,505,506,509],{},[239,507,508],{},"At least three features that hold and change state"," — a cart, a score, a\nsaved list, a filter, a booking.",[498,511,512,515],{},[239,513,514],{},"Data-driven rendering"," — content comes from JavaScript data, never from\ncopy-pasted HTML.",[498,517,518,521],{},[239,519,520],{},"Responsive design"," — it works on a phone and on a laptop.",[498,523,524,527],{},[239,525,526],{},"Polish"," — empty states, input validation, confirmations, loading states,\ntransitions, a consistent visual design.",[529,530,531,537],"tip",{},[235,532,533,536],{},[239,534,535],{},"The one-sitting test."," If you could describe your whole app to an AI in one\nprompt and have something working by the end of the evening, it's too small.\nAdd screens, add features, add depth.",[235,538,539],{},"Most teams pitch something too small and don't realize it until week four.",[269,541,543],{"id":542},"frontend-only","Frontend Only",[235,545,546],{},"Everything runs in the browser. There is no server, no database, and no API you\ncontrol.",[274,548,549,559],{},[277,550,551],{},[280,552,553,556],{},[283,554,555],{},"You can use",[283,557,558],{},"You cannot use",[290,560,561,569,577,588,599,607],{},[280,562,563,566],{},[295,564,565],{},"HTML, CSS, vanilla JavaScript",[295,567,568],{},"A backend of any kind — Express, PHP, Laravel, .NET",[280,570,571,574],{},[295,572,573],{},"A JavaScript framework — React, Vue, Nuxt, Next, Svelte",[295,575,576],{},"A real database — MySQL, PostgreSQL, MongoDB, Firebase",[280,578,579,582],{},[295,580,581],{},"npm packages, a build step, a dev server",[295,583,584,585],{},"Server routes, API routes, or anything under ",[397,586,587],{},"server\u002F",[280,589,590,596],{},[295,591,592,595],{},[397,593,594],{},"localStorage"," to save data",[295,597,598],{},"User accounts with real passwords",[280,600,601,604],{},[295,602,603],{},"Hardcoded JSON \u002F JS data files",[295,605,606],{},"Payment processing",[280,608,609,612],{},[295,610,611],{},"Google Fonts, icon libraries, CSS frameworks",[295,613,614],{},"A language that isn't JavaScript or TypeScript",[375,616,618],{"id":617},"choosing-your-stack","Choosing Your Stack",[235,620,621,624],{},[239,622,623],{},"Vanilla HTML, CSS and JavaScript is the default",", and it's a completely valid\nchoice. Every concept this course has taught you applies directly, and nothing\nstands between you and the code.",[235,626,627,630],{},[239,628,629],{},"A JavaScript framework is allowed if someone on your team already knows it.","\nReact, Vue, Nuxt, Next, Svelte, Astro — your pick, as long as it's JavaScript\nor TypeScript. Declare it at the pitch.",[426,632,633,636,639],{},[235,634,635],{},"A framework raises the bar on the one rule that decides your grade.",[235,637,638],{},"AI is extremely good at producing framework code — hooks, composables, stores,\nrouting, patterns nobody on your team has seen before. It will hand you two\nhundred lines that work perfectly and that none of you can explain. At the\ndefense, that is worth less than fifty lines of vanilla JavaScript you wrote\nand understood.",[235,640,641],{},"Pick a framework because a teammate genuinely knows it and can teach the other\nthree. Do not pick one because it sounds more impressive. It isn't, and I will\nask.",[375,643,645],{"id":644},"if-you-use-a-framework","If you use a framework",[495,647,648,661,675,693],{},[498,649,650,653,654,656,657,660],{},[239,651,652],{},"Node and npm are tooling, not a backend."," A dev server and a build step are\nfine. ",[397,655,587],{},", ",[397,658,659],{},"\u002Fapi"," routes, Express, and database drivers are not.",[498,662,663,666,667,670,671,674],{},[239,664,665],{},"Nuxt and Next must be static or SPA only."," No SSR against live data, no\nserver routes. ",[397,668,669],{},"npm run generate"," (or ",[397,672,673],{},"next export",") has to produce a folder\nof files that runs on its own.",[498,676,677,688,689,692],{},[239,678,679,680,683,684,687],{},"Add ",[397,681,682],{},"node_modules\u002F"," to ",[397,685,686],{},".gitignore"," before your first push."," A repo with\n",[397,690,691],{},"node_modules"," committed is unusable for your teammates and unreadable for me.",[498,694,695,698,699,702],{},[239,696,697],{},"Your app must still run for me from a clean clone",": ",[397,700,701],{},"npm install",", one\ncommand, done. Write both commands in your README.",[375,704,706],{"id":705},"what-this-means-in-practice","What this means in practice",[495,708,709,718,727],{},[498,710,711,714,715,717],{},[239,712,713],{},"\"Saving data\""," means ",[397,716,594],{},". Your data lives in one browser on one\ncomputer, and that's fine — just be honest about it in your README.",[498,719,720,723,724,726],{},[239,721,722],{},"\"Logging in\""," means a fake login screen backed by ",[397,725,594],{},". It's a\ndemo of the interface, not real security. Never treat it as real.",[498,728,729,732],{},[239,730,731],{},"\"Products\" or \"levels\" or \"menu items\""," live in a JavaScript array of\nobjects that you write.",[263,734,735],{},[235,736,737],{},"The frontend-only limit is what makes this project gradeable. Every line in your\nrepo is a line the four of you can read, run in a browser, and explain. Add a\nbackend and half your codebase becomes a place your grade goes to hide.",[269,739,741],{"id":740},"project-directions","Project Directions",[235,743,744],{},"Anything is fair game as long as it clears the size bar. Some directions:",[274,746,747,760],{},[277,748,749],{},[280,750,751,754,757],{},[283,752,753],{},"Type",[283,755,756],{},"Example",[283,758,759],{},"What makes it semester-sized",[290,761,762,775,788,801,814,827,840],{},[280,763,764,769,772],{},[295,765,766],{},[239,767,768],{},"Cafe \u002F restaurant",[295,770,771],{},"Order system with a menu, cart, order queue, and receipt",[295,773,774],{},"Menu browsing, customization, cart math, order history",[280,776,777,782,785],{},[295,778,779],{},[239,780,781],{},"Store",[295,783,784],{},"Online shop with categories, cart, wishlist, checkout flow",[295,786,787],{},"Filtering, search, cart state, multi-step checkout",[280,789,790,795,798],{},[295,791,792],{},[239,793,794],{},"Game",[295,796,797],{},"Puzzle, quiz, tower defense, idle clicker, card game",[295,799,800],{},"Game loop, scoring, levels, save state, leaderboard",[280,802,803,808,811],{},[295,804,805],{},[239,806,807],{},"Booking",[295,809,810],{},"Salon, clinic, or court reservation",[295,812,813],{},"Calendar UI, time slots, conflict handling, confirmations",[280,815,816,821,824],{},[295,817,818],{},[239,819,820],{},"Tracker",[295,822,823],{},"Habit, budget, fitness, or study tracker",[295,825,826],{},"Data entry, charts, history views, streaks",[280,828,829,834,837],{},[295,830,831],{},[239,832,833],{},"Learning",[295,835,836],{},"Flashcards, language drills, typing trainer",[295,838,839],{},"Deck management, progress tracking, statistics",[280,841,842,847,850],{},[295,843,844],{},[239,845,846],{},"Event",[295,848,849],{},"Ticketing, seat picker, event listings",[295,851,852],{},"Seat map, filtering, cart, ticket generation",[235,854,855],{},"Bring your own idea if you have one. The best projects usually come from\nsomebody on the team having an actual problem to solve.",[269,857,859],{"id":858},"the-pitch-presentation","The Pitch Presentation",[235,861,862,865,866],{},[239,863,864],{},"Due: Saturday, August 8"," ",[239,867,868],{},"Length: 5–8 minutes per team, all four members speak",[375,870,872],{"id":871},"what-your-presentation-must-cover","What your presentation must cover",[371,874,875,879,882,886,894,897,901,904,908,911,915,926,930,933,940,944,947,950,954,957,961,964,968],{"level":373},[375,876,878],{"id":877},"the-team","The Team",[235,880,881],{},"All four names and all four GitHub usernames, on one slide.",[375,883,885],{"id":884},"the-app-in-one-sentence","The App, In One Sentence",[443,887,892],{"className":888,"code":890,"language":891,"meta":448},[889],"language-text","A ______ for ______ that lets them ______.\n","text",[397,893,890],{"__ignoreMap":448},[235,895,896],{},"If you can't finish that sentence, you don't have an idea yet — you have a\ncategory.",[375,898,900],{"id":899},"who-its-for","Who It's For",[235,902,903],{},"Who uses this and what problem it solves for them. Be specific. \"Students\" is\nnot specific. \"Students who share a dorm and split grocery costs\" is.",[375,905,907],{"id":906},"the-screens","The Screens",[235,909,910],{},"List every screen or view. Minimum five. For each one, one line on what a user\ndoes there.",[375,912,914],{"id":913},"the-features","The Features",[235,916,917,918,921,922,925],{},"Split into ",[239,919,920],{},"must-have"," (the app is pointless without it) and ",[239,923,924],{},"later"," (nice\nto have if time allows). Four to six must-haves is a healthy number.",[375,927,929],{"id":928},"your-stack","Your Stack",[235,931,932],{},"Say what you're building it with: vanilla HTML\u002FCSS\u002FJS, or a named JavaScript\nframework.",[235,934,935,936,939],{},"If you're picking a framework, say ",[239,937,938],{},"who on the team already knows it"," and how\nthey'll bring the other three up to speed. \"We'll learn it from the AI\" is not\na plan — it's how you end up with a codebase nobody can defend.",[375,941,943],{"id":942},"why-this-takes-a-semester","Why This Takes a Semester",[235,945,946],{},"Address it directly. Which parts are genuinely hard? What has to be polished?\nWhat's the part you're least sure how to build?",[235,948,949],{},"This slide is the one I'll push back on hardest.",[375,951,953],{"id":952},"look-and-feel","Look and Feel",[235,955,956],{},"Two or three reference websites, a rough wireframe, a sketch on paper, a colour\npalette — anything that shows you've thought about how it looks. A photo of a\nwhiteboard is completely acceptable.",[375,958,960],{"id":959},"who-does-what","Who Does What",[235,962,963],{},"Rough ownership of feature areas across the four of you. Not \"designer,\nprogrammer, tester\" — everybody writes code. Split by feature: who owns the\ncart, who owns the menu, who owns the game loop.",[375,965,967],{"id":966},"the-repository","The Repository",[235,969,970],{},"Show it live. The repo, the four collaborators, and four commits from four\ndifferent accounts.",[375,972,974],{"id":973},"pitch-grading","Pitch Grading",[274,976,977,988],{},[277,978,979],{},[280,980,981,984],{},[283,982,983],{},"Category",[283,985,987],{"align":986},"right","Points",[290,989,990,998,1005,1012,1019,1027,1034],{},[280,991,992,995],{},[295,993,994],{},"Clarity of the idea — can we all picture the app?",[295,996,997],{"align":986},"20",[280,999,1000,1003],{},[295,1001,1002],{},"Scope — is it semester-sized, and did they justify it?",[295,1004,997],{"align":986},[280,1006,1007,1010],{},[295,1008,1009],{},"Screens and features are specific, not vague",[295,1011,997],{"align":986},[280,1013,1014,1017],{},[295,1015,1016],{},"Repository set up correctly with all four contributing",[295,1018,997],{"align":986},[280,1020,1021,1024],{},[295,1022,1023],{},"All four members present and can answer questions",[295,1025,1026],{"align":986},"10",[280,1028,1029,1032],{},[295,1030,1031],{},"Look and feel — evidence of design thinking",[295,1033,1026],{"align":986},[280,1035,1036,1041],{},[295,1037,1038],{},[239,1039,1040],{},"Total",[295,1042,1043],{"align":986},[239,1044,1045],{},"100",[426,1047,1048],{},[235,1049,1050],{},"A team that shows up with a repo containing commits from only one account loses\n20 points immediately. Set it up this week.",[269,1052,1054],{"id":1053},"contribution-requirements","Contribution Requirements",[235,1056,1057],{},"Your commit history is the record of who did the work. There is no other record,\nand \"he did most of it but I helped\" is not one.",[371,1059,1060,1064,1067,1115,1118,1122,1125,1137,1140,1144,1161,1164,1168],{"level":373},[375,1061,1063],{"id":1062},"commit-under-your-own-account","Commit under your own account",[235,1065,1066],{},"Configure Git once on your machine, using your own GitHub email:",[443,1068,1070],{"className":445,"code":1069,"language":447,"meta":448,"style":448},"git config --global user.name \"Your Name\"\ngit config --global user.email \"you@example.com\"\n",[397,1071,1072,1096],{"__ignoreMap":448},[452,1073,1074,1076,1079,1083,1086,1090,1093],{"class":454,"line":455},[452,1075,459],{"class":458},[452,1077,1078],{"class":462}," config",[452,1080,1082],{"class":1081},"sz9Cv"," --global",[452,1084,1085],{"class":462}," user.name",[452,1087,1089],{"class":1088},"sbYkP"," \"",[452,1091,1092],{"class":462},"Your Name",[452,1094,1095],{"class":1088},"\"\n",[452,1097,1099,1101,1103,1105,1108,1110,1113],{"class":454,"line":1098},2,[452,1100,459],{"class":458},[452,1102,1078],{"class":462},[452,1104,1082],{"class":1081},[452,1106,1107],{"class":462}," user.email",[452,1109,1089],{"class":1088},[452,1111,1112],{"class":462},"you@example.com",[452,1114,1095],{"class":1088},[235,1116,1117],{},"Never push your teammate's work from your machine. Their commits must come from\ntheir account.",[375,1119,1121],{"id":1120},"pull-before-you-push","Pull before you push",[235,1123,1124],{},"Four people in one repo means conflicts. Every time you sit down to work:",[443,1126,1128],{"className":445,"code":1127,"language":447,"meta":448,"style":448},"git pull\n",[397,1129,1130],{"__ignoreMap":448},[452,1131,1132,1134],{"class":454,"line":455},[452,1133,459],{"class":458},[452,1135,1136],{"class":462}," pull\n",[235,1138,1139],{},"Then work, then commit, then push. Skipping the pull is how you spend an evening\nfixing a merge instead of building a feature.",[375,1141,1143],{"id":1142},"split-by-files-not-by-lines","Split by files, not by lines",[235,1145,1146,1147,1150,1151,656,1154,656,1157,1160],{},"Two people editing ",[397,1148,1149],{},"script.js"," at the same time will conflict constantly. Split\nyour app into separate files by feature area — ",[397,1152,1153],{},"cart.js",[397,1155,1156],{},"menu.js",[397,1158,1159],{},"game.js"," —\nand give each one an owner.",[235,1162,1163],{},"On a framework this is easier: one component per file, one owner per component.\nAgree on the folder structure at the start so four people aren't inventing four\ndifferent ones.",[375,1165,1167],{"id":1166},"everyone-codes","Everyone codes",[235,1169,1170],{},"Whatever your team calls the roles, all four members write and commit\nJavaScript. A member who only made slides has not passed this project.",[263,1172,1173],{},[235,1174,1175,1176,1179],{},"I will look at the ",[239,1177,1178],{},"Insights → Contributors"," page of your repository. It shows\ncommits per person over time. A flat line for one member across the whole\nsemester is visible from across the room.",[269,1181,1183],{"id":1182},"using-ai-on-this-project","Using AI on This Project",[235,1185,1186],{},"Use it. That's the course. But the rule from Day 1 hasn't changed:",[1188,1189,1190],"blockquote",{},[235,1191,1192],{},[239,1193,1194],{},"You may only submit code you can explain.",[235,1196,1197],{},"At every checkpoint, and at the final defense, I'll pick a file from your repo\nand ask the member who committed it to walk me through it. \"The AI wrote that\npart\" is an answer, and it's the wrong one.",[235,1199,1200],{},"Practical habits that keep you out of trouble:",[495,1202,1203,1218,1225,1235],{},[498,1204,1205,1206,1209,1210,865,1214,1217],{},"Ask for a ",[239,1207,1208],{},"plan before code",". In OpenCode, that's Plan mode\n(",[1211,1212],"kbd",{"value":1213},"shift",[1211,1215],{"value":1216},"tab",").",[498,1219,1220,1221,1224],{},"Build ",[239,1222,1223],{},"one feature per prompt",", not one app per prompt.",[498,1226,1227,1230,1231,1234],{},[239,1228,1229],{},"Read the diff"," before you commit. ",[397,1232,1233],{},"git diff"," shows you what actually\nchanged, which is not always what the AI said it changed.",[498,1236,1237,1238,1241],{},"Write your ",[239,1239,1240],{},"own commit messages",". If you can't summarize the change in one\nline, you don't understand it yet.",[235,1243,1244,1245,1248,1249,261],{},"See ",[1246,1247,154],"a",{"href":155}," and\n",[1246,1250,1251],{"href":159},"OpenCode CLI",[269,1253,1255],{"id":1254},"after-the-pitch","After the Pitch",[235,1257,1258,1259,1261],{},"Once your pitch is approved, the project runs in checkpoints through the end of\nthe semester — roughly: data model and static screens, then core features, then\nsaving with ",[397,1260,594],{},", then polish and edge cases, then a feature freeze\nand final demo.",[235,1263,1264],{},"Details come after pitch day, because the checkpoints depend on what you pitch.",[529,1266,1267],{},[235,1268,1269],{},"Start the repo this week even though no real code is due. Teams that leave the\nGitHub setup until they need it lose their first working week to invitation\nemails and merge conflicts instead of building.",[269,1271,1273],{"id":1272},"checklist-for-saturday","Checklist for Saturday",[495,1275,1278,1288,1294,1300,1310,1316,1322],{"className":1276},[1277],"contains-task-list",[498,1279,1282,1287],{"className":1280},[1281],"task-list-item",[1283,1284],"input",{"disabled":1285,"type":1286},true,"checkbox"," Four members, confirmed",[498,1289,1291,1293],{"className":1290},[1281],[1283,1292],{"disabled":1285,"type":1286}," Four GitHub accounts created",[498,1295,1297,1299],{"className":1296},[1281],[1283,1298],{"disabled":1285,"type":1286}," One repository created",[498,1301,1303,1305,1306,1309],{"className":1302},[1281],[1283,1304],{"disabled":1285,"type":1286}," Three collaborators invited ",[239,1307,1308],{},"and"," invitations accepted",[498,1311,1313,1315],{"className":1312},[1281],[1283,1314],{"disabled":1285,"type":1286}," Four commits from four different accounts",[498,1317,1319,1321],{"className":1318},[1281],[1283,1320],{"disabled":1285,"type":1286}," Presentation covering all ten points above, including your stack",[498,1323,1325,1327],{"className":1324},[1281],[1283,1326],{"disabled":1285,"type":1286}," All four members ready to speak",[1329,1330,1331],"style",{},"html pre.shiki code .sYn-s, html code.shiki .sYn-s{--shiki-light:#E2931D;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .sTbE_, html code.shiki .sTbE_{--shiki-light:#91B859;--shiki-default:#B56959;--shiki-dark:#C98A7D}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 .sz9Cv, html code.shiki .sz9Cv{--shiki-light:#91B859;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .sbYkP, html code.shiki .sbYkP{--shiki-light:#39ADB5;--shiki-default:#B5695977;--shiki-dark:#C98A7D77}",{"title":448,"searchDepth":1333,"depth":1333,"links":1334},3,[1335,1336,1343,1344,1349,1350,1364,1370,1371,1372],{"id":271,"depth":1098,"text":272},{"id":365,"depth":1098,"text":366,"children":1337},[1338,1339,1340,1341,1342],{"id":377,"depth":1333,"text":378},{"id":391,"depth":1333,"text":392},{"id":416,"depth":1333,"text":417},{"id":437,"depth":1333,"text":438},{"id":469,"depth":1333,"text":470},{"id":482,"depth":1098,"text":483},{"id":542,"depth":1098,"text":543,"children":1345},[1346,1347,1348],{"id":617,"depth":1333,"text":618},{"id":644,"depth":1333,"text":645},{"id":705,"depth":1333,"text":706},{"id":740,"depth":1098,"text":741},{"id":858,"depth":1098,"text":859,"children":1351},[1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363],{"id":871,"depth":1333,"text":872},{"id":877,"depth":1333,"text":878},{"id":884,"depth":1333,"text":885},{"id":899,"depth":1333,"text":900},{"id":906,"depth":1333,"text":907},{"id":913,"depth":1333,"text":914},{"id":928,"depth":1333,"text":929},{"id":942,"depth":1333,"text":943},{"id":952,"depth":1333,"text":953},{"id":959,"depth":1333,"text":960},{"id":966,"depth":1333,"text":967},{"id":973,"depth":1333,"text":974},{"id":1053,"depth":1098,"text":1054,"children":1365},[1366,1367,1368,1369],{"id":1062,"depth":1333,"text":1063},{"id":1120,"depth":1333,"text":1121},{"id":1142,"depth":1333,"text":1143},{"id":1166,"depth":1333,"text":1167},{"id":1182,"depth":1098,"text":1183},{"id":1254,"depth":1098,"text":1255},{"id":1272,"depth":1098,"text":1273},"2026-08-01","Teams of four build one frontend application over the whole semester using AI, in a single shared GitHub repository where everyone contributes.",false,"md",[1378,1379,1380,1381,1382,1383],"semester project","team project","github collaborators","opencode","frontend only","group project javascript",[],{},12,{"title":134,"description":1374},[1389,1390,1391,1392,1393,1394],"teaching","activity","capstone","github","ai","frontend","RIW-9yp-BXMYmN_BJ9rWlQXlKNvtLysXLguIX9c1mfc",[1397,1399],{"title":130,"path":131,"stem":132,"description":1398,"children":-1},"A JavaScript activity where students build a simple product store using arrays, loops, functions, DOM manipulation, and event listeners.",{"title":138,"path":139,"stem":140,"description":1400,"children":-1},"Practice problems that build skill through repetition.",[1402,1404,1411,1414,1421,1429,1437,1442,1445,1448,1451,1459,1465,1468,1473,1476,1482,1485,1488,1493,1496,1499,1505,1509,1514,1517,1523,1526,1529,1534,1536,1539,1542,1545,1547,1553,1556,1561,1564,1568,1571,1578,1583,1586,1592],{"path":135,"title":134,"description":1374,"tags":1403,"category":120,"featured":1375,"updatedAt":1373,"createdAt":1373,"readingTime":1386,"draft":1375},[1389,1390,1391,1392,1393,1394],{"path":169,"title":168,"description":1405,"tags":1406,"category":162,"featured":1375,"updatedAt":1373,"createdAt":1373,"readingTime":1410,"draft":1375},"Create one repository, push your project, and add your teammates as collaborators so the whole team can work on the same code.",[1392,459,1407,1408,1409],"collaboration","teamwork","setup",4,{"path":163,"title":162,"description":1412,"tags":1413,"category":162,"featured":1375,"updatedAt":1373,"createdAt":1373,"readingTime":455,"draft":1375},"Step-by-step references students can follow on their own during class.",[],{"path":159,"title":158,"description":1415,"tags":1416,"category":148,"featured":1375,"updatedAt":1420,"createdAt":1420,"readingTime":1333,"draft":1375},"Install and configure the OpenCode CLI so AI writes code directly into your project folder instead of you copying it from a chat window.",[1393,1381,1417,1418,1419],"cli","tooling","workflow","2026-07-25",{"path":48,"title":47,"description":1422,"tags":1423,"category":37,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":1098,"draft":1375},"A service should return a result and let the caller decide how to show it — the single most useful separation-of-concerns rule.",[1424,1425,1426,1427],"clean-code","architecture","separation-of-concerns","services","2026-07-19",{"path":64,"title":63,"description":1430,"tags":1431,"category":1436,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":1333,"draft":1375},"Types, variables, control flow and how to write a function (method) in C#, mapped from PHP.",[1432,1433,1434,1435],"csharp","dotnet","basics","functions",null,{"path":68,"title":67,"description":1438,"tags":1439,"category":1436,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":1333,"draft":1375},"Create a class, give it properties and a constructor, and use it — the C# version of a Laravel model.",[1432,1433,1440,1441],"classes","models",{"path":72,"title":71,"description":1443,"tags":1444,"category":1436,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":1333,"draft":1375},"Put code in another file — a service or a static helper — and call it from anywhere, the C# way.",[1432,1433,1427,1425],{"path":76,"title":75,"description":1446,"tags":1447,"category":1436,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":1333,"draft":1375},"How C# files, namespaces, folders and the dotnet CLI fit together into a running app.",[1432,1433,1418,1425],{"path":58,"title":57,"description":1449,"tags":1450,"category":1436,"featured":1375,"updatedAt":1428,"createdAt":1428,"readingTime":455,"draft":1375},"Learning C# and .NET from a Laravel\u002FPHP background — the fundamentals, mapped to what you already know.",[1432,1433,1434],{"path":20,"title":19,"description":1452,"tags":1453,"category":13,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"The core Eloquent relationship types with examples and the N+1 trap to avoid.",[1454,1455,1456,1457],"laravel","eloquent","database","orm","2026-07-17",{"path":24,"title":23,"description":1460,"tags":1461,"category":13,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"My quick reference for setting up and using Laravel Homestead during development.",[1454,1462,1463,1464],"homestead","vagrant","virtualbox",{"path":14,"title":13,"description":1466,"tags":1467,"category":13,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"The PHP framework for web artisans — Eloquent, routing, queues and more.",[],{"path":34,"title":33,"description":1469,"tags":1470,"category":27,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1098,"draft":1375},"Personal Bash aliases and helper functions that streamline my Laravel and Homestead development workflow.",[447,1471,1472,1462,1454],"bashrc","git bash",{"path":28,"title":27,"description":1474,"tags":1475,"category":27,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Shell scripting and a faster life on the command line.",[],{"path":44,"title":43,"description":1477,"tags":1478,"category":37,"featured":1285,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Practical rules for naming variables, functions and types so code reads like prose.",[1424,1479,1480,1481],"naming","readability","craft",{"path":38,"title":37,"description":1483,"tags":1484,"category":37,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Writing code that other people (and future you) can read.",[],{"path":52,"title":51,"description":1486,"tags":1487,"category":51,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Getting reliable, useful results out of language models.",[],{"path":86,"title":85,"description":1489,"tags":1490,"category":79,"featured":1285,"updatedAt":1458,"createdAt":1458,"readingTime":1098,"draft":1375},"The Git commands I actually use day to day, plus how to undo things safely.",[459,1417,1491,1492],"version-control","cheat-sheet",{"path":80,"title":79,"description":1494,"tags":1495,"category":79,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Version control — everyday commands and getting out of trouble.",[],{"path":6,"title":10,"description":1497,"tags":1498,"category":10,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Languages, frameworks and the craft of building software.",[],{"path":109,"title":108,"description":1500,"tags":1501,"category":89,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1410,"draft":1375},"An introduction to AI-assisted software development, modern development workflows, and the mindset needed to use AI responsibly throughout the course.",[1393,1502,1503,1504],"software development","prompt engineering","beginners",{"path":113,"title":112,"description":1506,"tags":1507,"category":89,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1410,"draft":1375},"Learn how to write effective AI prompts and read JavaScript code confidently. This lesson teaches students how to direct AI instead of blindly copying its output.",[1393,1508,1503,1504],"javascript",{"path":117,"title":116,"description":1510,"tags":1511,"category":89,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1333,"draft":1375},"Introduction to the fundamentals of JavaScript, from variables and functions to loops, DOM manipulation, and events. This lesson prepares students for the Mini Product Store activity.",[1508,1504,1512,1513],"programming","web development",{"path":103,"title":102,"description":1515,"tags":1516,"category":102,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Session-by-session plans with objectives, timing and materials.",[],{"path":127,"title":126,"description":1518,"tags":1519,"category":120,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1333,"draft":1375},"Build a personal portfolio website using JavaScript arrays, loops, and DOM manipulation instead of hardcoded HTML.",[1389,1390,1508,1520,1521,1522],"portfolio","dom","loops",{"path":131,"title":130,"description":1398,"tags":1524,"category":120,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1333,"draft":1375},[1389,1390,1508,1521,1525,1522],"arrays",{"path":121,"title":120,"description":1527,"tags":1528,"category":120,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"In-class activities that get students doing, not just listening.",[],{"path":145,"title":144,"description":1530,"tags":1531,"category":120,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1098,"draft":1375},"Practice reading JavaScript code, predicting its output, and verifying your understanding before running the program.",[1389,1390,1508,1435,1532,1533],"if-statement","debugging",{"path":139,"title":138,"description":1400,"tags":1535,"category":138,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},[],{"path":155,"title":154,"description":1537,"tags":1538,"category":148,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1410,"draft":1375},"A structured workflow for working with AI that emphasizes planning, review, and understanding before implementation.",[1393,1503,1419],{"path":149,"title":148,"description":1540,"tags":1541,"category":148,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Prompt templates for teaching with and about AI.",[],{"path":97,"title":96,"description":1543,"tags":1544,"category":89,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Lesson plans, activities, rubrics and student references.",[],{"path":90,"title":89,"description":1543,"tags":1546,"category":89,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},[],{"path":180,"title":179,"description":1548,"tags":1549,"category":172,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Two tiny functions to control how often a handler runs — with the difference explained.",[1508,1550,1551,1552],"performance","snippets","events",{"path":173,"title":172,"description":1554,"tags":1555,"category":172,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Small, copy-ready fragments you reach for again and again.",[],{"path":190,"title":189,"description":1557,"tags":1558,"category":162,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"The essential Vim motions and commands to get productive and get out.",[1559,1560,1492,1417],"vim","editor",{"path":183,"title":162,"description":1562,"tags":1563,"category":162,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Dense, scannable references for commands and syntax.",[],{"path":201,"title":200,"description":1565,"tags":1566,"category":193,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"A reusable PR description template that makes reviews faster and kinder.",[459,1392,1567,1407],"template",{"path":194,"title":193,"description":1569,"tags":1570,"category":193,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Reusable starting points for files, configs and docs.",[],{"path":212,"title":211,"description":1572,"tags":1573,"category":204,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1098,"draft":1375},"The frontmatter and markdown conventions every note in this knowledge base follows.",[1574,1575,1576,1577],"meta","conventions","markdown","authoring",{"path":216,"title":215,"description":1579,"tags":1580,"category":204,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":1098,"draft":1375},"Every formatting feature this knowledge base supports, on one page — a living reference and rendering test.",[1576,1581,1582],"mdc","reference",{"path":205,"title":204,"description":1584,"tags":1585,"category":204,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"How this knowledge base itself is built and maintained.",[],{"path":227,"title":226,"description":1587,"tags":1588,"category":219,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"What a CORS error actually means and how to fix it — on the server, where it belongs.",[1589,1590,1591,1533],"cors","http","apis",{"path":220,"title":219,"description":1593,"tags":1594,"category":219,"featured":1375,"updatedAt":1458,"createdAt":1458,"readingTime":455,"draft":1375},"Symptoms, causes and fixes for problems worth remembering.",[],1785598841766]