[{"data":1,"prerenderedAt":13821},["ShallowReactive",2],{"content-page:\u002Finternet-applications\u002Fpresentations":3,"content-page-quiz:none":3,"book-module-total-pages":4,"content-section-pages:none":5,"content-directory-pages:\u002Finternet-applications\u002Fpresentations":6},null,[],[],[7,536,1616,2505,3601,4540,5331,6398,7124,7949,10645,12555],{"id":8,"title":9,"audience":10,"body":11,"contentType":509,"course":510,"description":511,"estimateBasis":512,"estimatedDiscussionMinutes":513,"estimatedLiveMinutes":514,"estimatedTotalMinutes":515,"extension":516,"meta":517,"module":518,"navigation":519,"order":520,"path":521,"promptAssist":522,"seo":523,"status":524,"stem":525,"tags":526,"videoDuration":531,"videoId":532,"videoLink":533,"videoTitle":534,"week":518,"__hash__":535},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F00-learn-courses-and-discord.md","Learn Courses Platform And Discord","student",{"type":12,"value":13,"toc":492},"minimark",[14,56,96,149,199,247,281,343,385,435,464],[15,16,19,24,40],"slide",{"id":17,"level":18},"learn-courses-flow","2",[20,21,23],"h2",{"id":22},"what-is-the-learn-courses-platform","What is the Learn Courses Platform",[25,26,27,31,34,37],"ul",{},[28,29,30],"li",{},"This is a platform I've built over the years to aid assignment submissions and course utilities",[28,32,33],{},"It provides objective-based worksheets to fill in images, urls, and open responses to document assignment evidence",[28,35,36],{},"The goal is to keep tasks clear and objective for students and grading",[28,38,39],{},"Also includes a few other utilities for courses (such as joining the Discord server)",[41,42,43,44,50,51,55],"p",{},"NOTE: Summer 2026 the previous Learn Platform (",[45,46,47],"a",{"href":47,"rel":48},"https:\u002F\u002Flearn.ethereallab.app",[49],"nofollow",") has been replaced by Learn Courses Platform (",[45,52,53],{"href":53,"rel":54},"https:\u002F\u002Fcourses.ethereallab.app",[49],"). The deprecated site is still available as a backup but all activities\u002Fcontent is being migrated to the new version",[15,57,59,62,65,93],{"id":58,"level":18},"learn-courses-title",[20,60,9],{"id":61},"learn-courses-platform-and-discord",[41,63,64],{},"How to join:",[25,66,67,73,81,84,87,90],{},[28,68,69,70],{},"Visit the platform ",[45,71,53],{"href":53,"rel":72},[49],[28,74,75,76],{},"Sign in with your NJIT email\n",[25,77,78],{},[28,79,80],{},"If you're in the Canvas course, you should automatically get synced to this platform",[28,82,83],{},"Visit your Profile page",[28,85,86],{},"Associate your Discord account",[28,88,89],{},"Join the course Discord server",[28,91,92],{},"Verify that your course channels appear on Discord",[41,94,95],{},"You can follow the steps on the below slides for guidance",[15,97,100,103],{"id":98,"level":99},"visit-learn-courses","3",[20,101,102],{"id":98},"Visit Learn Courses",[104,105,108,139],"two-col",{"gap":106,"left-width":107,"right-width":107},"lg","1fr",[109,110,112,115,120],"template",{"v-slot:left":111},"",[41,113,114],{},"Go to:",[41,116,117],{},[45,118,53],{"href":53,"rel":119},[49],[25,121,122,130,133,136],{},[28,123,124,125,129],{},"Click the ",[126,127,128],"strong",{},"Login"," button",[28,131,132],{},"Use your NJIT email",[28,134,135],{},"Only NJIT accounts are allowed",[28,137,138],{},"If the browser tries a personal Chrome profile, log out of that account or switch profiles",[109,140,141],{"v-slot:right":111},[41,142,143],{},[144,145],"img",{"alt":146,"src":147,"variant":148},"Learn Courses logged-out home page with the Login button visible","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fhome-loggedout-login-button.png","sidecar-screenshot",[15,150,152,155],{"id":151,"level":99},"associate-discord-name",[20,153,154],{"id":151},"Associate Discord Name",[104,156,157,183],{"gap":106,"left-width":107,"right-width":107},[109,158,159,162,180],{"v-slot:left":111},[41,160,161],{},"On Learn Courses:",[163,164,165,168,174,177],"ol",{},[28,166,167],{},"Open your Profile",[28,169,170,171],{},"Click ",[126,172,173],{},"Refresh Discord Username",[28,175,176],{},"Authorize the Discord prompt",[28,178,179],{},"After the success message appears, save your profile",[41,181,182],{},"If you are not sure where you are, use the Home icon in the top left to return to the dashboard.",[109,184,185,192],{"v-slot:right":111},[41,186,187],{},[144,188],{"alt":189,"src":190,"variant":148,"max-height":191},"Learn Courses dashboard sidebar with Profile and course links visible","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fdashboard-sidebar-profile-links.png","13rem",[41,193,194],{},[144,195],{"alt":196,"src":197,"variant":148,"max-height":198},"Learn Courses profile page with Discord connection controls visible","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fprofile-page.png","16rem",[15,200,202,205],{"id":201,"level":99},"authorize-discord",[20,203,204],{"id":201},"Authorize Discord",[104,206,207,231],{"gap":106,"left-width":107,"right-width":107},[109,208,209,212],{"v-slot:left":111},[41,210,211],{},"Discord will ask whether Learn Courses can access your Discord account.",[25,213,214,217,222,225,228],{},[28,215,216],{},"Confirm you are signed in to the correct Discord account",[28,218,170,219],{},[126,220,221],{},"Authorize",[28,223,224],{},"Return to Learn Courses",[28,226,227],{},"Look for the success message",[28,229,230],{},"Save the profile change",[109,232,233,240],{"v-slot:right":111},[41,234,235],{},[144,236],{"alt":237,"src":238,"variant":148,"max-height":239},"Discord authorization prompt for Learn Courses","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fdiscord-auth.png","25rem",[41,241,242],{},[144,243],{"alt":244,"src":245,"variant":148,"max-height":246},"Learn Courses success message after connecting Discord","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fdiscord-connected-success.png","7rem",[15,248,250,253,256,262,270],{"id":249,"level":99},"join-the-channel",[20,251,252],{"id":249},"Join The Channel",[41,254,255],{},"Use the Discord link provided on Canvas, or use:",[41,257,258],{},[45,259,260],{"href":260,"rel":261},"https:\u002F\u002Fdiscord.com\u002Finvite\u002FYEHcm44wzg",[49],[41,263,264,265,269],{},"This should send you to the ",[266,267,268],"code",{},"access-channel"," channel.",[25,271,272,275,278],{},[28,273,274],{},"Other channels are protected by a bot",[28,276,277],{},"Messages may be blocked until your name and role are set",[28,279,280],{},"You'll have temporary access until a role is applied so if you leave before completing the steps you'll have to revisit the invite link",[15,282,284,287],{"id":283,"level":18},"verify-with-quackbot",[20,285,286],{"id":283},"Verify With QuackBot",[104,288,289,334],{"gap":106,"left-width":107,"right-width":107},[109,290,291,303,309,314,317,331],{"v-slot:left":111},[25,292,293,296],{},[28,294,295],{},"A summer 2026 change was to have the bot attempt to auto-detect new members and apply roles automatically",[28,297,298,299,302],{},"If you don't see the proper semester category (i.e., ",[266,300,301],{},"summer-2026",") or the expected channels you can do the below action",[41,304,305,306,308],{},"In ",[266,307,268],{},", enter:",[41,310,311],{},[266,312,313],{},"@QuackBot",[41,315,316],{},"QuackBot will:",[25,318,319,322,325,328],{},[28,320,321],{},"Verify your account",[28,323,324],{},"Pull in your name and section",[28,326,327],{},"Apply your class role",[28,329,330],{},"Update your server nickname",[41,332,333],{},"This does not change your real Discord username.",[109,335,336],{"v-slot:right":111},[41,337,338],{},[144,339],{"alt":340,"src":341,"variant":148,"max-height":342},"QuackBot response showing the student already has a course role","\u002Fimages\u002Finternet-applications\u002Flearn-courses-discord\u002Fquackbot-role-response.png","8rem",[15,344,346,350,353,364,369],{"id":345,"level":18},"welcome-and-potential-issues",[20,347,349],{"id":348},"welcome","Welcome",[41,351,352],{},"If the previous steps worked, you should see a new semester category in the Discord sidebar.",[25,354,355,358,361],{},[28,356,357],{},"It should appear after the general channels",[28,359,360],{},"It should include one or more channels for your active courses",[28,362,363],{},"Use the correct course channel for class questions and discussion",[365,366,368],"h3",{"id":367},"potential-issues","Potential Issues",[25,370,371,374],{},[28,372,373],{},"If you recently joined the class, your UCID may still need to be added to Learn Courses",[28,375,376,377,380],{},"If there is an issue, email the instructor or DM ",[266,378,379],{},"MattToegel",[25,381,382],{},[28,383,384],{},"Some Discord privacy settings may require a friend request before DMs work",[15,386,388,391],{"id":387,"level":18},"general-conduct",[20,389,390],{"id":387},"General Conduct",[25,392,393,396,399,410,413,421,429,432],{},[28,394,395],{},"Use class-related channels for questions and discussion",[28,397,398],{},"Ask general course questions in the channel instead of DM when possible",[28,400,401,402],{},"Do not post screenshots of in-progress assignment solutions\n",[25,403,404,407],{},[28,405,406],{},"This would be more ideal for a DM",[28,408,409],{},"If you see posted solution-like items don't assume they're correct",[28,411,412],{},"General unrelated code is okay when it supports a discussion (like content from a presentation or reading)",[28,414,415,416],{},"If the instructor needs to see assignment code, they may ask you to DM the screenshot\n",[25,417,418],{},[28,419,420],{},"Since repositories should be set to private; repo links are fine to post in the class channel since other students should not have access to them",[28,422,423,424],{},"Keep off-topic items out of class channels\n",[25,425,426],{},[28,427,428],{},"There are plenty of categorized channels to use and I can always make more",[28,430,431],{},"Helping classmates understand topics is encouraged just be mindful not to spoon-feed",[28,433,434],{},"Sharing direct solutions goes against the Academic Integrity Policy",[15,436,438,441,444],{"id":437,"level":18},"quick-check",[20,439,440],{"id":437},"Quick Check",[41,442,443],{},"Before continuing, confirm:",[25,445,446,449,452,455,458,461],{},[28,447,448],{},"You can sign in to Learn Courses with your NJIT email",[28,450,451],{},"Your profile is saved",[28,453,454],{},"Discord is associated with your Learn Courses profile",[28,456,457],{},"You joined the Discord server",[28,459,460],{},"QuackBot applied your course role",[28,462,463],{},"You can see the correct course channel",[15,465,467,470],{"id":466,"level":18},"summary",[20,468,469],{"id":466},"Summary",[25,471,472,475,483,486,489],{},[28,473,474],{},"Learn Courses supports course tools and course-specific setup",[28,476,477,478],{},"Canvas remains the official assignment, grade, and course hub\n",[25,479,480],{},[28,481,482],{},"All necessary items will be linked on Canvas",[28,484,485],{},"Discord is the preferred quick communication channel",[28,487,488],{},"QuackBot connects your Discord account to the correct course role",[28,490,491],{},"Good course communication keeps help requests specific and protects private information",{"title":111,"searchDepth":493,"depth":493,"links":494},2,[495,496,497,498,499,500,501,502,506,507,508],{"id":22,"depth":493,"text":23},{"id":61,"depth":493,"text":9},{"id":98,"depth":493,"text":102},{"id":151,"depth":493,"text":154},{"id":201,"depth":493,"text":204},{"id":249,"depth":493,"text":252},{"id":283,"depth":493,"text":286},{"id":348,"depth":493,"text":349,"children":503},[504],{"id":367,"depth":505,"text":368},3,{"id":387,"depth":493,"text":390},{"id":437,"depth":493,"text":440},{"id":466,"depth":493,"text":469},"presentation","Internet Applications","Set up Learn Courses Platform and Discord before starting terminal, Git, and local server work.","Face-to-face class of about 40 students; includes account sign-in, Discord association, QuackBot role setup, and communication expectations.","10","20","30","md",{},"1",true,"0","\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F00-learn-courses-and-discord",false,{"title":9,"description":511},"published","internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F00-learn-courses-and-discord",[527,528,529,530],"course-tools","learn-courses","discord","setup","11:16","ScmHyEF1sA0","https:\u002F\u002Fyoutu.be\u002FScmHyEF1sA0","Joining Learn Platform and Discord Server","tEFV7lUabcy7whz7FSHEjPXSirrd3ginqQq4O4AkW9o",{"id":537,"title":538,"audience":10,"body":539,"contentType":509,"course":510,"description":1600,"estimateBasis":1601,"estimatedDiscussionMinutes":513,"estimatedLiveMinutes":1602,"estimatedTotalMinutes":1603,"extension":516,"meta":1604,"module":518,"navigation":519,"order":513,"path":1605,"promptAssist":522,"seo":1606,"status":524,"stem":1607,"tags":1608,"videoDuration":1612,"videoId":1613,"videoLink":1614,"videoTitle":538,"week":518,"__hash__":1615},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands.md","Basic CLI Commands",{"type":12,"value":540,"toc":1566},[541,599,636,668,730,797,848,874,894,932,960,981,1016,1038,1110,1133,1178,1241,1293,1321,1341,1370,1410,1440,1450,1519],[15,542,544,548],{"id":543,"level":18},"why-cli-first",[20,545,547],{"id":546},"why-cli-comes-first","Why CLI Comes First",[25,549,550,558,566,580,588],{},[28,551,552,553],{},"Common language for setup and developer tools\n",[25,554,555],{},[28,556,557],{},"Git, servers, package installs, deployment logs",[28,559,560,561],{},"Works when there is no full desktop\n",[25,562,563],{},[28,564,565],{},"SSH, Ubuntu Server, minimal system access",[28,567,568,569],{},"Direct check of what the computer sees\n",[25,570,571,574,577],{},[28,572,573],{},"Current folder",[28,575,576],{},"Files and permissions",[28,578,579],{},"Command output",[28,581,582,583],{},"Repeatable steps beat guessing through menus\n",[25,584,585],{},[28,586,587],{},"Run a command, read output, adjust",[28,589,590,591],{},"Location still matters\n",[25,592,593,596],{},[28,594,595],{},"Wrong folder can make correct commands fail",[28,597,598],{},"Or create files in the wrong place",[15,600,602,605,608],{"id":601,"level":18},"goal",[20,603,604],{"id":601},"Goal",[41,606,607],{},"Build the command-line habits that make setup work predictable:",[25,609,610,613,616,630,633],{},[28,611,612],{},"Know what folder the terminal is using",[28,614,615],{},"Read file and folder lists before moving",[28,617,618,619,622,623,626,627],{},"Recognize common flags like ",[266,620,621],{},"-a",", ",[266,624,625],{},"-r",", and ",[266,628,629],{},"-l",[28,631,632],{},"Make small file changes and verify them",[28,634,635],{},"Stop safely when output does not match the lesson",[15,637,639,642,645,665],{"id":638,"level":18},"before-you-start",[20,640,641],{"id":638},"Before You Start",[41,643,644],{},"Run these commands on your host computer",[25,646,647,659,662],{},[28,648,649,650],{},"Windows: Git Bash",[25,651,652],{},[28,653,654,655],{},"Need Git Bash now? Use the Windows install slide in the next presentation:\n",[45,656,658],{"href":657},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Fview\u002Fslides#step-1-install-git-on-windows","Install Git On Windows",[28,660,661],{},"Apple macOS: Terminal",[28,663,664],{},"Linux: Terminal",[41,666,667],{},"Use one terminal window for the whole practice so your location is easy to track",[15,669,671,675],{"id":670,"level":18},"working-directory",[20,672,674],{"id":673},"the-main-idea","The Main Idea",[25,676,677,688,699,722],{},[28,678,679,680],{},"Terminal commands run from one folder at a time\n",[25,681,682],{},[28,683,684,685],{},"That folder is the ",[126,686,687],{},"working directory",[28,689,690,693,694],{},[266,691,692],{},"pwd",": print working directory\n",[25,695,696],{},[28,697,698],{},"Shows the full path to the folder your terminal is using",[28,700,701,702],{},"Fresh terminal usually starts in your home folder\n",[25,703,704,710,716],{},[28,705,706,707],{},"Windows Git Bash: ",[266,708,709],{},"\u002Fc\u002FUsers\u002Fyour-username",[28,711,712,713],{},"Apple macOS: ",[266,714,715],{},"\u002FUsers\u002Fyour-username",[28,717,718,719],{},"Linux: ",[266,720,721],{},"\u002Fhome\u002Fyour-username",[28,723,724,725],{},"Commands from this lesson start from the working directory\n",[25,726,727],{},[28,728,729],{},"Unless you give a different path",[15,731,733,736,739,791],{"id":732,"level":18},"paths-relative-and-absolute",[20,734,735],{"id":732},"Paths: Relative And Absolute",[41,737,738],{},"Paths build on the working directory. They tell the terminal which file or folder you mean",[25,740,741,747,753,759,785],{},[28,742,743,744],{},"Relative path: starts from the working directory, like ",[266,745,746],{},"public\u002Findex.php",[28,748,749,750],{},"Absolute path: starts from the system root, like ",[266,751,752],{},"\u002Fhome\u002Fstudent\u002Fproject",[28,754,755,758],{},[266,756,757],{},"."," means the current folder",[28,760,761,764,765],{},[266,762,763],{},".."," means the parent folder\n",[25,766,767,773,779],{},[28,768,769,772],{},[266,770,771],{},"..\u002F.."," goes up two folders",[28,774,775,776],{},"Example: ",[266,777,778],{},"cd ..\u002F..",[28,780,781,784],{},[266,782,783],{},"..."," is not a shortcut",[28,786,787,790],{},[266,788,789],{},"~"," means your home folder",[41,792,793,794,796],{},"If a command affects the wrong place, check ",[266,795,692],{}," first, then check the path you typed",[15,798,800,803,806,825,828],{"id":799,"level":18},"flags-options-and-arguments",[20,801,802],{"id":799},"Flags, Options, And Arguments",[41,804,805],{},"Commands usually follow this shape:",[25,807,808,814,819],{},[28,809,810,811],{},"Command: what to do, like ",[266,812,813],{},"ls",[28,815,816,817],{},"Flag or option: how to do it, like ",[266,818,621],{},[28,820,821,822],{},"Argument: what to do it to, like ",[266,823,824],{},"public_html",[41,826,827],{},"Examples:",[25,829,830,836,842],{},[28,831,832,835],{},[266,833,834],{},"ls -a"," shows hidden files",[28,837,838,841],{},[266,839,840],{},"cp -r folder backup-folder"," copies a folder",[28,843,844,847],{},[266,845,846],{},"nano -l file.txt"," opens with line numbers",[15,849,851,855,858,869],{"id":850,"level":18},"practice-loop",[20,852,854],{"id":853},"practice-1-location-and-paths","Practice 1: Location And Paths",[41,856,857],{},"For each command, use the same pattern:",[163,859,860,863,866],{},[28,861,862],{},"Run one command",[28,864,865],{},"Read the output",[28,867,868],{},"Confirm the folder or file changed the way you expected",[25,870,871],{},[28,872,873],{},"See the slides below for workflow steps, checkpoints, and expected results",[15,875,877,880,883,888,891],{"id":876,"level":99},"step-1-confirm-where-you-are",[20,878,879],{"id":876},"Step 1: Confirm Where You Are",[41,881,882],{},"Run:",[884,885],"code-snippet",{"language":886,"src":887},"bash","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-1-confirm-where-you-01.sh",[41,889,890],{},"Expected result: a folder path",[41,892,893],{},"If you see a path, the terminal is working and you know your current location",[15,895,897,900,902,905,908,911,914],{"id":896,"level":99},"step-2-list-files",[20,898,899],{"id":896},"Step 2: List Files",[41,901,882],{},[884,903],{"language":886,"src":904},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-2-list-files-02.sh",[41,906,907],{},"Expected result: file and folder names from your current location",[41,909,910],{},"For hidden files and details too, run:",[884,912],{"language":886,"src":913},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-2-list-files-03.sh",[25,915,916,921,926],{},[28,917,918,920],{},[266,919,621],{}," includes hidden files",[28,922,923,925],{},[266,924,629],{}," uses a long listing",[28,927,928,931],{},[266,929,930],{},"-la"," combines both",[15,933,935,938,941,944,951,957],{"id":934,"level":99},"step-3-change-folders",[20,936,937],{"id":934},"Step 3: Change Folders",[41,939,940],{},"Start from your home folder, then move up and back",[884,942],{"language":886,"src":943},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-3-change-folders-04.sh",[41,945,946,947,950],{},"This avoids assuming your computer has a specific folder like ",[266,948,949],{},"Documents"," in the current location",[41,952,953,954,956],{},"When you move into a named folder later, run ",[266,955,813],{}," first and pick a folder that actually appears in the list",[41,958,959],{},"If a path has spaces, wrap it in quotes",[15,961,963,967,969,972],{"id":962,"level":99},"step-4-create-practice-folder",[20,964,966],{"id":965},"step-4-create-a-practice-folder","Step 4: Create A Practice Folder",[41,968,882],{},[884,970],{"language":886,"src":971},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-4-create-a-practice-05.sh",[41,973,974,975,977,978],{},"Expected result: ",[266,976,692],{}," ends with ",[266,979,980],{},"cli-practice",[15,982,984,988,990,993,996],{"id":983,"level":99},"step-5-create-and-read-file",[20,985,987],{"id":986},"step-5-write-text-to-a-file","Step 5: Write Text To A File",[41,989,882],{},[884,991],{"language":886,"src":992},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-5-write-text-to-a-f-06.sh",[41,994,995],{},"What this command does:",[25,997,998,1004,1010],{},[28,999,1000,1003],{},[266,1001,1002],{},"echo"," prepares text for the terminal",[28,1005,1006,1009],{},[266,1007,1008],{},">"," redirects that text into a file instead of printing it on screen",[28,1011,1012,1015],{},[266,1013,1014],{},"cli-proof.txt"," is created in the current folder, or replaced if it already exists",[15,1017,1019,1023,1026,1029,1035],{"id":1018,"level":99},"step-5-read-file-back",[365,1020,1022],{"id":1021},"step-5-continued-read-the-file-back","Step 5 Continued: Read The File Back",[41,1024,1025],{},"Then read it back:",[884,1027],{"language":886,"src":1028},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-5-continued-read-th-07.sh",[41,1030,1031,1034],{},[266,1032,1033],{},"cat"," prints file contents in the terminal",[41,1036,1037],{},"Expected result: the terminal prints the text you wrote",[15,1039,1041,1045,1047,1056,1059,1085,1088],{"id":1040,"level":18},"file-management-loop",[20,1042,1044],{"id":1043},"practice-2-file-management","Practice 2: File Management",[41,1046,857],{},[163,1048,1049,1051,1053],{},[28,1050,862],{},[28,1052,865],{},[28,1054,1055],{},"Confirm the file changed the way you expected",[41,1057,1058],{},"Commands in this practice:",[25,1060,1061,1067,1073,1079],{},[28,1062,1063,1066],{},[266,1064,1065],{},"touch"," creates an empty file",[28,1068,1069,1072],{},[266,1070,1071],{},"cp"," copies a file or folder",[28,1074,1075,1078],{},[266,1076,1077],{},"mv"," moves or renames",[28,1080,1081,1084],{},[266,1082,1083],{},"rm"," deletes",[41,1086,1087],{},"Important flags:",[25,1089,1090,1096,1102,1108],{},[28,1091,1092,1095],{},[266,1093,1094],{},"cp -r"," copies folders",[28,1097,1098,1101],{},[266,1099,1100],{},"rm -r"," deletes folders",[28,1103,1104,1107],{},[266,1105,1106],{},"rm -f"," forces deletion",[28,1109,873],{},[15,1111,1113,1117,1119,1122,1127],{"id":1112,"level":99},"practice-2-step-1-create-empty-file",[20,1114,1116],{"id":1115},"step-1-create-an-empty-file","Step 1: Create An Empty File",[41,1118,882],{},[884,1120],{"language":886,"src":1121},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-1-create-an-empty-f-08.sh",[41,1123,1124,1126],{},[266,1125,1065],{}," creates an empty file, or updates the timestamp if the file already exists",[41,1128,974,1129,1132],{},[266,1130,1131],{},"practice-empty.txt"," appears in the folder list",[15,1134,1136,1140,1142,1145,1148,1154,1167],{"id":1135,"level":99},"practice-2-step-2-copy-rename-and-delete",[20,1137,1139],{"id":1138},"step-2-copy-rename-and-delete","Step 2: Copy, Rename, And Delete",[41,1141,882],{},[884,1143],{"language":886,"src":1144},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fstep-2-copy-rename-and-d-09.sh",[41,1146,1147],{},"Expected result: the backup is copied, renamed, then removed",[41,1149,1150,1151,1153],{},"Use ",[266,1152,1083],{}," carefully. Deleting from the terminal usually skips the recycle bin",[25,1155,1156,1161],{},[28,1157,1158,1160],{},[266,1159,625],{},": recursive, includes folders and everything inside them",[28,1162,1163,1166],{},[266,1164,1165],{},"-f",": force, skips many confirmation prompts",[1168,1169,1171],"alert",{"color":1170},"red",[41,1172,1173,1174,1177],{},"Never run ",[266,1175,1176],{},"rm -rf \u002F",". It can try to delete the whole system from the root folder.",[15,1179,1181,1185,1188,1206,1211,1216,1236],{"id":1180,"level":18},"terminal-editors",[20,1182,1184],{"id":1183},"practice-3-terminal-editors","Practice 3: Terminal Editors",[41,1186,1187],{},"Sometimes you need to edit a file from a terminal",[25,1189,1190,1196],{},[28,1191,1192,1195],{},[266,1193,1194],{},"nano"," is beginner-friendly",[28,1197,1198,1201,1202,1205],{},[266,1199,1200],{},"vi"," or ",[266,1203,1204],{},"vim"," is common on servers but has a learning curve",[41,1207,1150,1208,1210],{},[266,1209,1194],{}," for this course unless a lesson says otherwise",[41,1212,1150,1213,1215],{},[266,1214,846],{}," when line numbers would help",[41,1217,1218,1219,1201,1221,1223,1224,1227,1228,1231,1232,1235],{},"If you accidentally open ",[266,1220,1200],{},[266,1222,1204],{},", press ",[266,1225,1226],{},"Esc",", type ",[266,1229,1230],{},":q",", and press ",[266,1233,1234],{},"Enter"," to exit without saving",[25,1237,1238],{},[28,1239,1240],{},"See the slide below for workflow steps, checkpoints, and expected results",[15,1242,1244,1249,1251,1254,1259,1281],{"id":1243,"level":99},"edit-with-nano",[20,1245,1246,1247],{"id":1243},"Edit With ",[266,1248,1194],{},[41,1250,882],{},[884,1252],{"language":886,"src":1253},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fedit-with-nano-10.sh",[41,1255,305,1256,1258],{},[266,1257,1194],{},":",[25,1260,1261,1264,1271,1275],{},[28,1262,1263],{},"Type a short note",[28,1265,1266,1267,1270],{},"Press ",[266,1268,1269],{},"Ctrl+O"," to save",[28,1272,1266,1273],{},[266,1274,1234],{},[28,1276,1266,1277,1280],{},[266,1278,1279],{},"Ctrl+X"," to exit",[41,1282,1283,1284,1286,1287,1227,1289,1231,1291],{},"If you open ",[266,1285,1200],{}," by mistake, press ",[266,1288,1226],{},[266,1290,1230],{},[266,1292,1234],{},[15,1294,1296,1302,1307,1310,1313,1316],{"id":1295,"level":18},"sudo-and-permission-boundaries",[20,1297,1298,1301],{"id":1295},[266,1299,1300],{},"sudo"," And Permission Boundaries",[41,1303,1304,1306],{},[266,1305,1300],{}," runs a command with elevated permissions",[41,1308,1309],{},"Use it only when a setup lesson explicitly says to use it",[41,1311,1312],{},"Example:",[884,1314],{"language":886,"src":1315},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fsudo-and-permission-boun-11.sh",[25,1317,1318],{},[28,1319,1320],{},"See the slide below for supporting examples and follow-up details",[15,1322,1324,1329,1335],{"id":1323,"level":99},"sudo-by-operating-system",[365,1325,1326,1328],{"id":1323},[266,1327,1300],{}," By Operating System",[41,1330,1331,1332,1334],{},"On Linux and macOS, ",[266,1333,1300],{}," is common for package installation and service management",[41,1336,1337,1338,1340],{},"Modern Windows also has a native ",[266,1339,1300],{}," option, but Windows Git Bash usually does not need it for this course. If elevated access is needed on Windows, open Git Bash as administrator",[15,1342,1344,1347,1350,1361],{"id":1343,"level":18},"quick-safety-routine",[20,1345,1346],{"id":1343},"Quick Safety Routine",[41,1348,1349],{},"Before a command changes files, ask:",[25,1351,1352,1355,1358],{},[28,1353,1354],{},"What folder am I in?",[28,1356,1357],{},"Do I see the files I expect?",[28,1359,1360],{},"Am I about to change the right folder?",[41,1362,1363,1364,1366,1367],{},"If one answer is unclear, stop and run ",[266,1365,692],{}," plus ",[266,1368,1369],{},"ls -la",[15,1371,1373,1376],{"id":1372,"level":18},"common-mistakes",[20,1374,1375],{"id":1372},"Common Mistakes",[25,1377,1378,1394,1400,1408],{},[28,1379,1380,1383,1384,1386,1387,1389,1390,1393],{},[266,1381,1382],{},"No such file or directory",": run ",[266,1385,692],{},", then ",[266,1388,813],{},", then try ",[266,1391,1392],{},"cd"," again",[28,1395,1396,1397,1399],{},"Command affected the wrong folder: check ",[266,1398,692],{}," before continuing",[28,1401,1402,1404,1405,1407],{},[266,1403,1033],{}," cannot find the file: run ",[266,1406,1369],{}," and check the exact filename",[28,1409,1320],{},[15,1411,1413,1417],{"id":1412,"level":99},"common-mistakes-recovery",[365,1414,1416],{"id":1415},"recovery-checks","Recovery Checks",[25,1418,1419,1422,1428,1434],{},[28,1420,1421],{},"Spaces in a path: wrap the path in quotes",[28,1423,1424,1425],{},"Command keeps running: press ",[266,1426,1427],{},"Ctrl+C",[28,1429,1430,1431],{},"Permission denied: move back home with ",[266,1432,1433],{},"cd ~",[28,1435,1436,1437,1439],{},"Wrong ",[266,1438,1083],{},": stop and ask before doing more work",[15,1441,1442,1444,1447],{"id":437,"level":18},[20,1443,440],{"id":437},[41,1445,1446],{},"You are ready for the next setup lesson when these commands make sense:",[884,1448],{"language":886,"src":1449},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands\u002Fquick-check-12.sh",[15,1451,1453,1457],{"id":1452,"level":18},"further-learning",[20,1454,1456],{"id":1455},"key-terms-and-further-learning","Key Terms And Further Learning",[104,1458,1459,1491],{"gap":106,"left-width":107,"right-width":107},[109,1460,1461,1465,1471,1480],{"v-slot:left":111},[365,1462,1464],{"id":1463},"key-terms","Key Terms",[41,1466,1467,1470],{},[126,1468,1469],{},"Working directory"," - The folder where the next terminal command runs",[41,1472,1473,1476,1477],{},[126,1474,1475],{},"Path"," - A file or folder location, such as ",[266,1478,1479],{},"public_html\u002Findex.php",[41,1481,1482,1485,1486,1488,1489],{},[126,1483,1484],{},"Flag"," - An extra command option, such as ",[266,1487,930],{}," in ",[266,1490,1369],{},[109,1492,1493,1496],{"v-slot:right":111},[365,1494,1495],{"id":1452},"Further Learning",[25,1497,1498,1505,1512],{},[28,1499,1500],{},[45,1501,1504],{"href":1502,"rel":1503},"https:\u002F\u002Fdocumentation.ubuntu.com\u002Fdesktop\u002Fen\u002Flatest\u002Ftutorial\u002Fthe-linux-command-line-for-beginners\u002F",[49],"Ubuntu Tutorial: The Linux Command Line For Beginners",[28,1506,1507],{},[45,1508,1511],{"href":1509,"rel":1510},"https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fcoreutils\u002Fmanual\u002Fcoreutils.html",[49],"GNU Coreutils Manual",[28,1513,1514],{},[45,1515,1518],{"href":1516,"rel":1517},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FLearn_web_development\u002FGetting_started\u002FEnvironment_setup\u002FCommand_line",[49],"MDN: Command Line Crash Course",[15,1520,1521,1523,1526],{"id":466,"level":18},[20,1522,469],{"id":466},[41,1524,1525],{},"Before leaving this presentation, confirm you can:",[25,1527,1528,1533,1538,1549,1563],{},[28,1529,1150,1530,1532],{},[266,1531,692],{}," to check where commands will run",[28,1534,1150,1535,1537],{},[266,1536,1369],{}," to inspect the current folder",[28,1539,1150,1540,622,1542,622,1544,626,1546,1548],{},[266,1541,1392],{},[266,1543,757],{},[266,1545,763],{},[266,1547,789],{}," to move intentionally",[28,1550,1551,1552,622,1554,622,1556,622,1558,626,1560,1562],{},"Use file commands such as ",[266,1553,1065],{},[266,1555,1071],{},[266,1557,1077],{},[266,1559,1083],{},[266,1561,1194],{}," carefully",[28,1564,1565],{},"Stop and check location when output does not match the lesson",{"title":111,"searchDepth":493,"depth":493,"links":1567},[1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1582,1583,1584,1585,1586,1588,1593,1594,1597,1598,1599],{"id":546,"depth":493,"text":547},{"id":601,"depth":493,"text":604},{"id":638,"depth":493,"text":641},{"id":673,"depth":493,"text":674},{"id":732,"depth":493,"text":735},{"id":799,"depth":493,"text":802},{"id":853,"depth":493,"text":854},{"id":876,"depth":493,"text":879},{"id":896,"depth":493,"text":899},{"id":934,"depth":493,"text":937},{"id":965,"depth":493,"text":966},{"id":986,"depth":493,"text":987,"children":1580},[1581],{"id":1021,"depth":505,"text":1022},{"id":1043,"depth":493,"text":1044},{"id":1115,"depth":493,"text":1116},{"id":1138,"depth":493,"text":1139},{"id":1183,"depth":493,"text":1184},{"id":1243,"depth":493,"text":1587},"Edit With nano",{"id":1295,"depth":493,"text":1589,"children":1590},"sudo And Permission Boundaries",[1591],{"id":1323,"depth":505,"text":1592},"sudo By Operating System",{"id":1343,"depth":493,"text":1346},{"id":1372,"depth":493,"text":1375,"children":1595},[1596],{"id":1415,"depth":505,"text":1416},{"id":437,"depth":493,"text":440},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Practice the terminal commands you need so you can move through folders, inspect files, and verify your location before running course commands.","Face-to-face class of about 40 students; includes short CLI demo, student command practice, path\u002Fflag checks, and common beginner recovery questions.","45","55",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands",{"title":538,"description":1600},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F01-basic-cli-commands",[1609,1610,1611],"cli","terminal","filesystem","46:05","NsSRKv_uBWM","https:\u002F\u002Fyoutu.be\u002FNsSRKv_uBWM","q_NRWUOCcsk5lm6u6kKPFGl9E9VqeQhaC0qb86nD7aY",{"id":1617,"title":1618,"audience":10,"body":1619,"contentType":509,"course":510,"description":2493,"estimateBasis":2494,"estimatedDiscussionMinutes":513,"estimatedLiveMinutes":2495,"estimatedTotalMinutes":1602,"extension":516,"meta":2496,"module":518,"navigation":519,"order":514,"path":2497,"promptAssist":522,"seo":2498,"status":524,"stem":2499,"tags":2500,"videoDuration":2501,"videoId":2502,"videoLink":2503,"videoTitle":1618,"week":518,"__hash__":2504},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools.md","Git Tools",{"type":12,"value":1620,"toc":2463},[1621,1644,1673,1701,1739,1770,1802,1837,1866,1896,1933,1936,1966,1997,2026,2076,2094,2111,2131,2156,2187,2205,2246,2291,2374,2434],[15,1622,1623,1625],{"id":601,"level":18},[20,1624,604],{"id":601},[25,1626,1627,1630,1633],{},[28,1628,1629],{},"Install Git",[28,1631,1632],{},"Choose one terminal for your operating system",[28,1634,1635,1636,622,1639,626,1641,1643],{},"Confirm ",[266,1637,1638],{},"git --version",[266,1640,692],{},[266,1642,1369],{}," work before GitHub setup",[15,1645,1647,1651],{"id":1646,"level":18},"terminal-choice-by-os",[20,1648,1650],{"id":1649},"terminal-choices","Terminal Choices",[25,1652,1653,1656,1659,1662,1664,1667,1670],{},[28,1654,1655],{},"Pick the terminal for your operating system",[28,1657,1658],{},"Use that same terminal for this lesson path",[28,1660,1661],{},"Run commands on your own computer unless a later lesson explicitly says \"inside the VM\"",[28,1663,649],{},[28,1665,1666],{},"Apple macOS: Terminal, with iTerm2 optional",[28,1668,1669],{},"Linux: Terminal, with Tilix optional",[28,1671,1672],{},"These operating system notes are alternatives, not a sequence",[15,1674,1676,1680,1698],{"id":1675,"level":18},"step-1-install-git-on-windows",[20,1677,1679],{"id":1678},"windows-path-git-bash","Windows Path: Git Bash",[163,1681,1682,1689,1692,1695],{},[28,1683,1684,1685],{},"Go to ",[45,1686,1687],{"href":1687,"rel":1688},"https:\u002F\u002Fgit-scm.com\u002Finstall\u002Fwindows",[49],[28,1690,1691],{},"Download and run the Git for Windows installer",[28,1693,1694],{},"Open Git Bash from the Start menu",[28,1696,1697],{},"Use Git Bash whenever this course says to use the terminal",[41,1699,1700],{},"See the slides below for the install settings, launch check, and Windows terminal habit",[15,1702,1704,1707],{"id":1703,"level":99},"windows-installer-components",[365,1705,1706],{"id":1703},"Windows Installer: Components",[104,1708,1712,1720],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},"1.4fr","0.9fr","never",[109,1713,1714],{"v-slot:left":111},[41,1715,1716],{},[144,1717],{"alt":1718,"src":1719,"variant":148},"Git for Windows installer component selection screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep01_components.png",[109,1721,1722],{"v-slot:right":111},[25,1723,1724,1727,1733],{},[28,1725,1726],{},"Recommended to have these components selected",[28,1728,1729,1730],{},"Keep ",[266,1731,1732],{},"Git Bash Here",[28,1734,1735,1736],{},"Continue with ",[266,1737,1738],{},"Next",[15,1740,1742,1745],{"id":1741,"level":99},"windows-installer-default-editor",[365,1743,1744],{"id":1741},"Windows Installer: Default Editor",[104,1746,1747,1755],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1748,1749],{"v-slot:left":111},[41,1750,1751],{},[144,1752],{"alt":1753,"src":1754,"variant":148},"Git for Windows installer default editor selection screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep02_default_editor.png",[109,1756,1757],{"v-slot:right":111},[25,1758,1759,1762,1767],{},[28,1760,1761],{},"Choose the editor you are comfortable with",[28,1763,1764,1766],{},[266,1765,1194],{}," or VS Code is friendlier than Vim for most beginners",[28,1768,1769],{},"This setting affects Git messages if Git opens an editor",[15,1771,1773,1776],{"id":1772,"level":99},"windows-installer-branch-name",[365,1774,1775],{"id":1772},"Windows Installer: Branch Name",[104,1777,1778,1786],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1779,1780],{"v-slot:left":111},[41,1781,1782],{},[144,1783],{"alt":1784,"src":1785,"variant":148},"Git for Windows installer default branch name screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep03_branch_naming.png",[109,1787,1788],{"v-slot:right":111},[25,1789,1790,1796,1799],{},[28,1791,1792,1793],{},"Select the option that uses ",[266,1794,1795],{},"main",[28,1797,1798],{},"Course repositories will tell you which branch to use later",[28,1800,1801],{},"Do not create custom branch names here",[15,1803,1805,1808],{"id":1804,"level":99},"windows-installer-path",[365,1806,1807],{"id":1804},"Windows Installer: PATH",[104,1809,1810,1818],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1811,1812],{"v-slot:left":111},[41,1813,1814],{},[144,1815],{"alt":1816,"src":1817,"variant":148},"Git for Windows installer PATH environment screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep04_path.png",[109,1819,1820],{"v-slot:right":111},[25,1821,1822,1825,1831,1834],{},[28,1823,1824],{},"Select the recommended PATH option",[28,1826,1827,1828],{},"This lets Git Bash and common tools find ",[266,1829,1830],{},"git",[28,1832,1833],{},"Avoid options that say Git Bash only",[28,1835,1836],{},"The third option can be used if you understand the consequences",[15,1838,1840,1843],{"id":1839,"level":99},"windows-installer-ssh",[365,1841,1842],{"id":1839},"Windows Installer: SSH",[104,1844,1845,1853],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1846,1847],{"v-slot:left":111},[41,1848,1849],{},[144,1850],{"alt":1851,"src":1852,"variant":148},"Git for Windows installer SSH executable screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep05_ssh_bundled.png",[109,1854,1855],{"v-slot:right":111},[25,1856,1857,1860,1863],{},[28,1858,1859],{},"Use the bundled OpenSSH option",[28,1861,1862],{},"This keeps Git Bash SSH behavior predictable",[28,1864,1865],{},"SSH setup happens in the next lesson",[15,1867,1869,1873],{"id":1868,"level":99},"windows-installer-openssl",[365,1870,1872],{"id":1871},"windows-installer-https","Windows Installer: HTTPS",[104,1874,1875,1883],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1876,1877],{"v-slot:left":111},[41,1878,1879],{},[144,1880],{"alt":1881,"src":1882,"variant":148},"Git for Windows installer HTTPS transport backend screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep06_openssl.png",[109,1884,1885],{"v-slot:right":111},[25,1886,1887,1890,1893],{},[28,1888,1889],{},"Keep the OpenSSL option",[28,1891,1892],{},"This is the normal Git for Windows choice",[28,1894,1895],{},"It supports secure GitHub connections",[15,1897,1899,1903],{"id":1898,"level":99},"windows-installer-checkout-style",[365,1900,1902],{"id":1901},"windows-installer-line-endings","Windows Installer: Line Endings",[104,1904,1905,1913],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1906,1907],{"v-slot:left":111},[41,1908,1909],{},[144,1910],{"alt":1911,"src":1912,"variant":148},"Git for Windows installer line ending conversion screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep07_checkout_style.png",[109,1914,1915,1926],{"v-slot:right":111},[25,1916,1917,1920,1923],{},[28,1918,1919],{},"Keep the default line-ending option",[28,1921,1922],{},"Git handles Windows and Linux line endings for you",[28,1924,1925],{},"Do not change this unless a lesson says to",[1927,1928,1930],"admonition",{"type":1929},"note",[41,1931,1932],{},"Line-ending warnings may appear later. They are usually informational, not a sign that there's an issue.",[41,1934,1935],{},"::\n::",[15,1937,1939,1943],{"id":1938,"level":99},"windows-installer-mintty",[365,1940,1942],{"id":1941},"windows-installer-terminal-emulator","Windows Installer: Terminal Emulator",[104,1944,1945,1953],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1946,1947],{"v-slot:left":111},[41,1948,1949],{},[144,1950],{"alt":1951,"src":1952,"variant":148},"Git for Windows installer terminal emulator screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep08_mintty.png",[109,1954,1955],{"v-slot:right":111},[25,1956,1957,1960,1963],{},[28,1958,1959],{},"Keep MinTTY selected",[28,1961,1962],{},"This is the normal Git Bash window",[28,1964,1965],{},"Course screenshots will assume this terminal style",[15,1967,1969,1973],{"id":1968,"level":99},"windows-installer-fast-forward",[365,1970,1972],{"id":1971},"windows-installer-pull-behavior","Windows Installer: Pull Behavior",[104,1974,1975,1983],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,1976,1977],{"v-slot:left":111},[41,1978,1979],{},[144,1980],{"alt":1981,"src":1982,"variant":148},"Git for Windows installer git pull behavior screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep09_ff_merge.png",[109,1984,1985],{"v-slot:right":111},[25,1986,1987,1994],{},[28,1988,1989,1990,1993],{},"Keep the default ",[266,1991,1992],{},"git pull"," behavior",[28,1995,1996],{},"Later lessons explain pull, merge, and conflicts",[15,1998,2000,2003],{"id":1999,"level":99},"windows-installer-credential-manager",[365,2001,2002],{"id":1999},"Windows Installer: Credential Manager",[104,2004,2005,2013],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,2006,2007],{"v-slot:left":111},[41,2008,2009],{},[144,2010],{"alt":2011,"src":2012,"variant":148},"Git for Windows installer credential manager screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep10_credential_manager.png",[109,2014,2015],{"v-slot:right":111},[25,2016,2017,2020,2023],{},[28,2018,2019],{},"Keep Git Credential Manager enabled",[28,2021,2022],{},"It helps with browser-based GitHub sign-in",[28,2024,2025],{},"This course still uses SSH for repo pushes",[15,2027,2029,2032],{"id":2028,"level":99},"windows-installer-extra-options",[365,2030,2031],{"id":2028},"Windows Installer: Extra Options",[104,2033,2034,2042],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,2035,2036],{"v-slot:left":111},[41,2037,2038],{},[144,2039],{"alt":2040,"src":2041,"variant":148},"Git for Windows installer extra options screen","\u002Fimages\u002Finternet-applications\u002Fgitbash\u002Fstep11_extra_options_optional.png",[109,2043,2044],{"v-slot:right":111},[25,2045,2046,2054,2065,2073],{},[28,2047,2048,2049],{},"Enable file system caching\n",[25,2050,2051],{},[28,2052,2053],{},"Improves Git performance on Windows",[28,2055,2056,2057],{},"Enable symbolic links if available\n",[25,2058,2059,2062],{},[28,2060,2061],{},"Helps Git handle link-like files correctly",[28,2063,2064],{},"May require Windows Developer Mode or admin rights",[28,2066,2067,2068],{},"Skip experimental options\n",[25,2069,2070],{},[28,2071,2072],{},"They can change behavior between Git versions",[28,2074,2075],{},"Finish the installer",[15,2077,2079,2083],{"id":2078,"level":99},"step-1-open-git-bash-on-windows",[365,2080,2082],{"id":2081},"open-git-bash","Open Git Bash",[25,2084,2085,2088,2091],{},[28,2086,2087],{},"Start menu -> Git Bash",[28,2089,2090],{},"Pin it if that helps you find the same terminal later",[28,2092,2093],{},"Run the checks in the next slides from Git Bash",[15,2095,2097,2100],{"id":2096,"level":99},"windows-terminal-habit",[365,2098,2099],{"id":2096},"Windows Terminal Habit",[25,2101,2102,2105,2108],{},[28,2103,2104],{},"Use Git Bash for course commands on Windows",[28,2106,2107],{},"If another terminal opens by accident, close it and open Git Bash",[28,2109,2110],{},"Staying in one terminal makes setup problems easier to diagnose",[15,2112,2114,2117],{"id":2113,"level":18},"macos-path-terminal",[20,2115,2116],{"id":2113},"macOS Path: Terminal",[25,2118,2119,2122,2125,2128],{},[28,2120,2121],{},"Built-in Terminal is fully supported",[28,2123,2124],{},"Optional iTerm2 gives you tabs, split panes, and profiles",[28,2126,2127],{},"Beginner default: start with Terminal unless you already prefer iTerm2",[28,2129,2130],{},"See the slide below for the optional modern terminal install path",[15,2132,2134,2138],{"id":2133,"level":99},"macos-optional-iterm2-install",[365,2135,2137],{"id":2136},"optional-iterm2-install","Optional iTerm2 Install",[25,2139,2140,2147,2150,2153],{},[28,2141,2142,2143],{},"Download the stable release from ",[45,2144,2145],{"href":2145,"rel":2146},"https:\u002F\u002Fiterm2.com\u002Fdownloads.html",[49],[28,2148,2149],{},"Move iTerm2 to Applications",[28,2151,2152],{},"Open iTerm2 and run the same checks as Terminal",[28,2154,2155],{},"Use Terminal or iTerm2 consistently for course commands",[15,2157,2159,2162,2176,2179,2182],{"id":2158,"level":18},"linux-path-terminal",[20,2160,2161],{"id":2158},"Linux Path: Terminal",[25,2163,2164,2167,2170],{},[28,2165,2166],{},"Open the built-in Terminal app",[28,2168,2169],{},"Git is often installed already",[28,2171,2172,2173,2175],{},"If ",[266,2174,1638],{}," fails, use your distribution package manager",[41,2177,2178],{},"For Ubuntu:",[884,2180],{"language":886,"src":2181},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Flinux-path-terminal-01.sh",[25,2183,2184],{},[28,2185,2186],{},"See the slide below for the optional split-pane terminal setup",[15,2188,2190,2194,2197,2199,2202],{"id":2189,"level":99},"linux-optional-tilix-install",[365,2191,2193],{"id":2192},"optional-tilix-install","Optional Tilix Install",[41,2195,2196],{},"Tilix is a Linux terminal with split panes and profiles",[41,2198,2178],{},[884,2200],{"language":886,"src":2201},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Foptional-tilix-install-02.sh",[41,2203,2204],{},"Use the built-in Terminal if optional installs add friction",[15,2206,2208,2212],{"id":2207,"level":18},"step-3-confirm-git-and-shell",[20,2209,2211],{"id":2210},"confirm-git-and-shell","Confirm Git And Shell",[104,2213,2216,2230],{"gap":106,"left-width":2214,"right-width":2215},"1.15fr","0.85fr",[109,2217,2218,2220,2223,2226],{"v-slot:left":111},[41,2219,882],{},[884,2221],{"language":886,"src":2222},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Fconfirm-git-and-shell-03.sh",[41,2224,2225],{},"Expected output:",[884,2227],{"language":2228,"src":2229},"plaintext","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Fexample-output-04.txt",[109,2231,2232,2235],{"v-slot:right":111},[41,2233,2234],{},"This confirms:",[25,2236,2237,2240,2243],{},[28,2238,2239],{},"Git is installed",[28,2241,2242],{},"The terminal can find Git",[28,2244,2245],{},"Your shell matches later course commands",[15,2247,2249,2253],{"id":2248,"level":18},"step-4-cli-safety-check-before-every-git-command",[20,2250,2252],{"id":2251},"check-location-before-git-commands","Check Location Before Git Commands",[104,2254,2256,2268],{"gap":106,"left-width":2255,"right-width":1710},"1.1fr",[109,2257,2258,2260,2263,2265],{"v-slot:left":111},[41,2259,882],{},[884,2261],{"language":886,"src":2262},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Fcheck-location-before-git-commands-05.sh",[41,2264,2225],{},[884,2266],{"language":2228,"src":2267},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools\u002Fexample-output-06.txt",[109,2269,2270,2273],{"v-slot:right":111},[41,2271,2272],{},"Use this before Git commands:",[25,2274,2275,2280,2285,2288],{},[28,2276,2277,2279],{},[266,2278,692],{}," shows the current folder",[28,2281,2282,2284],{},[266,2283,1369],{}," shows what is inside it",[28,2286,2287],{},"If the folder is wrong, fix location first",[28,2289,2290],{},"Do not run Git commands while guessing",[15,2292,2293,2295],{"id":1372,"level":18},[20,2294,1375],{"id":1372},[104,2296,2297,2340],{"gap":106,"left-width":107,"right-width":107},[109,2298,2299],{"v-slot:left":111},[25,2300,2301,2314,2332],{},[28,2302,2303,2306],{},[266,2304,2305],{},"git: command not found",[25,2307,2308,2311],{},[28,2309,2310],{},"Git is missing, or this terminal cannot find it",[28,2312,2313],{},"Close the terminal and reopen the correct one",[28,2315,2316,2319],{},[266,2317,2318],{},"not a git repository",[25,2320,2321,2324],{},[28,2322,2323],{},"The command ran outside a cloned repository",[28,2325,1150,2326,2328,2329,2331],{},[266,2327,692],{}," and ",[266,2330,1369],{},", then move to the repo folder",[28,2333,2334,2335],{},"Wrong terminal",[25,2336,2337],{},[28,2338,2339],{},"Windows users should switch back to Git Bash",[109,2341,2342,2345],{"v-slot:right":111},[28,2343,2344],{},"Too many terminals open",[163,2346,2347,2350,2360,2365,2371],{},[28,2348,2349],{},"Close extra terminal windows",[28,2351,2352,2353],{},"Open the correct terminal\n",[25,2354,2355,2357],{},[28,2356,649],{},[28,2358,2359],{},"Apple macOS\u002FLinux: Terminal",[28,2361,2362,2363],{},"Run ",[266,2364,1638],{},[28,2366,2362,2367,2328,2369],{},[266,2368,692],{},[266,2370,1369],{},[28,2372,2373],{},"Continue only after the folder looks right",[15,2375,2376,2378],{"id":1452,"level":18},[20,2377,1456],{"id":1455},[104,2379,2380,2402],{"gap":106,"left-width":107,"right-width":107},[109,2381,2382,2384,2390,2396],{"v-slot:left":111},[365,2383,1464],{"id":1463},[41,2385,2386,2389],{},[126,2387,2388],{},"Terminal"," - A text-based interface where you type commands to control your computer",[41,2391,2392,2395],{},[126,2393,2394],{},"CLI (Command Line Interface)"," - The text-based interface where you type commands",[41,2397,2398,2401],{},[126,2399,2400],{},"Git"," - A tool for tracking changes in code files over time",[109,2403,2404,2406],{"v-slot:right":111},[365,2405,1495],{"id":1452},[25,2407,2408,2415,2421,2427],{},[28,2409,2410],{},[45,2411,2414],{"href":2412,"rel":2413},"https:\u002F\u002Fgit-scm.com\u002Fdownloads",[49],"Git Downloads",[28,2416,2417],{},[45,2418,2420],{"href":1687,"rel":2419},[49],"Git For Windows Install Page",[28,2422,2423],{},[45,2424,2426],{"href":2145,"rel":2425},[49],"iTerm2 Downloads",[28,2428,2429],{},[45,2430,2433],{"href":2431,"rel":2432},"https:\u002F\u002Fgnunn1.github.io\u002Ftilix-web\u002F",[49],"Tilix",[15,2435,2436,2438,2441],{"id":466,"level":18},[20,2437,469],{"id":466},[41,2439,2440],{},"Before moving on, confirm you can:",[25,2442,2443,2446,2450,2457,2460],{},[28,2444,2445],{},"Open the correct terminal for your operating system",[28,2447,2362,2448],{},[266,2449,1638],{},[28,2451,1150,2452,2328,2454,2456],{},[266,2453,692],{},[266,2455,1369],{}," to check your location",[28,2458,2459],{},"Understand what terminal\u002FCLI refers to",[28,2461,2462],{},"Keep track of terminal instances",{"title":111,"searchDepth":493,"depth":493,"links":2464},[2465,2466,2467,2482,2485,2488,2489,2490,2491,2492],{"id":601,"depth":493,"text":604},{"id":1649,"depth":493,"text":1650},{"id":1678,"depth":493,"text":1679,"children":2468},[2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481],{"id":1703,"depth":505,"text":1706},{"id":1741,"depth":505,"text":1744},{"id":1772,"depth":505,"text":1775},{"id":1804,"depth":505,"text":1807},{"id":1839,"depth":505,"text":1842},{"id":1871,"depth":505,"text":1872},{"id":1901,"depth":505,"text":1902},{"id":1941,"depth":505,"text":1942},{"id":1971,"depth":505,"text":1972},{"id":1999,"depth":505,"text":2002},{"id":2028,"depth":505,"text":2031},{"id":2081,"depth":505,"text":2082},{"id":2096,"depth":505,"text":2099},{"id":2113,"depth":493,"text":2116,"children":2483},[2484],{"id":2136,"depth":505,"text":2137},{"id":2158,"depth":493,"text":2161,"children":2486},[2487],{"id":2192,"depth":505,"text":2193},{"id":2210,"depth":493,"text":2211},{"id":2251,"depth":493,"text":2252},{"id":1372,"depth":493,"text":1375},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Install Git and choose the correct terminal for course commands.","Face-to-face class of about 40 students; includes OS-specific terminal choices, Git installation, short checks, and setup friction.","35",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools",{"title":1618,"description":2493},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F02-install-git-tools",[1830,1610,530],"21:30","u1x5bq-JmCg","https:\u002F\u002Fyoutu.be\u002Fu1x5bq-JmCg","71DrP8YI_ks4jUswWJXy9rmZOVVoeaJAEPancHNHsV4",{"id":2506,"title":2507,"audience":10,"body":2508,"contentType":509,"course":510,"description":3583,"estimateBasis":3584,"estimatedDiscussionMinutes":3585,"estimatedLiveMinutes":3586,"estimatedTotalMinutes":3587,"extension":516,"meta":3588,"module":518,"navigation":519,"order":515,"path":3589,"promptAssist":522,"seo":3590,"status":524,"stem":3591,"tags":3592,"videoDuration":3596,"videoId":3597,"videoLink":3598,"videoTitle":3599,"week":518,"__hash__":3600},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh.md","Set Up GitHub SSH",{"type":12,"value":2509,"toc":3555},[2510,2536,2554,2579,2592,2619,2656,2733,2781,2848,2924,2966,2992,3024,3062,3107,3141,3210,3212,3215,3226,3298,3327,3361,3409,3455,3523],[15,2511,2513,2516],{"id":2512,"level":18},"goals",[20,2514,2515],{"id":2512},"Goals",[25,2517,2518,2521,2524,2527,2530,2533],{},[28,2519,2520],{},"Confirm Git works in the correct terminal",[28,2522,2523],{},"Sign in to GitHub with a school or personal account",[28,2525,2526],{},"Create or reuse an SSH key for GitHub",[28,2528,2529],{},"Add the public key to GitHub",[28,2531,2532],{},"Create and clone your course repository",[28,2534,2535],{},"Set Git identity inside the cloned repository",[15,2537,2539,2542,2551],{"id":2538,"level":18},"terminal-by-os",[20,2540,2541],{"id":2538},"Terminal By OS",[25,2543,2544,2546,2549],{},[28,2545,649],{},[28,2547,2548],{},"Apple macOS: Terminal or iTerm2",[28,2550,664],{},[41,2552,2553],{},"Run these commands on your own computer",[15,2555,2557,2560],{"id":2556,"level":18},"git-and-ssh-terms",[20,2558,2559],{"id":2556},"Git And SSH Terms",[25,2561,2562,2565,2573,2576],{},[28,2563,2564],{},"Git identity: name and email attached to commits in a repository",[28,2566,2567,2568],{},"SSH key pair: private key stays on your computer, public key goes to GitHub\n",[25,2569,2570],{},[28,2571,2572],{},"This is how we'll authenticate to GitHub",[28,2574,2575],{},"SSH agent: helper that keeps your private key available to Git commands",[28,2577,2578],{},"Clone: local folder connected to a GitHub repository",[15,2580,2582,2585,2589],{"id":2581,"level":18},"ssh-key-flow",[20,2583,2584],{"id":2581},"SSH Key Flow",[2586,2587],"mermaid",{"code":2588},"sequenceDiagram\n  participant Terminal\n  participant PrivateKey as Private key on your computer\n  participant GitHub as Public key in GitHub\n  Terminal->>PrivateKey: Load key with ssh-add\n  Terminal->>GitHub: Ask to authenticate\n  GitHub-->>Terminal: Confirm matching public key\n",[41,2590,2591],{},"GitHub receives only the public key. The private key stays on your computer",[15,2593,2595,2598],{"id":2594,"level":18},"step-1-check-git",[20,2596,2597],{"id":2594},"Step 1: Check Git",[104,2599,2600,2608],{"gap":106,"left-width":107,"right-width":107},[109,2601,2602,2604],{"v-slot:left":111},[41,2603,882],{},[884,2605],{"label":2606,"language":886,"src":2607},"check-git.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-1-check-git-01.sh",[109,2609,2610,2612,2616],{"v-slot:right":111},[41,2611,2225],{},[884,2613],{"label":2614,"language":2228,"src":2615},"example-output.txt","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-02.txt",[41,2617,2618],{},"A valid version means Git is installed and available in this terminal",[15,2620,2622,2626],{"id":2621,"level":18},"step-2-github-account",[20,2623,2625],{"id":2624},"step-2-sign-in-to-github","Step 2: Sign In To GitHub",[104,2627,2629,2648],{"gap":106,"left-width":107,"right-width":2628},"0.8fr",[109,2630,2631],{"v-slot:left":111},[25,2632,2633,2636,2639,2642,2645],{},[28,2634,2635],{},"Use an existing GitHub account or create one",[28,2637,2638],{},"School email recommended for course identity",[28,2640,2641],{},"Personal email is fine if you prefer it",[28,2643,2644],{},"Avoid work email so course access does not depend on an employer account",[28,2646,2647],{},"Confirm you can open GitHub Settings before continuing",[109,2649,2650],{"v-slot:right":111},[41,2651,2652],{},[144,2653],{"alt":2654,"src":2655,"variant":148},"GitHub account menu open with Settings visible","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fgithub-logged-in.png",[15,2657,2659,2663],{"id":2658,"level":18},"step-2-create-repo",[20,2660,2662],{"id":2661},"step-3-create-course-repository","Step 3: Create Course Repository",[104,2664,2666,2725],{"gap":106,"left-width":2665,"right-width":2214},"0.95fr",[109,2667,2668,2671],{"v-slot:left":111},[41,2669,2670],{},"In GitHub:",[25,2672,2673,2678,2684,2690,2705,2711,2714,2722],{},[28,2674,170,2675],{},[266,2676,2677],{},"+",[28,2679,2680,2681],{},"Choose ",[266,2682,2683],{},"New repository",[28,2685,2686,2687],{},"Name it ",[266,2688,2689],{},"\u003Cucid>-IT202-\u003Csection>-\u003CsemYear>",[28,2691,2692,2693,2696,2697,2700,2701,2704],{},"Semester code examples: ",[266,2694,2695],{},"S2026"," spring, ",[266,2698,2699],{},"M2026"," summer, ",[266,2702,2703],{},"F2026"," fall",[28,2706,2707,2708],{},"Set visibility to ",[266,2709,2710],{},"Private",[28,2712,2713],{},"Toggle \"Add README\"",[28,2715,2716,2717],{},"Do not toggle \"Add .gitignore\"",[25,2718,2719],{},[28,2720,2721],{},"A future lesson will discuss and add this important file",[28,2723,2724],{},"Do not add starter files unless instructed",[109,2726,2727],{"v-slot:right":111},[41,2728,2729],{},[144,2730],{"alt":2731,"src":2732,"variant":148},"GitHub new repository form with course naming pattern, private visibility, and README enabled","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fnew-repo.png",[15,2734,2736,2740,2767],{"id":2735,"level":18},"step-3-check-existing-key",[20,2737,2739],{"id":2738},"step-4-check-for-existing-ssh-key","Step 4: Check For Existing SSH Key",[104,2741,2742,2750],{"gap":106,"left-width":107,"right-width":107},[109,2743,2744,2746],{"v-slot:left":111},[41,2745,882],{},[884,2747],{"label":2748,"language":886,"src":2749},"check-ssh-folder.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-3-check-for-existing-ssh-key-03.sh",[109,2751,2752,2755,2758],{"v-slot:right":111},[41,2753,2754],{},"Example output:",[884,2756],{"label":2614,"language":2228,"src":2757},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-04.txt",[41,2759,2760,2761,2328,2764],{},"Look for a matching GitHub-specific pair such as ",[266,2762,2763],{},"github_key",[266,2765,2766],{},"github_key.pub",[41,2768,2769,2770,2773,2774,1201,2777,2780],{},"You can reuse an existing matching pair only if it is ",[126,2771,2772],{},"NOT"," a default key such as ",[266,2775,2776],{},"id_ed25519",[266,2778,2779],{},"id_rsa",". Otherwise, create a GitHub-specific key in the next step",[15,2782,2784,2788,2790,2794,2796,2799],{"id":2783,"level":18},"step-4-create-key-if-needed",[20,2785,2787],{"id":2786},"step-5-create-ssh-key-if-needed","Step 5: Create SSH Key If Needed",[41,2789,882],{},[884,2791],{"label":2792,"language":886,"src":2793},"create-github-key.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-4-create-ssh-key-if-needed-05.sh",[41,2795,2754],{},[884,2797],{"label":2614,"language":2228,"src":2798},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-06.txt",[25,2800,2801,2827,2832,2837],{},[28,2802,2803,2804],{},"Command flags:\n",[25,2805,2806,2812,2818],{},[28,2807,2808,2811],{},[266,2809,2810],{},"-t"," chooses the key type",[28,2813,2814,2817],{},[266,2815,2816],{},"-C"," adds a comment label, usually your GitHub email",[28,2819,2820,2822,2823,2826],{},[266,2821,1165],{}," chooses the output file path (must include ",[266,2824,2825],{},"~\u002F.ssh\u002F"," followed by the file name)",[28,2828,2829,2831],{},[266,2830,2763],{}," is the private key file",[28,2833,2834,2836],{},[266,2835,2766],{}," is the public key file for GitHub",[28,2838,2839,2840],{},"Passphrase is optional unless your instructor requires one\n",[25,2841,2842,2845],{},[28,2843,2844],{},"Pro: protects the key if someone gets the file",[28,2846,2847],{},"Con: adds an unlock prompt when the key is used",[15,2849,2851,2855,2872,2904],{"id":2850,"level":18},"step-5-start-agent-and-add-key",[20,2852,2854],{"id":2853},"step-6-start-ssh-agent-and-verify-key","Step 6: Start SSH Agent And Verify Key",[104,2856,2857,2865],{"gap":106,"left-width":2255,"right-width":107},[109,2858,2859,2861],{"v-slot:left":111},[41,2860,882],{},[884,2862],{"label":2863,"language":886,"src":2864},"start-agent-add-key.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-5-start-ssh-agent-and-add-key-07.sh",[109,2866,2867,2869],{"v-slot:right":111},[41,2868,2754],{},[884,2870],{"label":2614,"language":2228,"src":2871},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-08.txt",[25,2873,2874,2880,2901],{},[28,2875,2876,2879],{},[266,2877,2878],{},"eval \"$(ssh-agent -s)\""," starts the SSH helper GitHub docs usually show",[28,2881,2882,2883,2886,2887,2890],{},"If that fails, run ",[266,2884,2885],{},"exec ssh-agent bash",", then run ",[266,2888,2889],{},"ssh-add ~\u002F.ssh\u002Fgithub_key",[25,2891,2892],{},[28,2893,1150,2894,2897,2898,2900],{},[266,2895,2896],{},"~\u002F.ssh\u002Fgithub_key"," because ",[266,2899,789],{}," avoids issues with spaces in home directory paths",[28,2902,2903],{},"Then verify the key is loaded",[104,2905,2906,2914],{"gap":106,"left-width":107,"right-width":107},[109,2907,2908,2910],{"v-slot:left":111},[41,2909,882],{},[884,2911],{"label":2912,"language":886,"src":2913},"verify-loaded-key.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fverify-loaded-key-09.sh",[109,2915,2916,2918,2921],{"v-slot:right":111},[41,2917,2225],{},[884,2919],{"label":2614,"language":2228,"src":2920},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-10.txt",[41,2922,2923],{},"One loaded key is enough for this lesson",[15,2925,2927,2931,2948],{"id":2926,"level":18},"step-6-copy-public-key",[20,2928,2930],{"id":2929},"step-7-copy-public-key","Step 7: Copy Public Key",[104,2932,2933,2941],{"gap":106,"left-width":107,"right-width":107},[109,2934,2935,2937],{"v-slot:left":111},[41,2936,882],{},[884,2938],{"label":2939,"language":886,"src":2940},"show-public-key.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-6-copy-public-key-11.sh",[109,2942,2943,2945],{"v-slot:right":111},[41,2944,2754],{},[884,2946],{"label":2614,"language":2228,"src":2947},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-12.txt",[25,2949,2950,2960],{},[28,2951,2952,2953,2956,2957,2959],{},"Copy the full line starting with ",[266,2954,2955],{},"ssh-ed25519"," and ending with the value you set with ",[266,2958,2816],{}," earlier",[28,2961,2962,2963,2965],{},"Do not copy ",[266,2964,2763],{},", which is the private key (never share the private key)",[15,2967,2969,2973],{"id":2968,"level":18},"step-7-add-key-to-github",[20,2970,2972],{"id":2971},"step-8-add-key-to-github","Step 8: Add Key To GitHub",[25,2974,2975,2978,2983,2986,2989],{},[28,2976,2977],{},"In GitHub, open account settings",[28,2979,1684,2980],{},[266,2981,2982],{},"SSH and GPG keys",[28,2984,2985],{},"Add a new authentication key",[28,2987,2988],{},"Paste the public key from the previous step",[28,2990,2991],{},"See the slides below for the GitHub screens",[15,2993,2995,2999],{"id":2994,"level":99},"step-8-open-github-settings",[365,2996,2998],{"id":2997},"open-github-settings","Open GitHub Settings",[104,3000,3001,3009],{"gap":106,"left-width":2255,"right-width":1710,"stack":1711},[109,3002,3003],{"v-slot:left":111},[41,3004,3005],{},[144,3006],{"alt":3007,"src":3008,"variant":148},"GitHub profile menu with Settings highlighted","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fssh-key-01-gh-menu.png",[109,3010,3011],{"v-slot:right":111},[25,3012,3013,3016,3021],{},[28,3014,3015],{},"Click your GitHub profile photo",[28,3017,2680,3018],{},[266,3019,3020],{},"Settings",[28,3022,3023],{},"Use the account menu, not the repository settings",[15,3025,3027,3031],{"id":3026,"level":99},"step-8-open-ssh-keys-page",[365,3028,3030],{"id":3029},"open-ssh-and-gpg-keys","Open SSH And GPG Keys",[104,3032,3033,3041],{"gap":106,"left-width":2255,"right-width":1710,"stack":1711},[109,3034,3035],{"v-slot:left":111},[41,3036,3037],{},[144,3038],{"alt":3039,"src":3040,"variant":148},"GitHub settings sidebar with SSH and GPG keys selected","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fssh-key-02-gh-ssh-link.png",[109,3042,3043],{"v-slot:right":111},[25,3044,3045,3052,3057],{},[28,3046,3047,3048,3051],{},"Find the ",[266,3049,3050],{},"Access"," section",[28,3053,3054,3055],{},"Open ",[266,3056,2982],{},[28,3058,2680,3059],{},[266,3060,3061],{},"New SSH key",[15,3063,3065,3069],{"id":3064,"level":99},"step-8-add-new-ssh-key",[365,3066,3068],{"id":3067},"add-new-ssh-key","Add New SSH Key",[104,3070,3072,3080],{"gap":106,"left-width":3071,"right-width":2215,"stack":1711},"1.35fr",[109,3073,3074],{"v-slot:left":111},[41,3075,3076],{},[144,3077],{"alt":3078,"src":3079,"variant":148},"GitHub Add new SSH Key form with title, authentication key type, and public key field","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fssh-key-03-add-new-key.png",[109,3081,3082],{"v-slot:right":111},[25,3083,3084,3090,3096,3099,3104],{},[28,3085,3086,3087],{},"Title it clearly, such as ",[266,3088,3089],{},"\u003Ccourse> Laptop",[28,3091,3092,3093],{},"Keep key type as ",[266,3094,3095],{},"Authentication Key",[28,3097,3098],{},"Paste the full public key line",[28,3100,170,3101],{},[266,3102,3103],{},"Add SSH key",[28,3105,3106],{},"Never paste the private key",[15,3108,3110,3114],{"id":3109,"level":18},"step-8-test-auth",[20,3111,3113],{"id":3112},"step-9-test-github-ssh-access","Step 9: Test GitHub SSH Access",[104,3115,3116,3131],{"gap":106,"left-width":107,"right-width":2255},[109,3117,3118,3120,3124],{"v-slot:left":111},[41,3119,882],{},[884,3121],{"label":3122,"language":886,"src":3123},"test-github-ssh.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-8-test-github-ssh-access-13.sh",[41,3125,3126,3127,3130],{},"If prompted the first time, type ",[266,3128,3129],{},"yes"," to trust GitHub's host key",[109,3132,3133,3135,3138],{"v-slot:right":111},[41,3134,2225],{},[884,3136],{"label":2614,"language":2228,"src":3137},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-14.txt",[41,3139,3140],{},"This confirms authentication, then GitHub closes the connection",[15,3142,3144,3148],{"id":3143,"level":18},"step-9-clone-repo",[20,3145,3147],{"id":3146},"step-10-clone-course-repository","Step 10: Clone Course Repository",[104,3149,3150,3191],{"gap":106,"left-width":1710,"right-width":2255},[109,3151,3152,3156,3185],{"v-slot:left":111},[365,3153,3155],{"id":3154},"get-the-ssh-clone-url","Get The SSH Clone URL",[25,3157,3158,3164,3171,3178],{},[28,3159,3160,3161],{},"In your GitHub repository, click ",[266,3162,3163],{},"Code",[28,3165,3166,3167,3170],{},"Choose the ",[266,3168,3169],{},"SSH"," tab",[28,3172,3173,3174,3177],{},"Copy the ",[266,3175,3176],{},"git@github.com:..."," link",[28,3179,3180,3181,3184],{},"Use that link in the ",[266,3182,3183],{},"git clone"," command",[41,3186,3187],{},[144,3188],{"alt":3189,"src":3190,"variant":148},"GitHub repository Code menu with SSH clone URL selected","\u002Fimages\u002Finternet-applications\u002Fgithub-ssh\u002Fgithub-clone-url.png",[109,3192,3193,3196,3200],{"v-slot:right":111},[41,3194,3195],{},"Run from the folder that should contain your course repo:",[884,3197],{"label":3198,"language":886,"src":3199},"clone-course-repository.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-9-clone-course-repository-15.sh",[1927,3201,3203],{"type":3202},"tip",[41,3204,3205,3206,3209],{},"Before cloning, run ",[266,3207,3208],{},"git rev-parse --show-toplevel",". If it prints a path, move somewhere else first. Clone this repo only once.",[41,3211,2754],{},[884,3213],{"label":2614,"language":2228,"src":3214},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-16.txt",[41,3216,3217,3218,3221,3222,3225],{},"If you see an empty repository warning, you probably forgot to add ",[266,3219,3220],{},"README.md"," when creating the repo. Create it with ",[266,3223,3224],{},"touch README.md",", then use the add\u002Fcommit\u002Fpush commands from the next lesson\n::\n::",[15,3227,3229,3233,3252,3271,3291],{"id":3228,"level":18},"step-10-set-repo-identity",[20,3230,3232],{"id":3231},"step-11-set-repo-git-identity","Step 11: Set Repo Git Identity",[104,3234,3235,3244],{"gap":106,"left-width":107,"right-width":107},[109,3236,3237,3240],{"v-slot:left":111},[41,3238,3239],{},"Run inside the cloned repository:",[884,3241],{"label":3242,"language":886,"src":3243},"set-repo-identity.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-10-set-repo-git-identity-17.sh",[109,3245,3246,3248],{"v-slot:right":111},[41,3247,2225],{},[884,3249],{"label":3250,"language":2228,"src":3251},"config-output.txt","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-19.txt",[104,3253,3254,3263],{"gap":106,"left-width":107,"right-width":107},[109,3255,3256,3259],{"v-slot:left":111},[41,3257,3258],{},"Then verify:",[884,3260],{"label":3261,"language":886,"src":3262},"verify-repo-identity.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fstep-10-set-repo-git-identity-18.sh",[109,3264,3265,3267],{"v-slot:right":111},[41,3266,2225],{},[884,3268],{"label":3269,"language":2228,"src":3270},"identity-output.txt","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh\u002Fexample-output-20.txt",[25,3272,3273,3279,3285],{},[28,3274,3275,3278],{},[266,3276,3277],{},"user.name"," can be your real or display name, though commonly it's your GitHub username",[28,3280,3281,3284],{},[266,3282,3283],{},"user.email"," should match a GitHub email or GitHub no-reply address for commit linking to work (this is important)",[28,3286,3287,3290],{},[266,3288,3289],{},"core.sshCommand"," tells this repository to use your course GitHub key",[41,3292,3293,3294,3297],{},"These commands set identity for this repository. The ",[266,3295,3296],{},"--global"," flag is an option only if you intentionally want the same identity for all repositories",[15,3299,3301,3305,3308,3324],{"id":3300,"level":18},"step-11-invite-collaborators",[20,3302,3304],{"id":3303},"step-12-invite-course-collaborators","Step 12: Invite Course Collaborators",[41,3306,3307],{},"In GitHub, open your course repository:",[25,3309,3310,3313,3318,3321],{},[28,3311,3312],{},"Settings -> Collaborators and teams",[28,3314,3315,3316],{},"Invite ",[266,3317,379],{},[28,3319,3320],{},"Invite your TA if your section has one",[28,3322,3323],{},"Wait until the invitation shows as sent or accepted",[41,3325,3326],{},"This is so it can be accessed for grading and assistance",[15,3328,3330,3333],{"id":3329,"level":18},"troubleshooting-auth",[20,3331,3332],{"id":3329},"Troubleshooting Auth",[25,3334,3335,3341,3348,3355,3358],{},[28,3336,3337,3340],{},[266,3338,3339],{},"Permission denied (publickey)",": GitHub did not accept a loaded key",[28,3342,3343,3344,3347],{},"No loaded key in ",[266,3345,3346],{},"ssh-add -l",": start the agent and add the key again",[28,3349,3350,3351,3354],{},"Wrong key in GitHub: delete it and paste the ",[266,3352,3353],{},".pub"," key again",[28,3356,3357],{},"Wrong account: make sure the success message names your GitHub account",[28,3359,3360],{},"See the slide below for a quick reset sequence",[15,3362,3364,3368,3370,3397],{"id":3363,"level":99},"troubleshooting-auth-recovery",[365,3365,3367],{"id":3366},"quick-reset-sequence","Quick Reset Sequence",[41,3369,882],{},[163,3371,3372,3376,3380,3384,3389,3392],{},[28,3373,3374],{},[266,3375,2878],{},[28,3377,3378],{},[266,3379,2889],{},[28,3381,3382],{},[266,3383,3346],{},[28,3385,3386],{},[266,3387,3388],{},"cat ~\u002F.ssh\u002Fgithub_key.pub",[28,3390,3391],{},"Re-paste the public key in GitHub if needed",[28,3393,3394],{},[266,3395,3396],{},"ssh -T git@github.com",[41,3398,2172,3399,3401,3402,3404,3405,3408],{},[266,3400,2878],{}," fails in Git Bash, use ",[266,3403,2885],{},", then repeat the ",[266,3406,3407],{},"ssh-add"," steps",[15,3410,3411,3413,3416],{"id":437,"level":18},[20,3412,440],{"id":437},[41,3414,3415],{},"You are done when all are true:",[25,3417,3418,3423,3430,3435,3438,3443,3446],{},[28,3419,3420,3422],{},[266,3421,1638],{}," works",[28,3424,3425,3427,3428],{},[266,3426,3346],{}," shows ",[266,3429,2763],{},[28,3431,3432,3434],{},[266,3433,3396],{}," names your GitHub account",[28,3436,3437],{},"Your private course repository exists on GitHub",[28,3439,3440,3442],{},[266,3441,379],{}," and your TA, if applicable, are invited as collaborators",[28,3444,3445],{},"Your local terminal is open to the cloned repository",[28,3447,3448,2328,3451,3454],{},[266,3449,3450],{},"git config user.name",[266,3452,3453],{},"git config user.email"," return your repo identity",[15,3456,3457,3459],{"id":1452,"level":18},[20,3458,1456],{"id":1455},[104,3460,3461,3489],{"gap":106,"left-width":107,"right-width":107},[109,3462,3463,3465,3471,3477,3483],{"v-slot:left":111},[365,3464,1464],{"id":1463},[41,3466,3467,3470],{},[126,3468,3469],{},"Git identity"," - commit name and email saved in repo config",[41,3472,3473,3476],{},[126,3474,3475],{},"SSH key pair"," - private key on your computer, public key in GitHub",[41,3478,3479,3482],{},[126,3480,3481],{},"SSH agent"," - background helper that makes your private key available",[41,3484,3485,3488],{},[126,3486,3487],{},"Clone"," - local copy of a GitHub repository",[109,3490,3491,3493],{"v-slot:right":111},[365,3492,1495],{"id":1452},[25,3494,3495,3502,3509,3516],{},[28,3496,3497],{},[45,3498,3501],{"href":3499,"rel":3500},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fauthentication\u002Fconnecting-to-github-with-ssh\u002Fgenerating-a-new-ssh-key-and-adding-it-to-the-ssh-agent",[49],"GitHub Docs: Generate a new SSH key and add it to the ssh-agent",[28,3503,3504],{},[45,3505,3508],{"href":3506,"rel":3507},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fauthentication\u002Fconnecting-to-github-with-ssh\u002Ftesting-your-ssh-connection",[49],"GitHub Docs: Testing your SSH connection",[28,3510,3511],{},[45,3512,3515],{"href":3513,"rel":3514},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Frepositories\u002Fcreating-and-managing-repositories\u002Fcreating-a-new-repository",[49],"GitHub Docs: Create a repository",[28,3517,3518],{},[45,3519,3522],{"href":3520,"rel":3521},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Frepositories\u002Fcreating-and-managing-repositories\u002Fcloning-a-repository",[49],"GitHub Docs: Cloning a repository",[15,3524,3525,3527,3529],{"id":466,"level":18},[20,3526,469],{"id":466},[41,3528,1525],{},[25,3530,3531,3534,3537,3540,3543,3546,3552],{},[28,3532,3533],{},"Use the correct terminal for your operating system",[28,3535,3536],{},"Authenticate to GitHub with SSH",[28,3538,3539],{},"Find your private course repository on GitHub",[28,3541,3542],{},"Invite course collaborators",[28,3544,3545],{},"Open the local clone in the terminal",[28,3547,3548,3549],{},"Show repo-local Git identity with ",[266,3550,3551],{},"git config",[28,3553,3554],{},"Next: practice the Git commands used for course work",{"title":111,"searchDepth":493,"depth":493,"links":3556},[3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3573,3574,3575,3576,3577,3580,3581,3582],{"id":2512,"depth":493,"text":2515},{"id":2538,"depth":493,"text":2541},{"id":2556,"depth":493,"text":2559},{"id":2581,"depth":493,"text":2584},{"id":2594,"depth":493,"text":2597},{"id":2624,"depth":493,"text":2625},{"id":2661,"depth":493,"text":2662},{"id":2738,"depth":493,"text":2739},{"id":2786,"depth":493,"text":2787},{"id":2853,"depth":493,"text":2854},{"id":2929,"depth":493,"text":2930},{"id":2971,"depth":493,"text":2972,"children":3569},[3570,3571,3572],{"id":2997,"depth":505,"text":2998},{"id":3029,"depth":505,"text":3030},{"id":3067,"depth":505,"text":3068},{"id":3112,"depth":493,"text":3113},{"id":3146,"depth":493,"text":3147},{"id":3231,"depth":493,"text":3232},{"id":3303,"depth":493,"text":3304},{"id":3329,"depth":493,"text":3332,"children":3578},[3579],{"id":3366,"depth":505,"text":3367},{"id":437,"depth":493,"text":440},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Connect your computer to GitHub with SSH, create the course repository, clone it, and set repo-local Git identity.","Face-to-face class of about 40 students; includes GitHub account check, SSH key generation, GitHub UI steps, repo creation, clone troubleshooting, repo-local Git identity, and authentication checks.","15","70","85",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh",{"title":2507,"description":3583},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F03-setup-github-ssh",[1830,3593,3594,3595],"github","ssh","repository","48:26","HZG3_HfczOk","https:\u002F\u002Fyoutu.be\u002FHZG3_HfczOk","Setup Git SSH and GitHub","rJ2RP6nrPEoOj98kzeevFpO0YOXaJl-M5ajP_tsjwvA",{"id":3602,"title":3603,"audience":10,"body":3604,"contentType":509,"course":510,"description":4524,"estimateBasis":4525,"estimatedDiscussionMinutes":514,"estimatedLiveMinutes":3586,"estimatedTotalMinutes":4526,"extension":516,"meta":4527,"module":518,"navigation":519,"order":4528,"path":4529,"promptAssist":522,"seo":4530,"status":524,"stem":4531,"tags":4532,"videoDuration":4535,"videoId":4536,"videoLink":4537,"videoTitle":4538,"week":518,"__hash__":4539},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs.md","Git Commands And Pull Requests",{"type":12,"value":3605,"toc":4489},[3606,3635,3656,3673,3705,3739,3790,3806,3827,3858,3890,3932,3963,3998,4022,4067,4094,4124,4142,4154,4190,4223,4259,4293,4319,4347,4377,4444,4486],[15,3607,3609,3612,3615],{"id":3608,"level":18},"objectives",[20,3610,3611],{"id":3608},"Objectives",[41,3613,3614],{},"By the end, you should be able to:",[25,3616,3617,3620,3623,3626,3629,3632],{},[28,3618,3619],{},"Explain what the common Git commands do",[28,3621,3622],{},"Connect commands to the working folder, staging area, local commits, and GitHub remote",[28,3624,3625],{},"Create a branch for practice work",[28,3627,3628],{},"Stage, commit, and push a small change",[28,3630,3631],{},"Open a pull request on GitHub",[28,3633,3634],{},"Investigate a failed push and a merge conflict",[15,3636,3638,3642,3645,3648],{"id":3637,"level":18},"git-vs-github",[20,3639,3641],{"id":3640},"git-versus-github","Git Versus GitHub",[41,3643,3644],{},"Git is the tool that tracks file history",[41,3646,3647],{},"GitHub is a website that hosts a remote copy of a Git repository",[25,3649,3650,3653],{},[28,3651,3652],{},"Git: local terminal workflow",[28,3654,3655],{},"GitHub: remote branches, pull requests, issues, and project evidence",[15,3657,3659,3663,3667,3670],{"id":3658,"level":18},"git-stages",[20,3660,3662],{"id":3661},"the-git-stages","The Git Stages",[884,3664],{"language":3665,"src":3666},"text","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fthe-git-stages-01.txt",[41,3668,3669],{},"Common commands:",[884,3671],{"language":3665,"src":3672},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fthe-git-stages-02.txt",[15,3674,3676,3680,3682,3685,3688,3691],{"id":3675,"level":18},"status-first",[20,3677,3679],{"id":3678},"command-1-git-status","Command 1: git status",[41,3681,882],{},[884,3683],{"language":886,"src":3684},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-1-git-status-03.sh",[41,3686,3687],{},"Use this before and after every important Git action",[41,3689,3690],{},"It tells you:",[25,3692,3693,3696,3699,3702],{},[28,3694,3695],{},"Current branch",[28,3697,3698],{},"Changed files",[28,3700,3701],{},"Staged files",[28,3703,3704],{},"Whether your working tree is clean",[15,3706,3708,3712,3714,3717],{"id":3707,"level":18},"branch-command",[20,3709,3711],{"id":3710},"command-2-git-branch","Command 2: git branch",[41,3713,882],{},[884,3715],{"language":886,"src":3716},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-2-git-branch-04.sh",[25,3718,3719,3722,3725],{},[28,3720,3721],{},"Active branch has an asterisk",[28,3723,3724],{},"Branches are separate timelines for work",[28,3726,3727,3728],{},"Branch names are case-sensitive\n",[25,3729,3730],{},[28,3731,3732,2328,3735,3738],{},[266,3733,3734],{},"Practice",[266,3736,3737],{},"practice"," are different names",[15,3740,3742,3746,3751,3754],{"id":3741,"level":18},"create-branch",[20,3743,3745],{"id":3744},"practice-step-1-create-a-branch","Practice Step 1: Create A Branch",[41,3747,3748,3749,1258],{},"Start from ",[266,3750,1795],{},[884,3752],{"language":886,"src":3753},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpractice-step-1-create-a-05.sh",[25,3755,3756,3767],{},[28,3757,3758,3759,3761,3762],{},"First two commands: make sure ",[266,3760,1795],{}," is current\n",[25,3763,3764],{},[28,3765,3766],{},"Explained more later",[28,3768,3769,3770],{},"Branch control commands\n",[25,3771,3772,3778,3784],{},[28,3773,3774,3777],{},[266,3775,3776],{},"git checkout -b practice",": create and switch",[28,3779,3780,3783],{},[266,3781,3782],{},"git branch practice",": create only",[28,3785,3786,3789],{},[266,3787,3788],{},"git checkout practice",": switch to existing",[15,3791,3793,3797,3800,3803],{"id":3792,"level":18},"make-file",[20,3794,3796],{"id":3795},"practice-step-2-make-a-small-file","Practice Step 2: Make A Small File",[41,3798,3799],{},"Create a small practice file:",[884,3801],{"language":886,"src":3802},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpractice-step-2-make-a-s-06.sh",[41,3804,3805],{},"Expected result: Git shows the new file as untracked",[15,3807,3809,3813,3816,3819,3822],{"id":3808,"level":18},"add-command",[20,3810,3812],{"id":3811},"command-3-git-add","Command 3: git add",[41,3814,3815],{},"Stage the new file:",[884,3817],{"language":886,"src":3818},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-3-git-add-07.sh",[41,3820,3821],{},"Staging means: include this change in the next commit",[25,3823,3824],{},[28,3825,3826],{},"See below for add patterns and verification checks",[15,3828,3830,3834,3837,3840],{"id":3829,"level":99},"add-variants",[365,3831,3833],{"id":3832},"common-git-add-patterns","Common git add Patterns",[41,3835,3836],{},"Use the smallest clear target when possible",[884,3838],{"language":886,"src":3839},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommon-git-add-patterns-08.sh",[25,3841,3842,3845,3848],{},[28,3843,3844],{},"Single file: safest when you changed one file",[28,3846,3847],{},"Folder: useful when one feature is grouped in one folder",[28,3849,3850,3853,3854,3857],{},[266,3851,3852],{},"git add .",": convenient, but review ",[266,3855,3856],{},"git status"," first",[15,3859,3861,3865,3868,3871],{"id":3860,"level":18},"diff-command",[20,3862,3864],{"id":3863},"command-4-git-diff","Command 4: git diff",[41,3866,3867],{},"Before committing, inspect what changed:",[884,3869],{"language":886,"src":3870},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-4-git-diff-09.sh",[25,3872,3873,3880,3883,3888],{},[28,3874,3875,3876,3879],{},"New untracked file: ",[266,3877,3878],{},"git diff"," may show nothing",[28,3881,3882],{},"That does not mean the file is missing",[28,3884,1150,3885,3887],{},[266,3886,3856],{}," to confirm untracked files",[28,3889,1320],{},[15,3891,3893,3897,3900,3903,3906,3909],{"id":3892,"level":99},"cached-rm",[365,3894,3896],{"id":3895},"if-you-staged-the-wrong-file","If You Staged The Wrong File",[41,3898,3899],{},"If a file was staged by mistake, remove it from staging:",[884,3901],{"language":886,"src":3902},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fif-you-staged-the-wrong--10.sh",[41,3904,3905],{},"For a folder:",[884,3907],{"language":886,"src":3908},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fif-you-staged-the-wrong--11.sh",[25,3910,3911,3922],{},[28,3912,3913,3916,3917],{},[266,3914,3915],{},"--cached",": remove from staging only\n",[25,3918,3919],{},[28,3920,3921],{},"Keeps the file in your working folder",[28,3923,3924,3926,3927],{},[266,3925,625],{},": folder mode\n",[25,3928,3929],{},[28,3930,3931],{},"Recursive: include files inside the folder",[15,3933,3935,3939,3942,3945,3948],{"id":3934,"level":18},"commit-command",[20,3936,3938],{"id":3937},"command-5-git-commit","Command 5: git commit",[41,3940,3941],{},"Commit the staged file:",[884,3943],{"language":886,"src":3944},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-5-git-commit-12.sh",[41,3946,3947],{},"A commit is a saved checkpoint in your local repository",[25,3949,3950,3961],{},[28,3951,3952,3955,3956],{},[266,3953,3954],{},"-m",": commit message",[25,3957,3958],{},[28,3959,3960],{},"Required, even if the message is an empty string",[28,3962,1320],{},[15,3964,3966,3970,3972,3975,3995],{"id":3965,"level":99},"log-command",[365,3967,3969],{"id":3968},"check-the-local-history","Check The Local History",[41,3971,882],{},[884,3973],{"language":886,"src":3974},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcheck-the-local-history-13.sh",[25,3976,3977,3983,3989],{},[28,3978,3979,3982],{},[266,3980,3981],{},"log",": show commit history",[28,3984,3985,3988],{},[266,3986,3987],{},"--oneline",": one commit per line",[28,3990,3991,3994],{},[266,3992,3993],{},"-5",": show the latest five commits",[41,3996,3997],{},"You should see your latest commit near the top",[15,3999,4001,4005,4008,4011],{"id":4000,"level":18},"push-command",[20,4002,4004],{"id":4003},"command-6-git-push","Command 6: git push",[41,4006,4007],{},"Send the branch to GitHub:",[884,4009],{"language":886,"src":4010},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fcommand-6-git-push-14.sh",[25,4012,4013,4019],{},[28,4014,4015,4018],{},[266,4016,4017],{},"origin",": common remote name for GitHub",[28,4020,4021],{},"Final part: branch you are pushing",[15,4023,4025,4029],{"id":4024,"level":18},"open-pr",[20,4026,4028],{"id":4027},"pull-request","Pull Request",[104,4030,4031,4059],{"gap":106,"left-width":107,"right-width":107},[109,4032,4033,4036,4039,4042,4045,4048],{"v-slot:left":111},[41,4034,4035],{},"On GitHub, open a pull request",[41,4037,4038],{},"Use this direction:",[884,4040],{"language":3665,"src":4041},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpull-request-15.txt",[41,4043,4044],{},"Use a clear description:",[884,4046],{"language":3665,"src":4047},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpull-request-description-16.txt",[25,4049,4050,4053,4056],{},[28,4051,4052],{},"Review page before merge",[28,4054,4055],{},"Shows what will change",[28,4057,4058],{},"Captures branch evidence",[109,4060,4061],{"v-slot:right":111},[41,4062,4063],{},[144,4064],{"alt":4065,"src":4066,"variant":148},"GitHub pull request creation page showing base main and compare practice","\u002Fimages\u002Fshared\u002Fgit-workflow\u002Fgithub-create-pull-request.png",[15,4068,4070,4074,4077,4085,4088,4091],{"id":4069,"level":18},"merge-pr",[20,4071,4073],{"id":4072},"merge-and-sync","Merge And Sync",[41,4075,4076],{},"After GitHub merge:",[25,4078,4079],{},[28,4080,4081,4082,4084],{},"Local ",[266,4083,1795],{}," is not updated automatically",[41,4086,4087],{},"Sync it:",[884,4089],{"language":886,"src":4090},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fmerge-and-sync-15.sh",[41,4092,4093],{},"Remote changes must be pulled down intentionally",[15,4095,4097,4101,4104,4121],{"id":4096,"level":18},"why-prs",[20,4098,4100],{"id":4099},"why-pull-requests-matter","Why Pull Requests Matter",[41,4102,4103],{},"Pull requests create evidence:",[25,4105,4106,4109,4112,4115,4118],{},[28,4107,4108],{},"Which branch changed",[28,4110,4111],{},"Which files changed",[28,4113,4114],{},"What discussion or explanation was provided",[28,4116,4117],{},"Chance to review risky changes before merging",[28,4119,4120],{},"When the change was merged",[41,4122,4123],{},"For this course, pull requests are part of the workflow evidence, not just a GitHub feature",[15,4125,4127,4131,4134],{"id":4126,"level":18},"exploration-intro",[20,4128,4130],{"id":4129},"troubleshooting-explorations","Troubleshooting Explorations",[41,4132,4133],{},"The next slides use controlled problems to practice recovery",[25,4135,4136,4139],{},[28,4137,4138],{},"The goal is not avoiding every error",[28,4140,4141],{},"The goal is reading output, identifying state, and recovering without guessing",[15,4143,4145,4148,4151],{"id":4144,"level":18},"exploration-setup",[20,4146,4147],{"id":4144},"Exploration Setup",[41,4149,4150],{},"Create a conflict practice branch:",[884,4152],{"language":886,"src":4153},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fexploration-setup-16.sh",[15,4155,4157,4161,4167,4174,4179,4182,4185],{"id":4156,"level":18},"exploration-issue-1",[20,4158,4160],{"id":4159},"exploration-issue-1-push-rejected","Exploration Issue 1: Push Rejected",[41,4162,4163,4164],{},"On GitHub, switch to ",[266,4165,4166],{},"practice-conflict",[41,4168,4169,4170,4173],{},"Edit one line in ",[266,4171,4172],{},"myFile.txt"," directly on GitHub and commit the change",[25,4175,4176],{},[28,4177,4178],{},"Use the same line you will change locally",[41,4180,4181],{},"Back locally, edit that same line and commit:",[884,4183],{"language":886,"src":4184},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fexploration-issue-1-push-17.sh",[25,4186,4187],{},[28,4188,4189],{},"See the slides below for the rejected push and the pull that creates the conflict",[15,4191,4193,4197,4200],{"id":4192,"level":99},"issue-1-push-without-pulling",[365,4194,4196],{"id":4195},"try-push-without-pulling","Try Push Without Pulling",[41,4198,4199],{},"Push the local commit before pulling the GitHub commit:",[104,4201,4202,4215],{"gap":106,"left-width":107,"right-width":107},[109,4203,4204,4207],{"v-slot:left":111},[884,4205],{"language":886,"src":4206},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Ftry-push-without-pulling-20.sh",[25,4208,4209,4212],{},[28,4210,4211],{},"Expected result: push rejected",[28,4213,4214],{},"Reason: GitHub has a commit your local branch does not have",[109,4216,4217],{"v-slot:right":111},[41,4218,4219],{},[144,4220],{"alt":4221,"src":4222,"variant":148},"Git push rejected because the remote branch has commits that are not local yet","\u002Fimages\u002Fshared\u002Fgit-workflow\u002Fgit-push-rejected-before-pull.png",[15,4224,4226,4230],{"id":4225,"level":99},"issue-1-read-output",[365,4227,4229],{"id":4228},"pull-the-remote-change","Pull The Remote Change",[104,4231,4232,4251],{"gap":106,"left-width":107,"right-width":107},[109,4233,4234,4237,4240,4243,4248],{"v-slot:left":111},[41,4235,4236],{},"The usual next command is:",[884,4238],{"language":886,"src":4239},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpull-the-remote-change-20.sh",[41,4241,4242],{},"If Git asks how to reconcile divergent branches:",[25,4244,4245],{},[28,4246,4247],{},"Use merge behavior for this course practice",[884,4249],{"language":886,"src":4250},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fpull-the-remote-change-21.sh",[109,4252,4253],{"v-slot:right":111},[41,4254,4255],{},[144,4256],{"alt":4257,"src":4258,"variant":148},"Git pull output asking how to reconcile divergent branches","\u002Fimages\u002Fshared\u002Fgit-workflow\u002Fgit-pull-divergent-branches.png",[15,4260,4262,4266,4269,4273,4276,4279,4282],{"id":4261,"level":18},"exploration-issue-2",[20,4263,4265],{"id":4264},"exploration-issue-2-merge-conflict","Exploration Issue 2: Merge Conflict",[41,4267,4268],{},"After pulling, Git should report a conflict",[41,4270,3054,4271],{},[266,4272,4172],{},[41,4274,4275],{},"You may see markers like:",[884,4277],{"language":3665,"src":4278},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fexploration-issue-2-merg-18.txt",[41,4280,4281],{},"Conflict markers show:",[25,4283,4284,4287,4290],{},[28,4285,4286],{},"Your local version",[28,4288,4289],{},"The GitHub version",[28,4291,4292],{},"The part Git could not combine automatically",[15,4294,4296,4300,4306,4309,4312,4315],{"id":4295,"level":99},"resolve-conflict",[365,4297,4299],{"id":4298},"resolve-the-conflict","Resolve The Conflict",[41,4301,4302,4303,4305],{},"Edit ",[266,4304,4172],{}," so it contains the final text you want",[41,4307,4308],{},"Remove all conflict markers",[41,4310,4311],{},"Then run:",[884,4313],{"language":886,"src":4314},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs\u002Fresolve-the-conflict-19.sh",[25,4316,4317],{},[28,4318,1320],{},[15,4320,4322,4326,4329],{"id":4321,"level":99},"verify-conflict-resolution",[365,4323,4325],{"id":4324},"verify-the-recovery","Verify The Recovery",[41,4327,4328],{},"Check:",[25,4330,4331,4336,4339,4344],{},[28,4332,4333,4335],{},[266,4334,3856],{}," is clean",[28,4337,4338],{},"GitHub shows the updated branch",[28,4340,4341,4343],{},[266,4342,4172],{}," contains the final text",[28,4345,4346],{},"No conflict markers remain",[15,4348,4349,4351],{"id":1372,"level":18},[20,4350,1375],{"id":1372},[25,4352,4353,4356,4359,4362,4365,4374],{},[28,4354,4355],{},"Committing on the wrong branch",[28,4357,4358],{},"Forgetting to push after committing",[28,4360,4361],{},"Forgetting to pull after merging on GitHub",[28,4363,4364],{},"Leaving conflict markers in a file",[28,4366,4367,4368,1201,4371],{},"Using vague branch names like ",[266,4369,4370],{},"stuff",[266,4372,4373],{},"final",[28,4375,4376],{},"Making several unrelated changes in one commit",[15,4378,4379,4381],{"id":1452,"level":18},[20,4380,1456],{"id":1455},[104,4382,4383,4407],{"gap":106,"left-width":107,"right-width":107},[109,4384,4385,4387],{"v-slot:left":111},[365,4386,1464],{"id":1463},[25,4388,4389,4392,4395,4398,4401,4404],{},[28,4390,4391],{},"Working folder: files you can edit",[28,4393,4394],{},"Staging area: changes selected for the next commit",[28,4396,4397],{},"Commit: local saved checkpoint",[28,4399,4400],{},"Remote: GitHub copy of the repository",[28,4402,4403],{},"Pull request: GitHub page for reviewing and merging branch work",[28,4405,4406],{},"Conflict: a change Git cannot merge automatically",[109,4408,4409,4411],{"v-slot:right":111},[365,4410,1495],{"id":1452},[25,4412,4413,4421,4428,4436],{},[28,4414,4415,4416],{},"Pro Git Book: ",[45,4417,4420],{"href":4418,"rel":4419},"https:\u002F\u002Fgit-scm.com\u002Fbook\u002Fen\u002Fv2\u002FGit-Basics-Getting-a-Git-Repository",[49],"Git Basics",[28,4422,4415,4423],{},[45,4424,4427],{"href":4425,"rel":4426},"https:\u002F\u002Fgit-scm.com\u002Fbook\u002Fen\u002Fv2\u002FGit-Branching-Basic-Branching-and-Merging",[49],"Basic Branching and Merging",[28,4429,4430,4431],{},"GitHub Docs: ",[45,4432,4435],{"href":4433,"rel":4434},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fpull-requests\u002Fcollaborating-with-pull-requests\u002Fproposing-changes-to-your-work-with-pull-requests\u002Fcreating-a-pull-request",[49],"Creating a pull request",[28,4437,4438,4439],{},"Oh Shit, Git!?!: ",[45,4440,4443],{"href":4441,"rel":4442},"https:\u002F\u002Fohshitgit.com\u002F",[49],"Common Git recovery situations",[15,4445,4446,4448],{"id":466,"level":18},[20,4447,469],{"id":466},[104,4449,4452,4476],{"gap":516,"left-width":4450,"right-width":4451},"0.72fr","1.38fr",[109,4453,4454,4456],{"v-slot:left":111},[41,4455,1525],{},[25,4457,4458,4464,4467,4470,4473],{},[28,4459,4460,4461,4463],{},"Read ",[266,4462,3856],{}," before choosing the next command",[28,4465,4466],{},"Move a change from working folder to staging area to commit",[28,4468,4469],{},"Push a branch to GitHub and open a pull request",[28,4471,4472],{},"Recognize when a failed push or conflict needs recovery",[28,4474,4475],{},"Next: open the cloned repository in VS Code",[109,4477,4478,4481],{"v-slot:right":111},[41,4479,4480],{},"Git\u002FGitHub flow:",[4482,4483],"figure-image",{"alt":4484,"src":4485},"Lane diagram showing local Git commands moving from the base branch to a feature or homework branch, then pushing to GitHub for pull request review and merge, then pulling the base branch back locally","\u002Fimages\u002Fshared\u002Fgit-github-lane-flow.svg",[41,4487,4488],{},"::",{"title":111,"searchDepth":493,"depth":493,"links":4490},[4491,4492,4493,4494,4495,4496,4497,4498,4501,4504,4507,4508,4509,4510,4511,4512,4513,4517,4521,4522,4523],{"id":3608,"depth":493,"text":3611},{"id":3640,"depth":493,"text":3641},{"id":3661,"depth":493,"text":3662},{"id":3678,"depth":493,"text":3679},{"id":3710,"depth":493,"text":3711},{"id":3744,"depth":493,"text":3745},{"id":3795,"depth":493,"text":3796},{"id":3811,"depth":493,"text":3812,"children":4499},[4500],{"id":3832,"depth":505,"text":3833},{"id":3863,"depth":493,"text":3864,"children":4502},[4503],{"id":3895,"depth":505,"text":3896},{"id":3937,"depth":493,"text":3938,"children":4505},[4506],{"id":3968,"depth":505,"text":3969},{"id":4003,"depth":493,"text":4004},{"id":4027,"depth":493,"text":4028},{"id":4072,"depth":493,"text":4073},{"id":4099,"depth":493,"text":4100},{"id":4129,"depth":493,"text":4130},{"id":4144,"depth":493,"text":4147},{"id":4159,"depth":493,"text":4160,"children":4514},[4515,4516],{"id":4195,"depth":505,"text":4196},{"id":4228,"depth":505,"text":4229},{"id":4264,"depth":493,"text":4265,"children":4518},[4519,4520],{"id":4298,"depth":505,"text":4299},{"id":4324,"depth":505,"text":4325},{"id":1372,"depth":493,"text":1375},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Practice the core Git workflow with small changes, branches, pull requests, and two guided troubleshooting scenarios.","Face-to-face class of about 40 students; includes command explanation, branch practice, pull request walkthrough, conflict exploration, and recovery discussion.","90",{},"40","\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs",{"title":3603,"description":4524},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F04-git-commands-prs",[1830,4533,4534],"branches","pull-requests","48:54","MOa9zIUOqaI","https:\u002F\u002Fyoutu.be\u002FMOa9zIUOqaI","Git Commands and PRs","GTIGHU5IyAE7RcRy68evvCM5YPZVDAWUbiTdBfC9nCI",{"id":4541,"title":4542,"audience":10,"body":4543,"contentType":509,"course":510,"description":5315,"estimateBasis":5316,"estimatedDiscussionMinutes":513,"estimatedLiveMinutes":515,"estimatedTotalMinutes":4528,"extension":516,"meta":5317,"module":518,"navigation":519,"order":5318,"path":5319,"promptAssist":522,"seo":5320,"status":524,"stem":5321,"tags":5322,"videoDuration":5326,"videoId":5327,"videoLink":5328,"videoTitle":5329,"week":518,"__hash__":5330},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment.md","Local Development Environment Setup",{"type":12,"value":4544,"toc":5293},[4545,4562,4580,4601,4626,4661,4693,4771,4848,4950,4978,5043,5120,5144,5171,5189,5213,5264],[15,4546,4548,4551],{"id":4547,"level":18},"local-development-environment-title",[20,4549,4542],{"id":4550},"local-development-environment-setup",[25,4552,4553,4556,4559],{},[28,4554,4555],{},"VS Code for editing course files",[28,4557,4558],{},"Course profile for Internet Applications extensions",[28,4560,4561],{},"Optional local PHP check on your own computer",[15,4563,4564,4566],{"id":601,"level":18},[20,4565,604],{"id":601},[25,4567,4568,4571,4574,4577],{},[28,4569,4570],{},"Install VS Code",[28,4572,4573],{},"Open the course repository root",[28,4575,4576],{},"Install the required extensions for the course",[28,4578,4579],{},"Have a local php install as a light weight dev server (as a backup for the VM lessons)",[15,4581,4583,4586],{"id":4582,"level":18},"what-this-setup-does",[20,4584,4585],{"id":4582},"What This Setup Does",[25,4587,4588,4591,4594],{},[28,4589,4590],{},"VS Code: editor for course files",[28,4592,4593],{},"Extensions: syntax help, Git visibility, database viewing, time tracking",[28,4595,4596,4597,4600],{},"Optional host PHP: quick ",[266,4598,4599],{},"php -v"," check and editor support",[15,4602,4604,4607],{"id":4603,"level":18},"step-1-install-vs-code",[20,4605,4606],{"id":4603},"Step 1: Install VS Code",[25,4608,4609,4617,4620,4623],{},[28,4610,4611,4612],{},"Download: ",[45,4613,4616],{"href":4614,"rel":4615},"https:\u002F\u002Fcode.visualstudio.com\u002FDownload",[49],"Visual Studio Code",[28,4618,4619],{},"Install like a normal desktop app",[28,4621,4622],{},"Do not install VS Code inside your repository folder",[28,4624,4625],{},"VS Code is the editor; the repo is the workspace folder",[15,4627,4629,4632,4635,4658],{"id":4628,"level":18},"step-2-open-the-repository",[20,4630,4631],{"id":4628},"Step 2: Open The Repository",[41,4633,4634],{},"After the course repo is cloned:",[25,4636,4637,4647,4650,4655],{},[28,4638,4639,4640,4643,4644],{},"VS Code -> ",[266,4641,4642],{},"File"," -> ",[266,4645,4646],{},"Open Folder",[28,4648,4649],{},"Choose the repository root",[28,4651,4652,4653],{},"Folder name should match ",[266,4654,2689],{},[28,4656,4657],{},"Trust the workspace only if it is your cloned GitHub repo",[41,4659,4660],{},"Do not open a ZIP copy or clone the same repo again",[15,4662,4664,4668,4690],{"id":4663,"level":18},"step-3-create-course-profile",[20,4665,4667],{"id":4666},"step-3-create-a-course-profile","Step 3: Create A Course Profile",[25,4669,4670,4676,4684,4687],{},[28,4671,4672,4673],{},"Gear icon -> ",[266,4674,4675],{},"Profiles",[28,4677,4678,4679,1201,4681],{},"Create ",[266,4680,510],{},[266,4682,4683],{},"PHP",[28,4685,4686],{},"Switch into that profile",[28,4688,4689],{},"Install course extensions there",[41,4691,4692],{},"Profiles keep this course setup separate from other projects",[15,4694,4696,4699,4703],{"id":4695,"level":18},"step-4-install-extensions",[20,4697,4698],{"id":4695},"Step 4: Install Extensions",[365,4700,4702],{"id":4701},"start-with-these","Start With These",[25,4704,4705,4713,4721,4729,4737,4745,4760,4768],{},[28,4706,4707,4708],{},"Auto Rename Tag (Jun Han)\n",[25,4709,4710],{},[28,4711,4712],{},"Auto-completes matching HTML tags while you edit",[28,4714,4715,4716],{},"Bracket Lens (wraith13)\n",[25,4717,4718],{},[28,4719,4720],{},"Adds readability cues for closing brackets",[28,4722,4723,4724],{},"GitLens (GitKraken)\n",[25,4725,4726],{},[28,4727,4728],{},"Required: Git history, blame, and branch visibility in-editor",[28,4730,4731,4732],{},"MySQL (cweijan)\n",[25,4733,4734],{},[28,4735,4736],{},"Required later: connect to and inspect course database tables",[28,4738,4739,4740],{},"PHP Intelephense (Ben Mewburn)\n",[25,4741,4742],{},[28,4743,4744],{},"PHP language support, syntax checks, and warnings",[28,4746,4747,4748],{},"Todo Tree (Gruntfuggly)\n",[25,4749,4750],{},[28,4751,4752,4753,622,4756,4759],{},"Finds and lists ",[266,4754,4755],{},"TODO",[266,4757,4758],{},"FIXME",", and similar comments",[28,4761,4762,4763],{},"WakaTime\n",[25,4764,4765],{},[28,4766,4767],{},"Required in sections that use time tracking; needs your API key",[28,4769,4770],{},"See the slides below for MySQL and WakaTime setup",[15,4772,4774,4778],{"id":4773,"level":99},"step-4a-setup-mysql-extension",[20,4775,4777],{"id":4776},"step-4a-configure-mysql-extension","Step 4A: Configure MySQL Extension",[104,4779,4781,4840],{"gap":106,"left-width":1710,"right-width":2255,"align":4780},"center",[109,4782,4783,4787],{"v-slot:left":111},[365,4784,4786],{"id":4785},"connection-settings","Connection Settings",[25,4788,4789,4792,4837],{},[28,4790,4791],{},"Open the MySQL panel from the VS Code sidebar",[28,4793,4794,4795],{},"Create a new connection with your course database details",[25,4796,4797,4803,4809,4812,4815],{},[28,4798,4799,4800],{},"Host: ",[266,4801,4802],{},"db.ethereallab.app",[28,4804,4805,4806],{},"Port: ",[266,4807,4808],{},"3306",[28,4810,4811],{},"Username: your UCID",[28,4813,4814],{},"Database: your UCID",[28,4816,4817,4818],{},"Password: from your generated connection string\n",[25,4819,4820,4828],{},[28,4821,4822,4823],{},"Get it from the ",[45,4824,4827],{"href":4825,"rel":4826},"https:\u002F\u002Fcourses.ethereallab.app\u002Fdatabase",[49],"course database page",[28,4829,4830,4831,2328,4834],{},"Use the 12 characters between ",[266,4832,4833],{},"ucid:",[266,4835,4836],{},"@",[28,4838,4839],{},"Save this connection; you will reuse it in later database lessons",[109,4841,4842],{"v-slot:right":111},[41,4843,4844],{},[144,4845],{"alt":4846,"src":4847,"variant":148},"MySQL extension connection setup for the course database","\u002Fimages\u002Finternet-applications\u002Flocal-setup\u002Fmysql-setup.png",[15,4849,4851,4855],{"id":4850,"level":99},"step-4b-setup-wakatime",[20,4852,4854],{"id":4853},"step-4b-configure-wakatime","Step 4B: Configure WakaTime",[104,4856,4858,4913],{"gap":106,"left-width":2665,"right-width":4857,"align":4780},"1.05fr",[109,4859,4860,4864],{"v-slot:left":111},[365,4861,4863],{"id":4862},"setup-order","Setup Order",[25,4865,4866,4873,4876,4879,4882,4885,4902,4907,4910],{},[28,4867,1684,4868],{},[45,4869,4872],{"href":4870,"rel":4871},"https:\u002F\u002Fwakatime.com\u002Fsignup",[49],"WakaTime",[28,4874,4875],{},"Create or open your account",[28,4877,4878],{},"Copy your API key from account settings",[28,4880,4881],{},"In VS Code, search Extensions for WakaTime",[28,4883,4884],{},"Install the WakaTime extension",[28,4886,4887,4888],{},"Open Command Palette:",[25,4889,4890,4896],{},[28,4891,4892,4893],{},"Windows\u002FLinux: ",[266,4894,4895],{},"Ctrl+Shift+P",[28,4897,4898,4899],{},"macOS: ",[266,4900,4901],{},"Cmd+Shift+P",[28,4903,2362,4904],{},[266,4905,4906],{},"WakaTime: API Key",[28,4908,4909],{},"Paste your API key",[28,4911,4912],{},"Restart VS Code if tracking does not appear right away",[109,4914,4915,4920,4927,4932,4939,4944],{"v-slot:right":111},[163,4916,4917],{},[28,4918,4919],{},"WakaTime account settings:",[41,4921,4922],{},[144,4923],{"alt":4924,"src":4925,"variant":148,"max-height":4926},"WakaTime account settings API key detail","\u002Fimages\u002Finternet-applications\u002Flocal-setup\u002Fwakatime\u002Fsettings-api-key-detail.png","14rem",[163,4928,4929],{"start":493},[28,4930,4931],{},"VS Code extension search:",[41,4933,4934],{},[144,4935],{"alt":4936,"src":4937,"variant":148,"max-height":4938},"VS Code Extensions search results showing WakaTime","\u002Fimages\u002Finternet-applications\u002Flocal-setup\u002Fwakatime\u002Fvs-code-search.png","9rem",[163,4940,4941],{"start":505},[28,4942,4943],{},"VS Code API key command:",[41,4945,4946],{},[144,4947],{"alt":4948,"src":4949,"variant":148,"max-height":4938},"Command Palette with WakaTime API key command","\u002Fimages\u002Finternet-applications\u002Flocal-setup\u002Fwakatime\u002Fvs-code-prompt.png",[15,4951,4953,4956],{"id":4952,"level":18},"step-5-optional-local-php",[20,4954,4955],{"id":4952},"Step 5: Optional Local PHP",[25,4957,4958,4961,4964,4972,4975],{},[28,4959,4960],{},"Useful for editor support",[28,4962,4963],{},"Useful for quick terminal checks",[28,4965,4966,4967],{},"Not the main course runtime\n",[25,4968,4969],{},[28,4970,4971],{},"Viable backup solution if VM lesson has issues",[28,4973,4974],{},"VM and Render still run the real app path",[28,4976,4977],{},"See the slides below for OS-specific install notes",[15,4979,4981,4984],{"id":4980,"level":99},"step-5a-windows-php-zip",[20,4982,4983],{"id":4980},"Step 5A: Windows PHP ZIP",[104,4985,4986,5017],{"gap":106,"left-width":107,"right-width":107},[109,4987,4988,4992],{"v-slot:left":111},[365,4989,4991],{"id":4990},"download-and-extract","Download And Extract",[25,4993,4994,4997,5007,5012],{},[28,4995,4996],{},"Download PHP for Windows as a ZIP",[28,4998,4999,5000],{},"Extract it outside your repository",[25,5001,5002],{},[28,5003,775,5004],{},[266,5005,5006],{},"C:\\tools\\php",[28,5008,5009,5010],{},"Add that extracted PHP folder to the user ",[266,5011,1475],{},[28,5013,5014,5015],{},"Restart Git Bash, PowerShell, and VS Code after editing ",[266,5016,1475],{},[109,5018,5019,5023,5039],{"v-slot:right":111},[365,5020,5022],{"id":5021},"visual-checks","Visual Checks",[25,5024,5025,5031,5036],{},[28,5026,5027,5028],{},"The extracted folder contains ",[266,5029,5030],{},"php.exe",[28,5032,5033,5034],{},"The Path entry points to the folder, not to ",[266,5035,5030],{},[28,5037,5038],{},"A new terminal can run:",[884,5040],{"language":886,"src":5041,"label":5042},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment\u002Fwindows-php-path-check-03.sh","windows-php-check.sh",[15,5044,5046,5049],{"id":5045,"level":99},"step-5b-macos-homebrew-php",[20,5047,5048],{"id":5045},"Step 5B: macOS Homebrew PHP",[104,5050,5051,5082],{"gap":106,"left-width":107,"right-width":107},[109,5052,5053,5057],{"v-slot:left":111},[365,5054,5056],{"id":5055},"install-homebrew","Install Homebrew",[25,5058,5059,5062,5070,5073,5076,5079],{},[28,5060,5061],{},"Open Terminal",[28,5063,5064,5065],{},"Copy the install command from ",[45,5066,5069],{"href":5067,"rel":5068},"https:\u002F\u002Fbrew.sh\u002F",[49],"brew.sh",[28,5071,5072],{},"Expect Terminal to ask for your Mac password",[28,5074,5075],{},"Expect Homebrew to mention Command Line Tools if needed",[28,5077,5078],{},"At the end, Homebrew may print \"Next steps\"",[28,5080,5081],{},"Run those \"Next steps\" commands if shown",[109,5083,5084,5088,5092,5095],{"v-slot:right":111},[365,5085,5087],{"id":5086},"then-install-php","Then Install PHP",[884,5089],{"language":886,"src":5090,"label":5091},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment\u002Fmacos-install-php-homebrew-04.sh","macos-php.sh",[41,5093,5094],{},"Look for:",[25,5096,5097,5103,5108,5114],{},[28,5098,5099,5102],{},[266,5100,5101],{},"brew --version"," prints a version",[28,5104,5105,5107],{},[266,5106,4599],{}," prints PHP 8 output",[28,5109,5110,5111],{},"Apple Silicon Macs commonly use ",[266,5112,5113],{},"\u002Fopt\u002Fhomebrew",[28,5115,5116,5117],{},"Intel Macs commonly use ",[266,5118,5119],{},"\u002Fusr\u002Flocal",[15,5121,5123,5127,5129,5133],{"id":5122,"level":99},"step-5c-linux-php-cli",[20,5124,5126],{"id":5125},"step-5c-ubuntulinux-php-cli","Step 5C: Ubuntu\u002FLinux PHP CLI",[41,5128,882],{},[884,5130],{"language":886,"src":5131,"label":5132},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment\u002Flinux-install-php-cli-05.sh","linux-php.sh",[25,5134,5135,5138,5141],{},[28,5136,5137],{},"This installs command-line PHP",[28,5139,5140],{},"This is only for local terminal checks",[28,5142,5143],{},"The later VM lesson installs Apache, PHP, and MySQL together",[15,5145,5147,5150,5152,5155,5157,5160],{"id":5146,"level":18},"step-6-verify-optional-php",[20,5148,5149],{"id":5146},"Step 6: Verify Optional PHP",[41,5151,882],{},[884,5153],{"language":886,"src":5154},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment\u002Fstep-6-verify-optional-p-01.sh",[41,5156,2754],{},[884,5158],{"language":3665,"src":5159},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment\u002Fexample-output-02.txt",[25,5161,5162,5165,5168],{},[28,5163,5164],{},"Exact version can differ",[28,5166,5167],{},"PHP 8 output means the terminal can find PHP",[28,5169,5170],{},"Windows may need a terminal or VS Code restart after PATH changes",[15,5172,5173,5175],{"id":1372,"level":18},[20,5174,1375],{"id":1372},[25,5176,5177,5180,5183,5186],{},[28,5178,5179],{},"Installing tools inside the repository folder",[28,5181,5182],{},"Opening the parent folder instead of the repo root",[28,5184,5185],{},"Editing a ZIP copy instead of the cloned repo",[28,5187,5188],{},"Installing extensions in the wrong VS Code profile",[15,5190,5191,5193],{"id":437,"level":18},[20,5192,440],{"id":437},[25,5194,5195,5198,5201,5204,5207],{},[28,5196,5197],{},"VS Code opens your course repository root",[28,5199,5200],{},"Course profile is active",[28,5202,5203],{},"PHP Intelephense is installed",[28,5205,5206],{},"GitLens is installed",[28,5208,5209,5210,5212],{},"Optional: ",[266,5211,4599],{}," prints a PHP 8 version",[15,5214,5215,5217],{"id":1455,"level":18},[20,5216,1456],{"id":1455},[104,5218,5219,5237],{"gap":106,"left-width":107,"right-width":107},[109,5220,5221,5223],{"v-slot:left":111},[365,5222,1464],{"id":1463},[25,5224,5225,5228,5231,5234],{},[28,5226,5227],{},"IDE: editor with development tools",[28,5229,5230],{},"Extension: add-on that changes VS Code behavior",[28,5232,5233],{},"Profile: saved VS Code setup",[28,5235,5236],{},"PATH: system setting used to find commands",[109,5238,5239,5241],{"v-slot:right":111},[365,5240,1495],{"id":1452},[25,5242,5243,5250,5257],{},[28,5244,5245],{},[45,5246,5249],{"href":5247,"rel":5248},"https:\u002F\u002Fcode.visualstudio.com\u002Fdocs\u002Fintrovideos\u002Fbasics",[49],"VS Code Getting Started",[28,5251,5252],{},[45,5253,5256],{"href":5254,"rel":5255},"https:\u002F\u002Fcode.visualstudio.com\u002Fdocs\u002Fconfigure\u002Fprofiles",[49],"VS Code Profiles",[28,5258,5259],{},[45,5260,5263],{"href":5261,"rel":5262},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Finstall.php",[49],"PHP Installation",[15,5265,5266,5268],{"id":466,"level":18},[20,5267,469],{"id":466},[25,5269,5270,5273,5276,5279,5290],{},[28,5271,5272],{},"VS Code installed as the course editor",[28,5274,5275],{},"Repository opens from its root folder",[28,5277,5278],{},"Course extensions live in a course profile",[28,5280,5281,5282],{},"Local PHP is optional for this Internet Applications path\n",[25,5283,5284,5287],{},[28,5285,5286],{},"Summer 2026 added information about VM setup in a future lesson to teach clearer Apache\u002FMySQL topics",[28,5288,5289],{},"VM, Apache, Render QA, and Render production remain the real runtime checks",[28,5291,5292],{},"Next: copy the instructor template into the repository",{"title":111,"searchDepth":493,"depth":493,"links":5294},[5295,5296,5297,5298,5299,5300,5301,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314],{"id":4550,"depth":493,"text":4542},{"id":601,"depth":493,"text":604},{"id":4582,"depth":493,"text":4585},{"id":4603,"depth":493,"text":4606},{"id":4628,"depth":493,"text":4631},{"id":4666,"depth":493,"text":4667},{"id":4695,"depth":493,"text":4698,"children":5302},[5303],{"id":4701,"depth":505,"text":4702},{"id":4776,"depth":493,"text":4777},{"id":4853,"depth":493,"text":4854},{"id":4952,"depth":493,"text":4955},{"id":4980,"depth":493,"text":4983},{"id":5045,"depth":493,"text":5048},{"id":5125,"depth":493,"text":5126},{"id":5146,"depth":493,"text":5149},{"id":1372,"depth":493,"text":1375},{"id":437,"depth":493,"text":440},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Set up VS Code, course extensions, and optional local PHP checks.","First-pass timing estimate for VS Code installation, extension profile setup, optional PHP verification, and beginner folder checks.",{},"50","\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment",{"title":4542,"description":5315},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F05-setup-local-development-environment",[5323,5324,5325],"vscode","local-development","php","44:26","0s1N-m3LABc","https:\u002F\u002Fyoutu.be\u002F0s1N-m3LABc","Local Development Environment setup","X5U0DDKjg7X7HrYtDDcsE4QqlBLimZ9weKgnZlc8H2s",{"id":5332,"title":5333,"audience":10,"body":5334,"contentType":509,"course":510,"description":6385,"estimateBasis":6386,"estimatedDiscussionMinutes":3585,"estimatedLiveMinutes":1602,"estimatedTotalMinutes":6387,"extension":516,"meta":6388,"module":518,"navigation":519,"order":6387,"path":6389,"promptAssist":522,"seo":6390,"status":524,"stem":6391,"tags":6392,"videoDuration":6393,"videoId":6394,"videoLink":6395,"videoTitle":6396,"week":518,"__hash__":6397},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository.md","Add Instructor Template To Your Repository",{"type":12,"value":5335,"toc":6357},[5336,5365,5407,5435,5468,5499,5545,5638,5682,5727,5772,5817,5889,5948,6021,6075,6151,6220,6252,6304,6328],[15,5337,5338,5340,5343],{"id":3608,"level":18},[20,5339,3611],{"id":3608},[41,5341,5342],{},"By the end, you should have:",[25,5344,5345,5348,5351,5357,5362],{},[28,5346,5347],{},"Cloned course repository open in the terminal",[28,5349,5350],{},"Starter template copied into the repository root",[28,5352,5353,5354],{},"Baseline commit on ",[266,5355,5356],{},"Module01-Course-Template",[28,5358,5359,5360],{},"Pull request merged into ",[266,5361,1795],{},[28,5363,5364],{},"Clean working tree before moving on",[15,5366,5368,5372],{"id":5367,"level":18},"step-1-open-clone",[20,5369,5371],{"id":5370},"step-1-open-the-cloned-repository","Step 1: Open The Cloned Repository",[104,5373,5374,5382],{"gap":106,"left-width":107,"right-width":107},[109,5375,5376,5378],{"v-slot:left":111},[41,5377,882],{},[884,5379],{"language":886,"src":5380,"label":5381},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-1-open-the-cloned-repository-01.sh","open-cloned-repository.sh",[109,5383,5384,5386,5389],{"v-slot:right":111},[41,5385,2754],{},[884,5387],{"language":2228,"src":5388,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fopen-cloned-repository-output.txt",[25,5390,5391,5396,5401],{},[28,5392,5393,5395],{},[266,5394,692],{},": current working directory",[28,5397,5398,5400],{},[266,5399,3856],{},": current branch and file state",[28,5402,5403,5404,5406],{},"Important check: ",[266,5405,692],{}," ends with your repository folder",[15,5408,5410,5414,5417,5420],{"id":5409,"level":18},"step-2-open-vscode",[20,5411,5413],{"id":5412},"step-2-open-the-repository-root","Step 2: Open The Repository Root",[41,5415,5416],{},"Run from inside the cloned repository folder:",[884,5418],{"language":886,"src":5419},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-2-open-the-reposito-01.sh",[25,5421,5422,5427,5432],{},[28,5423,5424,5426],{},[266,5425,266],{},": opens VS Code from the terminal",[28,5428,5429,5431],{},[266,5430,757],{}," means \"this current folder\"",[28,5433,5434],{},"VS Code should show your repository folder, not the parent folder",[15,5436,5438,5442],{"id":5437,"level":18},"step-3-download-template",[20,5439,5441],{"id":5440},"step-3-download-the-instructor-template","Step 3: Download The Instructor Template",[25,5443,5444,5456,5459,5462,5465],{},[28,5445,5446,5447],{},"Open the instructor template repository",[25,5448,5449],{},[28,5450,5451],{},[45,5452,5455],{"href":5453,"rel":5454},"https:\u002F\u002Fgithub.com\u002FMattToegel\u002FIT202-2026",[49],"IT202-2026",[28,5457,5458],{},"Download the ZIP",[28,5460,5461],{},"Extract the ZIP",[28,5463,5464],{},"Copy scaffold contents into your repository root",[28,5466,5467],{},"See the slide below for the copy rule",[15,5469,5471,5475,5478,5481,5496],{"id":5470,"level":99},"template-copy-rule",[365,5472,5474],{"id":5473},"copy-rule","Copy Rule",[41,5476,5477],{},"Copy the contents of the extracted template folder",[41,5479,5480],{},"Do not copy:",[25,5482,5483,5486,5493],{},[28,5484,5485],{},"The extracted wrapper folder as one extra nested folder",[28,5487,5488,5489,5492],{},"The template repository's hidden ",[266,5490,5491],{},".git"," folder",[28,5494,5495],{},"Old files from a different semester",[41,5497,5498],{},"Repository root should contain the starter folders directly",[15,5500,5502,5506,5509,5512],{"id":5501,"level":18},"step-4-check-structure",[20,5503,5505],{"id":5504},"step-4-check-the-starter-structure","Step 4: Check The Starter Structure",[41,5507,5508],{},"After copying, repository root should look similar to:",[884,5510],{"language":3665,"src":5511},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-4-check-the-starter-02.txt",[25,5513,5514,5519,5528,5542],{},[28,5515,5516,5518],{},[266,5517,824],{}," should be directly inside your repository root",[28,5520,5521,5522,5525,5526],{},"Module folders and ",[266,5523,5524],{},"project"," live inside ",[266,5527,824],{},[28,5529,5530,622,5533,626,5536,5539,5540],{},[266,5531,5532],{},"lib",[266,5534,5535],{},"partials",[266,5537,5538],{},"sql"," stay outside ",[266,5541,824],{},[28,5543,5544],{},"See the slide below for the public\u002Fprivate folder boundary",[15,5546,5548,5552,5635],{"id":5547,"level":99},"public-html-boundary",[365,5549,5551],{"id":5550},"public-and-private-boundary","Public And Private Boundary",[25,5553,5554,5588,5610,5615,5620,5626,5632],{},[28,5555,5556,5558,5559],{},[266,5557,824],{},": web root Apache can serve\n",[25,5560,5561,5571,5576,5582],{},[28,5562,5563,5566,5567,5570],{},[266,5564,5565],{},"m01"," through ",[266,5568,5569],{},"m10",": module practice folders",[28,5572,5573,5575],{},[266,5574,5524],{},": course project folder",[28,5577,5578,5581],{},[266,5579,5580],{},"index.php",": first browser entry point",[28,5583,5584,5587],{},[266,5585,5586],{},"test_db.php",": database connection check",[28,5589,5590,5592,5593],{},[266,5591,5532],{},": reusable PHP helpers\n",[25,5594,5595,5601],{},[28,5596,5597,5600],{},[266,5598,5599],{},".env.sample",": example local config file",[28,5602,5603,2328,5606,5609],{},[266,5604,5605],{},"config.php",[266,5607,5608],{},"db.php",": config and database helpers",[28,5611,5612,5614],{},[266,5613,5535],{},": shared page pieces",[28,5616,5617,5619],{},[266,5618,5538],{},": database setup scripts",[28,5621,5622,5625],{},[266,5623,5624],{},"Dockerfile",": consistent runtime setup",[28,5627,5628,5631],{},[266,5629,5630],{},"structure.md",": starter layout notes",[28,5633,5634],{},"Private folders should not be opened directly in the browser",[41,5636,5637],{},"Later server setup expects this folder boundary",[15,5639,5641,5645],{"id":5640,"level":18},"step-5-check-status",[20,5642,5644],{"id":5643},"step-5-create-the-template-branch","Step 5: Create The Template Branch",[104,5646,5647,5655],{"gap":106,"left-width":107,"right-width":107},[109,5648,5649,5651],{"v-slot:left":111},[41,5650,882],{},[884,5652],{"language":886,"src":5653,"label":5654},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-5-create-template-branch-05.sh","create-template-branch.sh",[109,5656,5657,5660,5663],{"v-slot:right":111},[41,5658,5659],{},"Expected idea:",[884,5661],{"language":3665,"src":5662,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstatus-after-template-copy.txt",[25,5664,5665,5671,5676,5679],{},[28,5666,5667,5670],{},[266,5668,5669],{},"git checkout -b",": create and move to a new branch",[28,5672,5673,5674],{},"Branch name: ",[266,5675,5356],{},[28,5677,5678],{},"New files listed as untracked",[28,5680,5681],{},"No changes means likely wrong folder or copy missed",[15,5683,5685,5689],{"id":5684,"level":18},"step-6-stage",[20,5686,5688],{"id":5687},"step-6-stage-the-baseline-files","Step 6: Stage The Baseline Files",[104,5690,5691,5699],{"gap":106,"left-width":107,"right-width":107},[109,5692,5693,5695],{"v-slot:left":111},[41,5694,882],{},[884,5696],{"language":886,"src":5697,"label":5698},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-6-stage-the-baseline-files-06.sh","stage-baseline.sh",[109,5700,5701,5704,5722,5724],{"v-slot:right":111},[41,5702,5703],{},"What this means:",[25,5705,5706,5712,5717],{},[28,5707,5708,5711],{},[266,5709,5710],{},"git add",": choose files for the next commit",[28,5713,5714,5716],{},[266,5715,757],{}," means current folder and contents",[28,5718,5719,5721],{},[266,5720,3856],{},": verify what is staged before committing",[41,5723,5659],{},[884,5725],{"language":3665,"src":5726,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstatus-after-stage.txt",[15,5728,5730,5734],{"id":5729,"level":18},"step-7-commit",[20,5731,5733],{"id":5732},"step-7-commit-the-baseline","Step 7: Commit The Baseline",[104,5735,5736,5744],{"gap":106,"left-width":107,"right-width":107},[109,5737,5738,5740],{"v-slot:left":111},[41,5739,882],{},[884,5741],{"language":886,"src":5742,"label":5743},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-7-commit-the-baseline-07.sh","commit-baseline.sh",[109,5745,5746,5748,5751],{"v-slot:right":111},[41,5747,5659],{},[884,5749],{"language":3665,"src":5750,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fcommit-baseline-output.txt",[25,5752,5753,5759,5769],{},[28,5754,5755,5758],{},[266,5756,5757],{},"git commit",": save staged changes in local history",[28,5760,5761,5763,5764],{},[266,5762,3954],{},": commit message\n",[25,5765,5766],{},[28,5767,5768],{},"Message is required, even if empty",[28,5770,5771],{},"Baseline commit: starter state before custom work",[15,5773,5775,5779],{"id":5774,"level":18},"step-8-push",[20,5776,5778],{"id":5777},"step-8-push-the-template-branch","Step 8: Push The Template Branch",[104,5780,5781,5789],{"gap":106,"left-width":107,"right-width":107},[109,5782,5783,5785],{"v-slot:left":111},[41,5784,882],{},[884,5786],{"language":886,"src":5787,"label":5788},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-8-push-to-github-08.sh","push-baseline.sh",[109,5790,5791,5793,5796],{"v-slot:right":111},[41,5792,5659],{},[884,5794],{"language":3665,"src":5795,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fpush-baseline-output.txt",[25,5797,5798,5803,5809,5814],{},[28,5799,5800,5802],{},[266,5801,4017],{},": GitHub remote",[28,5804,5805,5808],{},[266,5806,5807],{},"-u",": remembers this branch's GitHub tracking branch",[28,5810,5811,5813],{},[266,5812,5356],{},": branch being sent",[28,5815,5816],{},"Refresh GitHub after the push",[15,5818,5820,5824],{"id":5819,"level":18},"step-9-open-pull-request",[20,5821,5823],{"id":5822},"step-9-open-the-pull-request","Step 9: Open The Pull Request",[104,5825,5826,5869],{"gap":106,"left-width":107,"right-width":107},[109,5827,5828,5830],{"v-slot:left":111},[41,5829,2670],{},[25,5831,5832,5835,5851,5856,5861,5864],{},[28,5833,5834],{},"Open your course repository",[28,5836,170,5837,5840],{},[126,5838,5839],{},"Compare & pull request",[25,5841,5842],{},[28,5843,5844,5845,4643,5848],{},"Or use ",[126,5846,5847],{},"Pull requests",[126,5849,5850],{},"New pull request",[28,5852,5853,5854],{},"Set base branch to ",[266,5855,1795],{},[28,5857,5858,5859],{},"Set compare branch to ",[266,5860,5356],{},[28,5862,5863],{},"Confirm the changed files are the starter template files",[28,5865,170,5866],{},[126,5867,5868],{},"Create pull request",[109,5870,5871,5874,5878],{"v-slot:right":111},[41,5872,5873],{},"Use a short title and description:",[884,5875],{"language":3665,"src":5876,"label":5877},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fpull-request-description.txt","pull-request-description.txt",[25,5879,5880,5883,5886],{},[28,5881,5882],{},"Base receives the changes",[28,5884,5885],{},"Compare contains your branch work",[28,5887,5888],{},"If base and compare are reversed, do not create the pull request",[15,5890,5892,5898],{"id":5891,"level":18},"step-10-merge-sync-main",[20,5893,5895,5896],{"id":5894},"step-10-merge-and-sync-main","Step 10: Merge And Sync ",[266,5897,1795],{},[104,5899,5900,5922],{"gap":106,"left-width":107,"right-width":107},[109,5901,5902,5904,5916,5918],{"v-slot:left":111},[41,5903,2670],{},[25,5905,5906,5911],{},[28,5907,170,5908],{},[126,5909,5910],{},"Merge pull request",[28,5912,170,5913],{},[126,5914,5915],{},"Confirm merge",[41,5917,4311],{},[884,5919],{"language":886,"src":5920,"label":5921},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-10-sync-main-after-pr-10.sh","sync-main-after-pr.sh",[109,5923,5924,5926,5929],{"v-slot:right":111},[41,5925,5659],{},[884,5927],{"language":3665,"src":5928,"label":2614},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fsync-main-after-pr-output.txt",[25,5930,5931,5937,5943],{},[28,5932,5933,5936],{},[266,5934,5935],{},"git checkout main",": return to the main branch",[28,5938,5939,5942],{},[266,5940,5941],{},"git pull origin main",": download the merged template files",[28,5944,5945,5946,4335],{},"Continue only when local ",[266,5947,1795],{},[15,5949,5951,5957],{"id":5950,"level":18},"step-11-create-local-env",[20,5952,5953,5954],{"id":5950},"Step 11: Create Local ",[266,5955,5956],{},".env",[104,5958,5959,5981],{"gap":106,"left-width":107,"right-width":107},[109,5960,5961,5964,5968],{"v-slot:left":111},[41,5962,5963],{},"Run from the repository root:",[884,5965],{"language":886,"src":5966,"label":5967},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-11-create-local-env-11.sh","create-local-env.sh",[25,5969,5970],{},[28,5971,5972,5973,5976,5977],{},"Get ",[266,5974,5975],{},"DB_URL"," from ",[45,5978,5980],{"href":4825,"rel":5979},[49],"courses.ethereallab.app\u002Fdatabase",[109,5982,5983,5986,5991],{"v-slot:right":111},[41,5984,5985],{},"Fill in values similar to:",[884,5987],{"language":5988,"src":5989,"label":5990},"dotenv","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Flocal-env-example.txt","lib\u002F.env",[25,5992,5993,5998,6003,6006,6011,6016],{},[28,5994,5995,5997],{},[266,5996,5956],{}," stores local secrets",[28,5999,1729,6000,6002],{},[266,6001,5956],{}," on your computer only",[28,6004,6005],{},"Do not commit your real connection string",[28,6007,6008,6009],{},"Paste the generated database connection string as ",[266,6010,5975],{},[28,6012,6013,6015],{},[266,6014,5605],{}," loads local or hosted environment variables",[28,6017,6018,6019],{},"Do not paste secrets directly into ",[266,6020,5605],{},[15,6022,6024,6028],{"id":6023,"level":18},"step-12-test-local-db",[20,6025,6027],{"id":6026},"step-12-test-local-database-connection","Step 12: Test Local Database Connection",[104,6029,6030,6038],{"gap":106,"left-width":107,"right-width":107},[109,6031,6032,6034],{"v-slot:left":111},[41,6033,5963],{},[884,6035],{"language":886,"src":6036,"label":6037},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-12-test-local-db-12.sh","run-local-php.sh",[109,6039,6040,6043,6047],{"v-slot:right":111},[41,6041,6042],{},"Then open:",[884,6044],{"language":3665,"src":6045,"label":6046},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Ftest-db-url.txt","browser-url.txt",[25,6048,6049,6055,6061,6069],{},[28,6050,6051,6054],{},[266,6052,6053],{},"php -S",": starts PHP's built-in local server",[28,6056,6057,6060],{},[266,6058,6059],{},"-t public_html",": serves the course web root",[28,6062,6063,6065,6066,6068],{},[266,6064,5586],{},": confirms PHP can read ",[266,6067,5956],{}," and connect to MySQL",[28,6070,6071,6072,6074],{},"Stop the server with ",[266,6073,1427],{}," when finished",[15,6076,6078,6086,6092],{"id":6077,"level":18},"step-13-enable-pdo-mysql",[20,6079,6081,6082,6085],{"id":6080},"step-13-enable-pdo_mysql-if-needed","Step 13: Enable ",[266,6083,6084],{},"pdo_mysql"," If Needed",[41,6087,6088,6089,757],{},"This is usually a Windows PHP ZIP setup issue. macOS and Linux usually install MySQL support through Homebrew or ",[266,6090,6091],{},"apt",[104,6093,6094,6125],{"gap":106,"left-width":107,"right-width":107},[109,6095,6096,6099,6103,6106],{"v-slot:left":111},[41,6097,6098],{},"Find the PHP folder:",[884,6100],{"language":886,"src":6101,"label":6102},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fstep-13-find-php-folder-13.sh","find-php-folder.sh",[41,6104,6105],{},"In that folder:",[25,6107,6108,6114,6120],{},[28,6109,6110,6111],{},"Find ",[266,6112,6113],{},"php.ini-development",[28,6115,6116,6117],{},"Copy it as ",[266,6118,6119],{},"php.ini",[28,6121,3054,6122,6124],{},[266,6123,6119],{}," in your editor",[109,6126,6127,6130,6134,6137,6141],{"v-slot:right":111},[41,6128,6129],{},"Uncomment these lines:",[884,6131],{"language":6132,"src":6133,"label":6119},"ini","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fphp-ini-pdo-mysql-settings.txt",[41,6135,6136],{},"Mac\u002FLinux usually use:",[884,6138],{"language":886,"src":6139,"label":6140},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fmacos-linux-pdo-mysql-commands-14.sh","macos-linux-php-mysql.sh",[25,6142,6143,6148],{},[28,6144,6145,6146],{},"Restart the php dev server after changing ",[266,6147,6119],{},[28,6149,6150],{},"Run Step 12 again after enabling the extension",[15,6152,6154,6156,6159],{"id":6153,"level":18},"quick-check-final",[20,6155,440],{"id":437},[41,6157,6158],{},"Confirm all of these:",[25,6160,6161,6164,6172,6175,6180,6189,6195,6200,6205,6211],{},[28,6162,6163],{},"GitHub shows the starter files",[28,6165,6166,6167,6169,6170],{},"GitHub shows a pull request from ",[266,6168,5356],{}," into ",[266,6171,1795],{},[28,6173,6174],{},"The pull request is merged",[28,6176,4081,6177,6179],{},[266,6178,1795],{}," says the working tree is clean",[28,6181,6182,5566,6185,6188],{},[266,6183,6184],{},"public_html\u002Fm01",[266,6186,6187],{},"public_html\u002Fm10"," exist",[28,6190,6191,6194],{},[266,6192,6193],{},"public_html\u002Fproject"," exists",[28,6196,6197,6199],{},[266,6198,824],{}," is not nested inside another accidental folder",[28,6201,6202,6204],{},[266,6203,5990],{}," exists locally and is not committed with real secrets",[28,6206,6207,6210],{},[266,6208,6209],{},"http:\u002F\u002Flocalhost:3000\u002Ftest_db.php"," confirms the database connection",[28,6212,6213,6214,6216,6217,6219],{},"Windows PHP has ",[266,6215,6084],{}," enabled if ",[266,6218,5586],{}," reports a missing driver",[15,6221,6223,6227,6229,6232,6241],{"id":6222,"level":18},"reset-check",[20,6224,6226],{"id":6225},"if-something-looks-wrong","If Something Looks Wrong",[41,6228,882],{},[884,6230],{"language":886,"src":6231},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository\u002Fif-something-looks-wrong-03.sh",[6233,6234,6235],"blockquote",{},[41,6236,6237,6238,6240],{},"Tip: ",[266,6239,3208],{}," prints the repository root when your current folder is inside a Git repository",[25,6242,6243,6246,6249],{},[28,6244,6245],{},"Output should point to your course repository",[28,6247,6248],{},"If it points somewhere else, move folders before continuing",[28,6250,6251],{},"Avoid cloning inside another cloned repository",[15,6253,6254,6256],{"id":1372,"level":18},[20,6255,1375],{"id":1372},[25,6257,6258,6261,6264,6269,6272,6275,6280,6290,6295,6298],{},[28,6259,6260],{},"Opening the parent folder instead of the repository root",[28,6262,6263],{},"Copying the instructor template folder as a nested folder",[28,6265,6266,6267,5492],{},"Copying the template ",[266,6268,5491],{},[28,6270,6271],{},"Keeping the downloaded ZIP inside the repository",[28,6273,6274],{},"Re-cloning the repository instead of opening the existing clone",[28,6276,6277,6278],{},"Putting module folders outside ",[266,6279,824],{},[28,6281,6282,6283,6285,6286,6289],{},"Renaming ",[266,6284,5565],{}," to ",[266,6287,6288],{},"M1"," or mixing folder casing",[28,6291,6292,6293],{},"Doing template work directly on ",[266,6294,1795],{},[28,6296,6297],{},"Reversing base and compare branches in the pull request",[28,6299,6300,6301,6303],{},"Forgetting to sync local ",[266,6302,1795],{}," after the pull request is merged",[15,6305,6306,6308],{"id":1463,"level":18},[20,6307,1464],{"id":1463},[25,6309,6310,6313,6316,6319,6322,6325],{},[28,6311,6312],{},"Repository root: top folder of the cloned project",[28,6314,6315],{},"Baseline: starter state before custom work begins",[28,6317,6318],{},"Pull request: GitHub review page used to merge branch work",[28,6320,6321],{},"Web root: folder served to the browser",[28,6323,6324],{},"Scaffold: starter folders that organize future work",[28,6326,6327],{},"Staging: choosing files for the next commit",[15,6329,6330,6332,6335],{"id":466,"level":18},[20,6331,469],{"id":466},[41,6333,6334],{},"Before leaving this presentation, confirm the following:",[25,6336,6337,6340,6343,6346,6352],{},[28,6338,6339],{},"You still have one clone for your repository",[28,6341,6342],{},"Your VS Code is able to open directly to your repository",[28,6344,6345],{},"Your repository has the full starter baseline correctly structured",[28,6347,6348,6349,6351],{},"GitHub remote ",[266,6350,1795],{}," has the baseline content",[28,6353,4081,6354,6356],{},[266,6355,1795],{}," was synchronized",{"title":111,"searchDepth":493,"depth":493,"links":6358},[6359,6360,6361,6362,6365,6368,6369,6370,6371,6372,6373,6375,6377,6378,6380,6381,6382,6383,6384],{"id":3608,"depth":493,"text":3611},{"id":5370,"depth":493,"text":5371},{"id":5412,"depth":493,"text":5413},{"id":5440,"depth":493,"text":5441,"children":6363},[6364],{"id":5473,"depth":505,"text":5474},{"id":5504,"depth":493,"text":5505,"children":6366},[6367],{"id":5550,"depth":505,"text":5551},{"id":5643,"depth":493,"text":5644},{"id":5687,"depth":493,"text":5688},{"id":5732,"depth":493,"text":5733},{"id":5777,"depth":493,"text":5778},{"id":5822,"depth":493,"text":5823},{"id":5894,"depth":493,"text":6374},"Step 10: Merge And Sync main",{"id":5950,"depth":493,"text":6376},"Step 11: Create Local .env",{"id":6026,"depth":493,"text":6027},{"id":6080,"depth":493,"text":6379},"Step 13: Enable pdo_mysql If Needed",{"id":437,"depth":493,"text":440},{"id":6225,"depth":493,"text":6226},{"id":1372,"depth":493,"text":1375},{"id":1463,"depth":493,"text":1464},{"id":466,"depth":493,"text":469},"Continue from your cloned course repository, copy in the instructor template, and merge the baseline files through a pull request.","Face-to-face class of about 40 students; starts from an existing clone and includes template copy checks, ZIP extraction, first commit verification, and common folder mistakes.","60",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository",{"title":5333,"description":6385},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F06-add-instructor-template-to-your-repository",[3595,109,1830],"47:11","4n0-QuXO_Aw","https:\u002F\u002Fyoutu.be\u002F4n0-QuXO_Aw","Adding Instructor\u002FCourse Template","iYq9WdND1ODBRrXLU2gX9dNCXvDc-Kvqufsokl_jg3E",{"id":6399,"title":6400,"audience":10,"body":6401,"contentType":509,"course":510,"description":7111,"estimateBasis":7112,"estimatedDiscussionMinutes":3585,"estimatedLiveMinutes":4528,"estimatedTotalMinutes":1603,"extension":516,"meta":7113,"module":518,"navigation":519,"order":3586,"path":7114,"promptAssist":522,"seo":7115,"status":524,"stem":7116,"tags":7117,"videoDuration":7119,"videoId":7120,"videoLink":7121,"videoTitle":7122,"week":518,"__hash__":7123},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches.md","QA And Prod Branches",{"type":12,"value":6402,"toc":7090},[6403,6437,6485,6507,6561,6626,6684,6734,6799,6840,6932,6972,6999,7057],[15,6404,6405,6407,6409],{"id":3608,"level":18},[20,6406,3611],{"id":3608},[41,6408,3614],{},[25,6410,6411,6420,6425,6429,6434],{},[28,6412,6413,6414,2328,6417],{},"Understand the purpose and usage of ",[266,6415,6416],{},"qa",[266,6418,6419],{},"prod",[28,6421,6422,6423],{},"Create and push ",[266,6424,6416],{},[28,6426,6422,6427],{},[266,6428,6419],{},[28,6430,6431,6432],{},"Keep local work pointed at ",[266,6433,6416],{},[28,6435,6436],{},"Confirm GitHub has the expected branches",[15,6438,6440,6443,6478],{"id":6439,"level":18},"branch-roles",[20,6441,6442],{"id":6439},"Branch Roles",[25,6444,6445,6455,6465,6475],{},[28,6446,6447,6449,6450],{},[266,6448,1795],{},": starter baseline and shared source branch\n",[25,6451,6452],{},[28,6453,6454],{},"Most projects stick with this; we'll split ours into development lanes",[28,6456,6457,6459,6460],{},[266,6458,6416],{},": public testing and evidence branch\n",[25,6461,6462],{},[28,6463,6464],{},"Normal branch to return to before new course work",[28,6466,6467,6469,6470],{},[266,6468,6419],{},": stable grading and evaluation branch\n",[25,6471,6472],{},[28,6473,6474],{},"Protected from everyday local edits",[28,6476,6477],{},"Later deployment setup connects Render to these branches",[41,6479,6480,6481,4643,6483],{},"Course flow: feature or homework branch -> ",[266,6482,6416],{},[266,6484,6419],{},[15,6486,6487,6489,6492,6496],{"id":638,"level":18},[20,6488,641],{"id":638},[41,6490,6491],{},"Run inside the course repository:",[884,6493],{"label":6494,"language":886,"src":6495},"before-you-start.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fbefore-you-start.sh",[25,6497,6498,6501,6504],{},[28,6499,6500],{},"Working tree should be clean",[28,6502,6503],{},"Starter baseline already pushed to GitHub",[28,6505,6506],{},"Stop if Git says files are modified or untracked",[15,6508,6510,6516],{"id":6509,"level":18},"step-1-sync-main",[20,6511,6513,6514],{"id":6512},"step-1-start-from-main","Step 1: Start From ",[266,6515,1795],{},[104,6517,6518,6526],{"gap":106,"left-width":107,"right-width":107},[109,6519,6520,6522],{"v-slot:left":111},[41,6521,882],{},[884,6523],{"label":6524,"language":886,"src":6525},"sync-main.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fsync-main.sh",[109,6527,6528,6530,6533],{"v-slot:right":111},[41,6529,2754],{},[884,6531],{"label":2614,"language":3665,"src":6532},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fsync-main-output.txt",[25,6534,6535,6542],{},[28,6536,6537,6539,6540],{},[266,6538,5935],{},": switch to ",[266,6541,1795],{},[28,6543,6544,6546,6547,6549,6550],{},[266,6545,5941],{},": get the latest ",[266,6548,1795],{}," from GitHub\n",[25,6551,6552,6556],{},[28,6553,6554,5802],{},[266,6555,4017],{},[28,6557,6558,6560],{},[266,6559,1795],{},": remote branch being pulled",[15,6562,6564,6570],{"id":6563,"level":18},"step-2-create-qa",[20,6565,6567,6568],{"id":6566},"step-2-create-and-push-qa","Step 2: Create And Push ",[266,6569,6416],{},[104,6571,6572,6580],{"gap":106,"left-width":107,"right-width":107},[109,6573,6574,6576],{"v-slot:left":111},[41,6575,882],{},[884,6577],{"label":6578,"language":886,"src":6579},"create-qa.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fcreate-qa.sh",[109,6581,6582,6584,6587],{"v-slot:right":111},[41,6583,2754],{},[884,6585],{"label":2614,"language":3665,"src":6586},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fcreate-qa-output.txt",[25,6588,6589,6606],{},[28,6590,6591,6594,6595,6597,6598],{},[266,6592,6593],{},"git checkout -b qa",": create ",[266,6596,6416],{}," and switch to it\n",[25,6599,6600],{},[28,6601,6602,6605],{},[266,6603,6604],{},"-b",": creates a new branch of the following name",[28,6607,6608,6611,6612,6614,6615],{},[266,6609,6610],{},"git push -u origin qa",": send ",[266,6613,6416],{}," to GitHub\n",[25,6616,6617],{},[28,6618,6619,6621,6622,6625],{},[266,6620,5807],{},": remember ",[266,6623,6624],{},"origin\u002Fqa"," as the upstream branch",[15,6627,6629,6635],{"id":6628,"level":18},"step-3-create-prod",[20,6630,6632,6633],{"id":6631},"step-3-create-and-push-prod","Step 3: Create And Push ",[266,6634,6419],{},[104,6636,6637,6645],{"gap":106,"left-width":107,"right-width":107},[109,6638,6639,6641],{"v-slot:left":111},[41,6640,882],{},[884,6642],{"label":6643,"language":886,"src":6644},"create-prod.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fcreate-prod.sh",[109,6646,6647,6649,6652],{"v-slot:right":111},[41,6648,2754],{},[884,6650],{"label":2614,"language":3665,"src":6651},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fcreate-prod-output.txt",[25,6653,6654,6662,6667,6679],{},[28,6655,4678,6656,6658,6659,6661],{},[266,6657,6419],{}," from the current ",[266,6660,6416],{}," branch",[28,6663,6664],{},[266,6665,6666],{},"git checkout -b prod",[28,6668,6669,6670,6614,6672],{},"Push ",[266,6671,6419],{},[25,6673,6674],{},[28,6675,6676],{},[266,6677,6678],{},"git push origin prod",[28,6680,6681,6683],{},[266,6682,6419],{}," starts from the same clean baseline",[15,6685,6687,6692],{"id":6686,"level":18},"step-4-return-to-qa",[20,6688,6689,6690],{"id":6686},"Step 4: Return To ",[266,6691,6416],{},[104,6693,6694,6702],{"gap":106,"left-width":107,"right-width":107},[109,6695,6696,6698],{"v-slot:left":111},[41,6697,882],{},[884,6699],{"label":6700,"language":886,"src":6701},"return-to-qa.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Freturn-to-qa.sh",[109,6703,6704,6706,6709],{"v-slot:right":111},[41,6705,2754],{},[884,6707],{"label":2614,"language":3665,"src":6708},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Freturn-to-qa-output.txt",[25,6710,6711,6716,6721],{},[28,6712,6713,6715],{},[266,6714,6416],{}," should have the asterisk",[28,6717,6718,6720],{},[266,6719,6419],{}," should still exist on GitHub",[28,6722,6723,6724,6726],{},"Do not start normal course work from ",[266,6725,6419],{},[25,6727,6728],{},[28,6729,6730,6731,6733],{},"We'll remove local ",[266,6732,6419],{}," to avoid this issue",[15,6735,6737,6743],{"id":6736,"level":18},"step-5-delete-local-prod",[20,6738,6740,6741],{"id":6739},"step-5-remove-local-prod","Step 5: Remove Local ",[266,6742,6419],{},[104,6744,6745,6753],{"gap":106,"left-width":107,"right-width":107},[109,6746,6747,6749],{"v-slot:left":111},[41,6748,882],{},[884,6750],{"label":6751,"language":886,"src":6752},"delete-local-prod.sh","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fdelete-local-prod.sh",[109,6754,6755,6757,6760],{"v-slot:right":111},[41,6756,2754],{},[884,6758],{"label":2614,"language":3665,"src":6759},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches\u002Fdelete-local-prod-output.txt",[25,6761,6762,6784],{},[28,6763,6764,6767,6768,6770],{},[266,6765,6766],{},"git branch -d prod",": delete local ",[266,6769,6419],{},[25,6771,6772,6778],{},[28,6773,6774,6777],{},[266,6775,6776],{},"-d",": delete only if Git considers it safe",[28,6779,6780,6783],{},[266,6781,6782],{},"-D",": can be used as a forced delete",[28,6785,6786,6789,6790],{},[266,6787,6788],{},"git branch -r",": list remote branches\n",[25,6791,6792],{},[28,6793,6794,6795,6798],{},"Confirms ",[266,6796,6797],{},"origin\u002Fprod"," still exists",[15,6800,6802,6805,6808,6811,6825,6828],{"id":6801,"level":18},"github-check",[20,6803,6804],{"id":6801},"GitHub Check",[41,6806,6807],{},"Open the branch dropdown on GitHub",[41,6809,6810],{},"You should see:",[25,6812,6813,6817,6821],{},[28,6814,6815],{},[266,6816,1795],{},[28,6818,6819],{},[266,6820,6416],{},[28,6822,6823],{},[266,6824,6419],{},[41,6826,6827],{},"Branch roles:",[25,6829,6830,6835],{},[28,6831,6832,6834],{},[266,6833,6416],{},": testing and evidence",[28,6836,6837,6839],{},[266,6838,6419],{},": stable grading target",[15,6841,6843,6847],{"id":6842,"level":18},"normal-workflow",[20,6844,6846],{"id":6845},"normal-workflow-after-setup","Normal Workflow After Setup",[163,6848,6849,6866,6874,6885,6890,6904,6907,6914,6926],{},[28,6850,6851,6852,6854],{},"Return to ",[266,6853,6416],{},[25,6855,6856,6861],{},[28,6857,6858],{},[266,6859,6860],{},"git checkout qa",[28,6862,6863],{},[266,6864,6865],{},"git pull origin qa",[28,6867,6868,6869],{},"Create a feature or homework branch\n",[25,6870,6871],{},[28,6872,6873],{},"Branch name matches the task",[28,6875,6876,6877],{},"Commit the work on that branch\n",[25,6878,6879],{},[28,6880,6881,6882,6884],{},"Check ",[266,6883,3856],{}," before each Git command",[28,6886,6887,6888],{},"Push the branch and open a pull request into ",[266,6889,6416],{},[28,6891,6892,6893,6895,6896],{},"Merge into ",[266,6894,6416],{}," after review\n",[25,6897,6898],{},[28,6899,6900,6901,6903],{},"QA deployment will update from ",[266,6902,6416],{}," after Render setup",[28,6905,6906],{},"Test the QA version",[28,6908,6909,6910,6169,6912],{},"Open a pull request from ",[266,6911,6416],{},[266,6913,6419],{},[28,6915,6892,6916,6918,6919],{},[266,6917,6419],{}," when stable\n",[25,6920,6921],{},[28,6922,6923,6924,6903],{},"Production deployment will use ",[266,6925,6419],{},[28,6927,6928,6929,6931],{},"Return locally to ",[266,6930,6416],{}," and pull before the next task",[15,6933,6934,6936],{"id":1372,"level":18},[20,6935,1375],{"id":1372},[25,6937,6938,6943,6948,6956,6964,6967],{},[28,6939,6940,6941],{},"Working directly on ",[266,6942,6419],{},[28,6944,6945,6946],{},"Forgetting to return to ",[266,6947,6416],{},[28,6949,6950,6951,6953,6954],{},"Pushing ",[266,6952,6416],{}," but not ",[266,6955,6419],{},[28,6957,6958,6959,6961,6962],{},"Deleting remote ",[266,6960,6419],{}," instead of local ",[266,6963,6419],{},[28,6965,6966],{},"Assuming GitHub has the branch without checking",[28,6968,6969,6970,4335],{},"Starting new work before ",[266,6971,3856],{},[15,6973,6974,6976,6979],{"id":437,"level":18},[20,6975,440],{"id":437},[41,6977,6978],{},"Answer before moving on:",[25,6980,6981,6984,6987,6990,6996],{},[28,6982,6983],{},"Which branch should QA deployment watch?",[28,6985,6986],{},"Which branch should production grading use?",[28,6988,6989],{},"Which branch should you return to before new work?",[28,6991,6992,6993,6995],{},"Why remove local ",[266,6994,6419],{}," after pushing it?",[28,6997,6998],{},"What future setup connects Render to these branches?",[15,7000,7001,7003],{"id":1452,"level":18},[20,7002,1456],{"id":1455},[104,7004,7005,7030],{"gap":106,"left-width":107,"right-width":107},[109,7006,7007,7009],{"v-slot:left":111},[365,7008,1464],{"id":1463},[25,7010,7011,7014,7017,7022,7027],{},[28,7012,7013],{},"Branch: named line of Git history",[28,7015,7016],{},"Upstream: remote branch Git remembers for push\u002Fpull",[28,7018,7019,7021],{},[266,7020,6416],{},": public testing branch",[28,7023,7024,7026],{},[266,7025,6419],{},": stable grading branch",[28,7028,7029],{},"Remote-only branch: exists on GitHub, not locally",[109,7031,7032,7034],{"v-slot:right":111},[365,7033,1495],{"id":1452},[25,7035,7036,7043,7050],{},[28,7037,4430,7038],{},[45,7039,7042],{"href":7040,"rel":7041},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fget-started\u002Fusing-git\u002Fabout-git#about-branches",[49],"About branches",[28,7044,4430,7045],{},[45,7046,7049],{"href":7047,"rel":7048},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fpull-requests\u002Fcollaborating-with-pull-requests\u002Fproposing-changes-to-your-work-with-pull-requests\u002Fabout-pull-requests",[49],"About pull requests",[28,7051,4415,7052],{},[45,7053,7056],{"href":7054,"rel":7055},"https:\u002F\u002Fgit-scm.com\u002Fbook\u002Fen\u002Fv2\u002FGit-Branching-Branches-in-a-Nutshell",[49],"Git Branching",[15,7058,7059,7061,7063],{"id":466,"level":18},[20,7060,469],{"id":466},[41,7062,1525],{},[25,7064,7065,7074,7078,7082,7087],{},[28,7066,7067,7068,622,7070,626,7072],{},"Explain ",[266,7069,1795],{},[266,7071,6416],{},[266,7073,6419],{},[28,7075,6422,7076],{},[266,7077,6416],{},[28,7079,6422,7080],{},[266,7081,6419],{},[28,7083,7084,7085],{},"Keep local work branched from ",[266,7086,6416],{},[28,7088,7089],{},"Verify remote branches on GitHub",{"title":111,"searchDepth":493,"depth":493,"links":7091},[7092,7093,7094,7095,7097,7099,7101,7103,7105,7106,7107,7108,7109,7110],{"id":3608,"depth":493,"text":3611},{"id":6439,"depth":493,"text":6442},{"id":638,"depth":493,"text":641},{"id":6512,"depth":493,"text":7096},"Step 1: Start From main",{"id":6566,"depth":493,"text":7098},"Step 2: Create And Push qa",{"id":6631,"depth":493,"text":7100},"Step 3: Create And Push prod",{"id":6686,"depth":493,"text":7102},"Step 4: Return To qa",{"id":6739,"depth":493,"text":7104},"Step 5: Remove Local prod",{"id":6801,"depth":493,"text":6804},{"id":6845,"depth":493,"text":6846},{"id":1372,"depth":493,"text":1375},{"id":437,"depth":493,"text":440},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Create the Internet Applications QA and production branches, then connect each branch to its role in the course workflow.","Face-to-face class of about 40 students; includes branch roles, command practice, GitHub branch checks, and QA\u002Fprod workflow questions.",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches",{"title":6400,"description":7111},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F07-qa-prod-branches",[1830,4533,6416,7118],"production","10:35","32XilHQwRiY","https:\u002F\u002Fyoutu.be\u002F32XilHQwRiY","Create QA and Prod Branches","GZx1sXtI0BMbyb6Gbpj7aoBvczhhR-FV7YpFE4j4UCs",{"id":7125,"title":7126,"audience":10,"body":7127,"contentType":509,"course":510,"description":7934,"estimateBasis":7935,"estimatedDiscussionMinutes":3585,"estimatedLiveMinutes":1603,"estimatedTotalMinutes":3586,"extension":516,"meta":7936,"module":518,"navigation":519,"order":7937,"path":7938,"promptAssist":522,"seo":7939,"status":524,"stem":7940,"tags":7941,"videoDuration":7944,"videoId":7945,"videoLink":7946,"videoTitle":7947,"week":518,"__hash__":7948},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F08-render-setup.md","Render Setup",{"type":12,"value":7128,"toc":7913},[7129,7156,7179,7208,7276,7337,7372,7408,7445,7495,7541,7576,7622,7659,7687,7719,7766,7799,7867],[15,7130,7132,7135],{"id":7131,"level":18},"render-setup-title",[20,7133,7126],{"id":7134},"render-setup",[25,7136,7137,7140,7145,7150,7153],{},[28,7138,7139],{},"Connect GitHub repo to Render",[28,7141,7142,7143],{},"Create a QA service from ",[266,7144,6416],{},[28,7146,7147,7148],{},"Create a production service from ",[266,7149,6419],{},[28,7151,7152],{},"Add the course database connection string",[28,7154,7155],{},"Verify live URLs and deploy logs",[15,7157,7158,7160,7162],{"id":2512,"level":18},[20,7159,2515],{"id":2512},[41,7161,3614],{},[25,7163,7164,7167,7170,7173,7176],{},[28,7165,7166],{},"Explain what Render does in the course workflow",[28,7168,7169],{},"Create separate QA and production services",[28,7171,7172],{},"Connect each service to the correct branch",[28,7174,7175],{},"Read Render logs when a deploy fails",[28,7177,7178],{},"Identify which deployed URL to submit or test",[15,7180,7182,7185,7202],{"id":7181,"level":18},"what-render-does",[20,7183,7184],{"id":7181},"What Render Does",[25,7186,7187,7190,7193,7196,7199],{},[28,7188,7189],{},"Hosts your PHP app from GitHub",[28,7191,7192],{},"Watches a selected branch",[28,7194,7195],{},"Rebuilds when that branch changes",[28,7197,7198],{},"Stores secrets as environment variables",[28,7200,7201],{},"Gives each service a public URL",[41,7203,7204,7205],{},"Course loop: ",[266,7206,7207],{},"local work -> GitHub branch -> Render URL",[15,7209,7211,7213],{"id":7210,"level":18},"free-tier-and-before-start",[20,7212,641],{"id":638},[104,7214,7215,7244],{"gap":106,"left-width":107,"right-width":107},[109,7216,7217,7221],{"v-slot:left":111},[365,7218,7220],{"id":7219},"free-tier","Free Tier",[25,7222,7223,7233,7241],{},[28,7224,2680,7225,7228],{},[266,7226,7227],{},"Free",[25,7229,7230],{},[28,7231,7232],{},"Render may default to a paid plan",[28,7234,7235,7236],{},"Free services can sleep",[25,7237,7238],{},[28,7239,7240],{},"First visit after sleep may be slow",[28,7242,7243],{},"Avoid extra services unless instructed",[109,7245,7246,7250],{"v-slot:right":111},[365,7247,7249],{"id":7248},"repo-ready","Repo Ready",[25,7251,7252,7255,7260,7269],{},[28,7253,7254],{},"Starter files committed and pushed",[28,7256,7257,7259],{},[266,7258,5624],{}," in repo root",[28,7261,7262,622,7264,626,7266,7268],{},[266,7263,824],{},[266,7265,5532],{},[266,7267,5535],{}," present",[28,7270,7271,2328,7273,7275],{},[266,7272,6416],{},[266,7274,6419],{}," branches exist on GitHub",[15,7277,7279,7282],{"id":7278,"level":18},"target-architecture",[20,7280,7281],{"id":7278},"Target Architecture",[104,7283,7284,7312],{"gap":106,"left-width":107,"right-width":107},[109,7285,7286,7290],{"v-slot:left":111},[365,7287,7289],{"id":7288},"qa-service","QA Service",[25,7291,7292,7298,7303,7306],{},[28,7293,7294,7295],{},"Name: ",[266,7296,7297],{},"\u003Cucid>-it202-\u003Csection>-qa",[28,7299,7300,7301],{},"Watches ",[266,7302,6416],{},[28,7304,7305],{},"Used for testing and evidence",[28,7307,7308,7309],{},"URL ends with ",[266,7310,7311],{},"-qa.onrender.com",[109,7313,7314,7318],{"v-slot:right":111},[365,7315,7317],{"id":7316},"production-service","Production Service",[25,7319,7320,7325,7329,7332],{},[28,7321,7294,7322],{},[266,7323,7324],{},"\u003Cucid>-it202-\u003Csection>-prod",[28,7326,7300,7327],{},[266,7328,6419],{},[28,7330,7331],{},"Stable version after QA checks",[28,7333,7308,7334],{},[266,7335,7336],{},"-prod.onrender.com",[15,7338,7340,7344],{"id":7339,"level":18},"step-1-sign-up",[20,7341,7343],{"id":7342},"step-1-sign-up-with-github","Step 1: Sign Up With GitHub",[104,7345,7346,7364],{"gap":106,"left-width":2215,"right-width":2214},[109,7347,7348],{"v-slot:left":111},[25,7349,7350,7355,7358,7361],{},[28,7351,1684,7352],{},[266,7353,7354],{},"render.com",[28,7356,7357],{},"Choose GitHub sign-in",[28,7359,7360],{},"Authorize Render when prompted",[28,7362,7363],{},"Land on the Render dashboard",[109,7365,7366],{"v-slot:right":111},[41,7367,7368],{},[144,7369],{"alt":7370,"src":7371,"variant":148},"Render GitHub sign-in screen","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-01-github-signin.png",[15,7373,7375,7378],{"id":7374,"level":18},"step-2-new-web-service",[20,7376,7377],{"id":7374},"Step 2: New Web Service",[104,7379,7380,7400],{"gap":106,"left-width":2215,"right-width":2214},[109,7381,7382],{"v-slot:left":111},[25,7383,7384,7389,7394,7397],{},[28,7385,170,7386],{},[266,7387,7388],{},"New +",[28,7390,2680,7391],{},[266,7392,7393],{},"Web Service",[28,7395,7396],{},"Do not choose a database service here",[28,7398,7399],{},"This creates the hosted PHP app",[109,7401,7402],{"v-slot:right":111},[41,7403,7404],{},[144,7405],{"alt":7406,"src":7407,"variant":148},"Render New menu with Web Service option","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-04-new-menu.png",[15,7409,7411,7415],{"id":7410,"level":18},"step-3-connect-repo",[20,7412,7414],{"id":7413},"step-3-connect-repository","Step 3: Connect Repository",[104,7416,7417,7437],{"gap":106,"left-width":1710,"right-width":2255},[109,7418,7419],{"v-slot:left":111},[25,7420,7421,7424,7427,7434],{},[28,7422,7423],{},"Select your student course repository",[28,7425,7426],{},"Authorize repository access if Render asks",[28,7428,7429,7430,7433],{},"Ensure it's the proper repository (format: ",[266,7431,7432],{},"ucid-course-section-semYear",")",[28,7435,7436],{},"Continue to service settings",[109,7438,7439],{"v-slot:right":111},[41,7440,7441],{},[144,7442],{"alt":7443,"src":7444,"variant":148},"Render repository selection screen","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-07-select-repo.png",[15,7446,7448,7452],{"id":7447,"level":18},"step-4-configure-qa",[20,7449,7451],{"id":7450},"step-4-configure-qa-service","Step 4: Configure QA Service",[104,7453,7454,7487],{"gap":106,"left-width":2215,"right-width":2214},[109,7455,7456,7459],{"v-slot:left":111},[41,7457,7458],{},"Use these settings:",[25,7460,7461,7465,7470,7476,7481,7484],{},[28,7462,7294,7463],{},[266,7464,7297],{},[28,7466,7467,7468],{},"Branch: ",[266,7469,6416],{},[28,7471,7472,7473],{},"Runtime: ",[266,7474,7475],{},"Docker",[28,7477,7478,7479],{},"Instance type: ",[266,7480,7227],{},[28,7482,7483],{},"Root directory: blank",[28,7485,7486],{},"Build\u002Fstart commands: blank",[109,7488,7489],{"v-slot:right":111},[41,7490,7491],{},[144,7492],{"alt":7493,"src":7494,"variant":148},"Render QA service configuration","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-08-qa-config-basic.png",[15,7496,7498,7502],{"id":7497,"level":18},"step-5-env-vars",[20,7499,7501],{"id":7500},"step-5-add-environment-variables","Step 5: Add Environment Variables",[104,7503,7504,7533],{"gap":106,"left-width":2665,"right-width":4857},[109,7505,7506],{"v-slot:left":111},[25,7507,7508,7521,7527,7530],{},[28,7509,7510,7511,7513],{},"Add ",[266,7512,5975],{},[25,7514,7515],{},[28,7516,7517,7518],{},"Get it from ",[45,7519,5980],{"href":4825,"rel":7520},[49],[28,7522,7523,7524,7526],{},"Do not use \"add from ",[266,7525,5956],{},"\"",[28,7528,7529],{},"Add later API keys only when a later lesson requires them",[28,7531,7532],{},"Repeat required env vars on both QA and production",[109,7534,7535],{"v-slot:right":111},[41,7536,7537],{},[144,7538],{"alt":7539,"src":7540,"variant":148},"Render environment variables section","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-09-env-vars.png",[15,7542,7544,7547],{"id":7543,"level":18},"step-6-deploy-qa",[20,7545,7546],{"id":7543},"Step 6: Deploy QA",[104,7548,7549,7568],{"gap":106,"left-width":1710,"right-width":2255},[109,7550,7551],{"v-slot:left":111},[25,7552,7553,7556,7559,7562,7565],{},[28,7554,7555],{},"Create the QA service",[28,7557,7558],{},"Watch the first deploy log",[28,7560,7561],{},"Wait for a success state",[28,7563,7564],{},"Open the QA URL",[28,7566,7567],{},"Confirm the starter page loads",[109,7569,7570],{"v-slot:right":111},[41,7571,7572],{},[144,7573],{"alt":7574,"src":7575,"variant":148},"Successful Render QA deployment","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-10-qa-deployed.png",[15,7577,7579,7583],{"id":7578,"level":18},"step-7-create-prod",[20,7580,7582],{"id":7581},"step-7-create-production-service","Step 7: Create Production Service",[104,7584,7585,7614],{"gap":106,"left-width":2215,"right-width":2214},[109,7586,7587,7590],{"v-slot:left":111},[41,7588,7589],{},"Create a second web service:",[25,7591,7592,7595,7599,7603,7607,7611],{},[28,7593,7594],{},"Same repository",[28,7596,7294,7597],{},[266,7598,7324],{},[28,7600,7467,7601],{},[266,7602,6419],{},[28,7604,7472,7605],{},[266,7606,7475],{},[28,7608,7478,7609],{},[266,7610,7227],{},[28,7612,7613],{},"Same required env vars",[109,7615,7616],{"v-slot:right":111},[41,7617,7618],{},[144,7619],{"alt":7620,"src":7621,"variant":148},"Render production service configuration","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-11-prod-config.png",[15,7623,7624,7627],{"id":6842,"level":18},[20,7625,7626],{"id":6842},"Normal Workflow",[163,7628,7629,7632,7635,7640,7643,7646,7649,7656],{},[28,7630,7631],{},"Work locally on a feature or homework branch",[28,7633,7634],{},"Commit and push that branch to GitHub",[28,7636,7637,7638],{},"Open a pull request into ",[266,7639,6416],{},[28,7641,7642],{},"Merge after review",[28,7644,7645],{},"Render updates the QA URL",[28,7647,7648],{},"Test the QA URL",[28,7650,6909,7651,6169,7653,7655],{},[266,7652,6416],{},[266,7654,6419],{}," after evidence gathering",[28,7657,7658],{},"Render updates the production URL",[15,7660,7662,7665],{"id":7661,"level":18},"urls-and-cold-starts",[20,7663,7664],{"id":7661},"URLs And Cold Starts",[25,7666,7667,7670,7673,7676,7684],{},[28,7668,7669],{},"QA URL shows the test deployment",[28,7671,7672],{},"Production URL shows the stable deployment",[28,7674,7675],{},"Homework evidence usually starts with QA",[28,7677,7678,7679],{},"Free services may sleep after inactivity\n",[25,7680,7681],{},[28,7682,7683],{},"First visit after sleep may take extra time (2 - 5 minutes)",[28,7685,7686],{},"Do not submit before Render finishes deploying",[15,7688,7690,7693],{"id":7689,"level":18},"logs-and-status",[20,7691,7692],{"id":7689},"Logs And Status",[104,7694,7695,7711],{"gap":106,"left-width":1710,"right-width":2255},[109,7696,7697],{"v-slot:left":111},[25,7698,7699,7702,7705,7708],{},[28,7700,7701],{},"Logs show build and startup output",[28,7703,7704],{},"Dashboard status shows deploy progress",[28,7706,7707],{},"Failed deploys usually show the first useful clue",[28,7709,7710],{},"Read the first clear error before changing settings",[109,7712,7713],{"v-slot:right":111},[41,7714,7715],{},[144,7716],{"alt":7717,"src":7718,"variant":148},"Render deploy logs","\u002Fimages\u002Finternet-applications\u002Frender-setup\u002Frender-12-logs.png",[15,7720,7722,7725],{"id":7721,"level":18},"troubleshooting",[20,7723,7724],{"id":7721},"Troubleshooting",[25,7726,7727,7737,7745,7755],{},[28,7728,7729,7730],{},"Build fails\n",[25,7731,7732],{},[28,7733,6881,7734,7736],{},[266,7735,5624],{},", root directory, runtime, and instance type",[28,7738,7739,7740],{},"App deploys but page fails\n",[25,7741,7742],{},[28,7743,7744],{},"Check logs for PHP errors",[28,7746,7747,7748],{},"Database connection fails\n",[25,7749,7750],{},[28,7751,6881,7752,7754],{},[266,7753,5975],{}," spelling and copied value",[28,7756,7757,7758],{},"Wrong version appears\n",[25,7759,7760,7763],{},[28,7761,7762],{},"Confirm the service watches the expected branch",[28,7764,7765],{},"Clear browser cache or test in a private window",[15,7767,7768,7770],{"id":1372,"level":18},[20,7769,1375],{"id":1372},[25,7771,7772,7782,7785,7790,7793,7796],{},[28,7773,7774,7775,7777,7778,1201,7780],{},"Choosing ",[266,7776,1795],{}," instead of ",[266,7779,6416],{},[266,7781,6419],{},[28,7783,7784],{},"Creating one service for both environments",[28,7786,7787,7788],{},"Forgetting ",[266,7789,5975],{},[28,7791,7792],{},"Using a paid instance type by accident",[28,7794,7795],{},"Checking GitHub but not the Render URL",[28,7797,7798],{},"Changing code locally but forgetting to push and merge",[15,7800,7801,7803],{"id":1455,"level":18},[20,7802,1456],{"id":1455},[104,7804,7805,7833],{"gap":106,"left-width":107,"right-width":107},[109,7806,7807,7809,7815,7821,7827],{"v-slot:left":111},[365,7808,1464],{"id":1463},[41,7810,7811,7814],{},[126,7812,7813],{},"Service"," - one deployed app on Render",[41,7816,7817,7820],{},[126,7818,7819],{},"Watched branch"," - Git branch Render deploys from",[41,7822,7823,7826],{},[126,7824,7825],{},"Environment variable"," - setting stored outside code",[41,7828,7829,7832],{},[126,7830,7831],{},"Deploy log"," - output from Render's build\u002Fstart process",[109,7834,7835,7837],{"v-slot:right":111},[365,7836,1495],{"id":1452},[25,7838,7839,7846,7853,7860],{},[28,7840,7841],{},[45,7842,7845],{"href":7843,"rel":7844},"https:\u002F\u002Frender.com\u002Fdocs\u002Fweb-services",[49],"Render Docs: Web Services",[28,7847,7848],{},[45,7849,7852],{"href":7850,"rel":7851},"https:\u002F\u002Frender.com\u002Fdocs\u002Fdeploys",[49],"Render Docs: Deploys",[28,7854,7855],{},[45,7856,7859],{"href":7857,"rel":7858},"https:\u002F\u002Frender.com\u002Fdocs\u002Fconfigure-environment-variables",[49],"Render Docs: Environment Variables",[28,7861,7862],{},[45,7863,7866],{"href":7864,"rel":7865},"https:\u002F\u002Frender.com\u002Fdocs\u002Ffree",[49],"Render Docs: Free Instance Types",[15,7868,7869,7871,7874],{"id":466,"level":18},[20,7870,469],{"id":466},[41,7872,7873],{},"Before leaving this presentation, confirm you:",[25,7875,7876,7879,7882,7889,7892,7895],{},[28,7877,7878],{},"Created QA and production Render services",[28,7880,7881],{},"Matched each service to the correct branch",[28,7883,7884,7885,5976,7887],{},"Added ",[266,7886,5975],{},[266,7888,5980],{},[28,7890,7891],{},"Opened each deployed URL",[28,7893,7894],{},"Read logs instead of assuming it worked",[28,7896,7897,7898],{},"Understand the local -> GitHub -> Render loop\n",[25,7899,7900,7903,7908],{},[28,7901,7902],{},"Majority of your work will be done locally and tested locally",[28,7904,7905,7907],{},[266,7906,6416],{}," is just for gathering evidence for submissions",[28,7909,7910,7912],{},[266,7911,6419],{}," is what will be verified during grading",{"title":111,"searchDepth":493,"depth":493,"links":7914},[7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933],{"id":7134,"depth":493,"text":7126},{"id":2512,"depth":493,"text":2515},{"id":7181,"depth":493,"text":7184},{"id":638,"depth":493,"text":641},{"id":7278,"depth":493,"text":7281},{"id":7342,"depth":493,"text":7343},{"id":7374,"depth":493,"text":7377},{"id":7413,"depth":493,"text":7414},{"id":7450,"depth":493,"text":7451},{"id":7500,"depth":493,"text":7501},{"id":7543,"depth":493,"text":7546},{"id":7581,"depth":493,"text":7582},{"id":6842,"depth":493,"text":7626},{"id":7661,"depth":493,"text":7664},{"id":7689,"depth":493,"text":7692},{"id":7721,"depth":493,"text":7724},{"id":1372,"depth":493,"text":1375},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Connect the course repository to Render, create QA and production services, and verify the deploy loop from GitHub to a live URL.","Face-to-face class of about 40 students; includes Render account setup, QA\u002Fprod service creation, environment variables, deploy verification, and first troubleshooting pass.",{},"80","\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F08-render-setup",{"title":7126,"description":7934},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F08-render-setup",[7942,7943,6416,7118],"render","deployment","21:42","esZd5RIpqCQ","https:\u002F\u002Fyoutu.be\u002FesZd5RIpqCQ","Render.com Setup (QA and Prod)","_1jV7vdhppggQ8TAOecx_1jFvjG90__8eGGlaXbnc28",{"id":7950,"title":7951,"audience":10,"body":7952,"contentType":509,"course":510,"description":10626,"estimateBasis":10627,"estimatedDiscussionMinutes":10628,"estimatedLiveMinutes":10629,"estimatedTotalMinutes":10630,"extension":516,"meta":10631,"module":518,"navigation":519,"order":4526,"path":10632,"promptAssist":522,"seo":10633,"status":524,"stem":10634,"tags":10635,"videoDuration":10640,"videoId":10641,"videoLink":10642,"videoTitle":10643,"week":518,"__hash__":10644},"content\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox.md","Local Ubuntu Web Server With VirtualBox",{"type":12,"value":7953,"toc":10558},[7954,7983,8028,8064,8133,8165,8192,8224,8250,8279,8308,8335,8366,8394,8430,8495,8530,8576,8619,8663,8710,8773,8809,8844,8881,8914,8951,8984,9014,9044,9074,9104,9134,9168,9200,9232,9264,9313,9315,9358,9384,9425,9477,9556,9607,9638,9668,9698,9748,9773,9823,9871,9929,9987,10028,10058,10092,10126,10160,10211,10263,10282,10310,10358,10430,10530],[15,7955,7957,7960],{"id":7956,"level":18},"virtualbox-title",[20,7958,7951],{"id":7959},"local-ubuntu-web-server-with-virtualbox",[25,7961,7962,7965,7968,7971,7974,7980],{},[28,7963,7964],{},"Primary course path for the local Ubuntu VM",[28,7966,7967],{},"Create an Ubuntu Server VM in VirtualBox",[28,7969,7970],{},"Connect from your host terminal with SSH",[28,7972,7973],{},"Share the course repo into Ubuntu",[28,7975,7976,7977,7979],{},"Serve ",[266,7978,824],{}," through Apache and PHP",[28,7981,7982],{},"Create a local MySQL database for testing",[15,7984,7986,7989,7992,8003,8006],{"id":7985,"level":18},"main-goal",[20,7987,7988],{"id":7985},"Main Goal",[41,7990,7991],{},"Your host computer and Ubuntu VM have different jobs:",[25,7993,7994,7997,8000],{},[28,7995,7996],{},"Host computer: edit files with VS Code and open the browser",[28,7998,7999],{},"Ubuntu VM: run Apache, PHP, MySQL, and server commands",[28,8001,8002],{},"Shared folder: lets both use the same course repo files",[41,8004,8005],{},"Target result:",[25,8007,8008,8014,8019,8022,8025],{},[28,8009,8010,8011],{},"Host browser opens ",[266,8012,8013],{},"http:\u002F\u002Flocalhost:3000",[28,8015,8016,8017],{},"Apache serves the repo's ",[266,8018,824],{},[28,8020,8021],{},"PHP executes inside Ubuntu",[28,8023,8024],{},"Local MySQL has a database and user named after your UCID",[28,8026,8027],{},"Edits made on the host appear after browser refresh",[15,8029,8031,8034,8037,8056,8059],{"id":8030,"level":18},"virtualbox-caveat",[20,8032,8033],{"id":8030},"VirtualBox Caveat",[41,8035,8036],{},"VirtualBox is the primary local VM path for this course:",[25,8038,8039,8042,8045,8053],{},[28,8040,8041],{},"Works well on modern Windows, Linux, and Intel Mac hosts",[28,8043,8044],{},"Apple Silicon Mac requires an ARM64 Ubuntu Server ISO",[28,8046,8047,8048],{},"Windows on Arm support is experimental in VirtualBox\n",[25,8049,8050],{},[28,8051,8052],{},"Avoid unless your instructor confirms it for your machine",[28,8054,8055],{},"Arm hosts cannot run x86\u002FAMD64 guest images",[41,8057,8058],{},"VMware is the fallback path if VirtualBox is not a good fit for your machine",[1927,8060,8061],{"type":3202},[41,8062,8063],{},"Most students do not need BIOS changes. If VirtualBox cannot start the VM or does not offer a 64-bit Ubuntu option, check that Intel VT-x, AMD-V, or SVM is enabled in BIOS\u002FUEFI. On Windows, Hyper-V-related features can also interfere on some systems.",[15,8065,8066,8068],{"id":638,"level":18},[20,8067,641],{"id":638},[25,8069,8070,8088,8106,8109,8112,8115,8130],{},[28,8071,8072,8073],{},"VirtualBox downloaded\n",[25,8074,8075,8082,8085],{},[28,8076,8077],{},[45,8078,8081],{"href":8079,"rel":8080},"https:\u002F\u002Fwww.virtualbox.org\u002Fwiki\u002FDownloads",[49],"VirtualBox downloads",[28,8083,8084],{},"Windows\u002FLinux\u002FIntel Mac: use the standard host installer",[28,8086,8087],{},"Apple Silicon Mac: use the macOS Arm64 host installer",[28,8089,8090,8091],{},"Ubuntu Server ISO downloaded\n",[25,8092,8093,8100,8103],{},[28,8094,8095],{},[45,8096,8099],{"href":8097,"rel":8098},"https:\u002F\u002Fubuntu.com\u002Fdownload\u002Fserver#how-to-install-tab-lts",[49],"Ubuntu Server installer",[28,8101,8102],{},"Apple Silicon Mac: use the ARM64 server ISO",[28,8104,8105],{},"Windows, Linux, and Intel Mac: use the AMD64 server ISO",[28,8107,8108],{},"Internet Applications course repo cloned on host computer",[28,8110,8111],{},"Git\u002FGitHub setup already working",[28,8113,8114],{},"Administrator access on your computer",[28,8116,8117,8118,8121,8122],{},"At least ",[266,8119,8120],{},"10 GB"," free disk space for the VM\n",[25,8123,8124],{},[28,8125,8126,8129],{},[266,8127,8128],{},"20-25 GB"," is safer if your computer has room",[28,8131,8132],{},"Stable internet for package installs",[15,8134,8136,8139],{"id":8135,"level":18},"setup-parts",[20,8137,8138],{"id":8135},"Setup Parts",[25,8140,8141,8144,8147,8150,8156,8159,8162],{},[28,8142,8143],{},"VM: Ubuntu Server running inside VirtualBox",[28,8145,8146],{},"NAT adapter: gives the VM internet access",[28,8148,8149],{},"Port forwarding: lets the host reach SSH and Apache",[28,8151,8152,8153],{},"SSH: lets the host terminal control Ubuntu through ",[266,8154,8155],{},"localhost",[28,8157,8158],{},"Shared folder: exposes the host repo inside Ubuntu",[28,8160,8161],{},"Apache\u002FPHP: serves and executes the web app",[28,8163,8164],{},"MySQL: local database server for local testing",[15,8166,8168,8172],{"id":8167,"level":18},"install-virtualbox-windows",[20,8169,8171],{"id":8170},"install-virtualbox-on-windows","Install VirtualBox On Windows",[25,8173,8174,8177,8180,8183,8186,8189],{},[28,8175,8176],{},"Download VirtualBox for Windows hosts",[28,8178,8179],{},"Run the installer as an administrator if prompted",[28,8181,8182],{},"Keep the default install path and features",[28,8184,8185],{},"Accept the network reset warning",[28,8187,8188],{},"Open VirtualBox after installation",[28,8190,8191],{},"See the slides below for the Windows installer screens",[15,8193,8195,8198],{"id":8194,"level":99},"windows-installer-start",[20,8196,8197],{"id":8194},"Windows Installer: Start",[104,8199,8200,8208],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8201,8202],{"v-slot:left":111},[41,8203,8204],{},[144,8205],{"alt":8206,"src":8207,"variant":148},"VirtualBox Windows installer start screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step1.png",[109,8209,8210],{"v-slot:right":111},[25,8211,8212,8218,8221],{},[28,8213,8214,8215],{},"Launch the downloaded ",[266,8216,8217],{},".exe",[28,8219,8220],{},"Approve the Windows security prompt if shown",[28,8222,8223],{},"Start the setup wizard",[15,8225,8227,8230],{"id":8226,"level":99},"windows-installer-features",[20,8228,8229],{"id":8226},"Windows Installer: Features",[104,8231,8232,8240],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8233,8234],{"v-slot:left":111},[41,8235,8236],{},[144,8237],{"alt":8238,"src":8239,"variant":148},"VirtualBox Windows installer feature selection screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step2.png",[109,8241,8242],{"v-slot:right":111},[25,8243,8244,8247],{},[28,8245,8246],{},"Keep the default install location",[28,8248,8249],{},"Keep the default features selected",[15,8251,8253,8256],{"id":8252,"level":99},"windows-installer-network-warning",[20,8254,8255],{"id":8252},"Windows Installer: Network Warning",[104,8257,8258,8266],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8259,8260],{"v-slot:left":111},[41,8261,8262],{},[144,8263],{"alt":8264,"src":8265,"variant":148},"VirtualBox Windows installer network warning","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step3.png",[109,8267,8268],{"v-slot:right":111},[25,8269,8270,8273,8276],{},[28,8271,8272],{},"VirtualBox may reset network adapters briefly",[28,8274,8275],{},"This is expected during install",[28,8277,8278],{},"Save web work before continuing if needed",[15,8280,8282,8285],{"id":8281,"level":99},"windows-installer-ready",[20,8283,8284],{"id":8281},"Windows Installer: Ready",[104,8286,8287,8295],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8288,8289],{"v-slot:left":111},[41,8290,8291],{},[144,8292],{"alt":8293,"src":8294,"variant":148},"VirtualBox Windows installer ready screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step4.png",[109,8296,8297],{"v-slot:right":111},[25,8298,8299,8302,8305],{},[28,8300,8301],{},"Start the installation",[28,8303,8304],{},"Keep the default choices",[28,8306,8307],{},"Wait for the installer to request permissions if needed",[15,8309,8311,8315],{"id":8310,"level":99},"windows-installer-progress",[20,8312,8314],{"id":8313},"windows-installer-start-options","Windows Installer: Start Options",[104,8316,8317,8325],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8318,8319],{"v-slot:left":111},[41,8320,8321],{},[144,8322],{"alt":8323,"src":8324,"variant":148},"VirtualBox Windows installer progress screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step5.png",[109,8326,8327],{"v-slot:right":111},[25,8328,8329,8332],{},[28,8330,8331],{},"No need to create a Start Menu item or desktop shortcut unless desired",[28,8333,8334],{},"Third option is likely optional too since we'll be using the VirtualBox Manager",[15,8336,8338,8341],{"id":8337,"level":99},"windows-installer-permission",[20,8339,8340],{"id":8337},"Windows Installer: Permission",[104,8342,8343,8351],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8344,8345],{"v-slot:left":111},[41,8346,8347],{},[144,8348],{"alt":8349,"src":8350,"variant":148},"VirtualBox Windows installer permission prompt","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step6.png",[109,8352,8353],{"v-slot:right":111},[25,8354,8355,8358],{},[28,8356,8357],{},"Proceed with install",[28,8359,8360,8361],{},"Approve VirtualBox driver prompts\n",[25,8362,8363],{},[28,8364,8365],{},"These let VirtualBox create virtual hardware",[15,8367,8369,8372],{"id":8368,"level":99},"windows-installer-complete",[20,8370,8371],{"id":8368},"Windows Installer: Complete",[104,8373,8374,8382],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8375,8376],{"v-slot:left":111},[41,8377,8378],{},[144,8379],{"alt":8380,"src":8381,"variant":148},"VirtualBox Windows installer completion screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_step7.png",[109,8383,8384],{"v-slot:right":111},[25,8385,8386,8388,8391],{},[28,8387,2075],{},[28,8389,8390],{},"Open VirtualBox",[28,8392,8393],{},"Continue to VM creation",[15,8395,8397,8401],{"id":8396,"level":18},"install-virtualbox-macos",[20,8398,8400],{"id":8399},"install-virtualbox-on-macos","Install VirtualBox On macOS",[104,8402,8403,8422],{"gap":106,"left-width":2665,"right-width":4857,"stack":1711},[109,8404,8405],{"v-slot:left":111},[25,8406,8407,8410,8413,8416,8419],{},[28,8408,8409],{},"Install the VirtualBox host package for your Mac CPU type",[28,8411,8412],{},"Intel Mac: standard macOS host installer",[28,8414,8415],{},"Apple Silicon Mac: Arm64 host installer and Arm64 Ubuntu Server ISO",[28,8417,8418],{},"Approve macOS security prompts if needed",[28,8420,8421],{},"If VirtualBox is not a good fit, use the VMware fallback lesson",[109,8423,8424],{"v-slot:right":111},[41,8425,8426],{},[144,8427],{"alt":8428,"src":8429,"variant":148},"Summary of macOS VirtualBox setup notes","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvm_summary_mac.png",[15,8431,8433,8437,8440],{"id":8432,"level":18},"step-1-create-vm",[20,8434,8436],{"id":8435},"step-1-create-the-vm","Step 1: Create The VM",[41,8438,8439],{},"Create a lightweight Ubuntu Server VM:",[25,8441,8442,8445,8453,8468,8480,8486,8489,8492],{},[28,8443,8444],{},"Type: Linux",[28,8446,8447,8448],{},"Version: Ubuntu 64-bit or Ubuntu Arm64\n",[25,8449,8450],{},[28,8451,8452],{},"Match the version to the ISO you downloaded",[28,8454,8455,8456,8459,8460],{},"Memory: ",[266,8457,8458],{},"1 GB"," course target\n",[25,8461,8462],{},[28,8463,1150,8464,8467],{},[266,8465,8466],{},"1.5-2 GB"," if the installer is too slow or refuses to continue (you shouldn't need to do this)",[28,8469,8470,8471,8473,8474],{},"Disk: ",[266,8472,8120],{}," course minimum\n",[25,8475,8476],{},[28,8477,8478,8129],{},[266,8479,8128],{},[28,8481,8482,8483,8485],{},"CPU: ",[266,8484,518],{}," core is enough for this course VM",[28,8487,8488],{},"Enable OpenSSH during install if prompted",[28,8490,8491],{},"Username: use your UCID",[28,8493,8494],{},"See the slides below for VM settings and Ubuntu install screens",[15,8496,8498,8501],{"id":8497,"level":99},"vm-setup-name-and-iso",[20,8499,8500],{"id":8497},"VM Setup: Name And ISO",[104,8502,8503,8511],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8504,8505],{"v-slot:left":111},[41,8506,8507],{},[144,8508],{"alt":8509,"src":8510,"variant":148},"VirtualBox VM name and ISO setup","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_setup_1.png",[109,8512,8513],{"v-slot:right":111},[25,8514,8515,8518,8524,8527],{},[28,8516,8517],{},"Start a new virtual machine",[28,8519,8520,8521],{},"Name it clearly, such as ",[266,8522,8523],{},"it202-vm",[28,8525,8526],{},"Choose the Ubuntu Server ISO file next",[28,8528,8529],{},"OS fields may look wrong until the ISO is selected",[15,8531,8533,8536],{"id":8532,"level":99},"vm-setup-confirm-ubuntu-iso",[20,8534,8535],{"id":8532},"VM Setup: Confirm Ubuntu ISO",[104,8537,8538,8546],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8539,8540],{"v-slot:left":111},[41,8541,8542],{},[144,8543],{"alt":8544,"src":8545,"variant":148},"VirtualBox VM name and Ubuntu ISO selected","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_setup_2.png",[109,8547,8548],{"v-slot:right":111},[25,8549,8550,8556,8562,8565],{},[28,8551,8552,8553],{},"Confirm OS is ",[266,8554,8555],{},"Linux",[28,8557,8558,8559],{},"Confirm distribution is ",[266,8560,8561],{},"Ubuntu",[28,8563,8564],{},"Confirm version matches your ISO",[28,8566,1729,8567,8570,8571],{},[266,8568,8569],{},"Unattended Installation"," off\n",[25,8572,8573],{},[28,8574,8575],{},"The Ubuntu installer screens are easier to teach manually",[15,8577,8579,8582],{"id":8578,"level":99},"vm-setup-memory-and-cpu",[20,8580,8581],{"id":8578},"VM Setup: Memory And CPU",[104,8583,8584,8592],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8585,8586],{"v-slot:left":111},[41,8587,8588],{},[144,8589],{"alt":8590,"src":8591,"variant":148},"VirtualBox VM memory and CPU settings","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_setup_4.png",[109,8593,8594],{"v-slot:right":111},[25,8595,8596,8609,8613,8616],{},[28,8597,8455,8598,8459,8601],{},[266,8599,8600],{},"1024 MB",[25,8602,8603,8606],{},[28,8604,8605],{},"The goal is to match free-tier cloud services",[28,8607,8608],{},"Demonstrates that small apps can run with limited resources",[28,8610,8482,8611],{},[266,8612,518],{},[28,8614,8615],{},"Keep EFI off unless your machine requires it",[28,8617,8618],{},"This VM is for Apache, PHP, MySQL, and local development\u002Ftesting",[15,8620,8622,8625],{"id":8621,"level":99},"vm-setup-virtual-disk",[20,8623,8624],{"id":8621},"VM Setup: Virtual Disk",[104,8626,8627,8635],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8628,8629],{"v-slot:left":111},[41,8630,8631],{},[144,8632],{"alt":8633,"src":8634,"variant":148},"VirtualBox virtual hard disk settings","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_setup_5.png",[109,8636,8637],{"v-slot:right":111},[25,8638,8639,8645,8648,8660],{},[28,8640,8641,8642],{},"Disk type: ",[266,8643,8644],{},"VDI",[28,8646,8647],{},"Storage: dynamically allocated",[28,8649,8650,8651,8653],{},"Minimum: ",[266,8652,8120],{},[25,8654,8655],{},[28,8656,8657,8659],{},[266,8658,8128],{}," is safer if you have room",[28,8661,8662],{},"Dynamic disk uses space as needed, not all at once",[15,8664,8666,8669],{"id":8665,"level":99},"vm-setup-start-with-gui",[20,8667,8668],{"id":8665},"VM Setup: Start With GUI",[104,8670,8671,8679],{"gap":106,"left-width":1709,"right-width":1710,"stack":1711},[109,8672,8673],{"v-slot:left":111},[41,8674,8675],{},[144,8676],{"alt":8677,"src":8678,"variant":148},"VirtualBox VM selected with the Start button visible","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_setup_6.png",[109,8680,8681],{"v-slot:right":111},[25,8682,8683,8686,8696,8699],{},[28,8684,8685],{},"Select the newly created VM",[28,8687,170,8688,8691],{},[266,8689,8690],{},"Start",[25,8692,8693],{},[28,8694,8695],{},"Choose the normal GUI start for the first boot",[28,8697,8698],{},"Complete the Ubuntu installer in the VM window",[28,8700,8701,8702],{},"After install and SSH setup, future starts can be headless\n",[25,8703,8704],{},[28,8705,8706,8707,8709],{},"You will connect with ",[266,8708,3594],{}," when you need the VM",[15,8711,8713,8717,8720],{"id":8712,"level":18},"ubuntu-installer",[20,8714,8716],{"id":8715},"step-2-ubuntu-installer","Step 2: Ubuntu Installer",[41,8718,8719],{},"Use the Ubuntu Server installer after the VM starts:",[25,8721,8722,8725,8728,8731,8734,8737,8770],{},[28,8723,8724],{},"Choose the default course options unless noted",[28,8726,8727],{},"Continue without updating the installer if instructed",[28,8729,8730],{},"Use your UCID for the Ubuntu username",[28,8732,8733],{},"Install OpenSSH server during setup",[28,8735,8736],{},"Skip optional server snaps",[28,8738,8739,8740],{},"Keyboard navigation:\n",[25,8741,8742,8749,8759,8765],{},[28,8743,8744,8748],{},[8745,8746,8747],"kbd",{},"Tab"," moves between fields and buttons",[28,8750,8751,8754,8755,8758],{},[8745,8752,8753],{},"Up"," \u002F ",[8745,8756,8757],{},"Down"," moves through lists",[28,8760,8761,8764],{},[8745,8762,8763],{},"Space"," toggles checkboxes",[28,8766,8767,8769],{},[8745,8768,1234],{}," confirms the selected option",[28,8771,8772],{},"See the slides below for the installer screens",[15,8774,8776,8780],{"id":8775,"level":99},"ubuntu-installer-boot-menu",[20,8777,8779],{"id":8778},"step-21-boot-menu","Step 2.1: Boot Menu",[104,8781,8784,8793],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},"1.75fr","0.65fr",[109,8785,8786],{"v-slot:left":111},[41,8787,8788],{},[144,8789],{"alt":8790,"src":8791,"variant":8792},"Ubuntu Server boot menu in VirtualBox","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_1.png","slide-screenshot",[109,8794,8795],{"v-slot:right":111},[25,8796,8797,8802,8806],{},[28,8798,2680,8799],{},[266,8800,8801],{},"Try or Install Ubuntu Server",[28,8803,1266,8804],{},[8745,8805,1234],{},[28,8807,8808],{},"This starts the Ubuntu Server installer",[15,8810,8812,8816],{"id":8811,"level":99},"ubuntu-installer-language",[20,8813,8815],{"id":8814},"step-22-language","Step 2.2: Language",[104,8817,8818,8826],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8819,8820],{"v-slot:left":111},[41,8821,8822],{},[144,8823],{"alt":8824,"src":8825,"variant":8792},"Ubuntu Server installer language screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_2.0.png",[109,8827,8828],{"v-slot:right":111},[25,8829,8830,8833,8839],{},[28,8831,8832],{},"Choose your preferred language",[28,8834,8835,8838],{},[266,8836,8837],{},"English"," is the expected course screenshot path",[28,8840,1266,8841,8843],{},[8745,8842,1234],{}," to continue",[15,8845,8847,8851],{"id":8846,"level":99},"ubuntu-installer-update",[20,8848,8850],{"id":8849},"step-23-update-prompt","Step 2.3: Update Prompt",[104,8852,8853,8861],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8854,8855],{"v-slot:left":111},[41,8856,8857],{},[144,8858],{"alt":8859,"src":8860,"variant":8792},"Ubuntu Server installer update prompt","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_2.5.png",[109,8862,8863],{"v-slot:right":111},[25,8864,8865,8875,8878],{},[28,8866,2680,8867,8870],{},[266,8868,8869],{},"Continue without updating",[25,8871,8872],{},[28,8873,8874],{},"If I forget to update the image, it's the second option",[28,8876,8877],{},"Keeps the install path consistent",[28,8879,8880],{},"Package updates happen after Ubuntu is installed",[15,8882,8884,8888],{"id":8883,"level":99},"ubuntu-installer-keyboard",[20,8885,8887],{"id":8886},"step-24-keyboard","Step 2.4: Keyboard",[104,8889,8890,8898],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8891,8892],{"v-slot:left":111},[41,8893,8894],{},[144,8895],{"alt":8896,"src":8897,"variant":8792},"Ubuntu Server installer keyboard screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_3.png",[109,8899,8900],{"v-slot:right":111},[25,8901,8902,8905,8911],{},[28,8903,8904],{},"Keep the detected keyboard layout if it matches",[28,8906,8907,8908],{},"Common setting: ",[266,8909,8910],{},"English (US)",[28,8912,8913],{},"Use Identify keyboard only if typing is wrong",[15,8915,8917,8921],{"id":8916,"level":99},"ubuntu-installer-install-type",[20,8918,8920],{"id":8919},"step-25-install-type","Step 2.5: Install Type",[104,8922,8923,8931],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8924,8925],{"v-slot:left":111},[41,8926,8927],{},[144,8928],{"alt":8929,"src":8930,"variant":8792},"Ubuntu Server installer installation type screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_4.png",[109,8932,8933],{"v-slot:right":111},[25,8934,8935,8945,8948],{},[28,8936,8937,8938,8941,8942],{},"Select ",[266,8939,8940],{},"Ubuntu Server (minimized)","; don't choose full ",[266,8943,8944],{},"Ubuntu Server",[28,8946,8947],{},"Keep third-party drivers unchecked",[28,8949,8950],{},"Minimized keeps the VM lighter and aids future lessons",[15,8952,8954,8958],{"id":8953,"level":99},"ubuntu-installer-network",[20,8955,8957],{"id":8956},"step-26-network","Step 2.6: Network",[104,8959,8960,8968],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8961,8962],{"v-slot:left":111},[41,8963,8964],{},[144,8965],{"alt":8966,"src":8967,"variant":8792},"Ubuntu Server installer network configuration screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_5.png",[109,8969,8970],{"v-slot:right":111},[25,8971,8972,8975,8981],{},[28,8973,8974],{},"DHCP address is expected",[28,8976,8977,8980],{},[266,8978,8979],{},"10.0.2.15"," is normal for VirtualBox NAT",[28,8982,8983],{},"Leave the network settings alone",[15,8985,8987,8991],{"id":8986,"level":99},"ubuntu-installer-proxy",[20,8988,8990],{"id":8989},"step-27-proxy","Step 2.7: Proxy",[104,8992,8993,9001],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,8994,8995],{"v-slot:left":111},[41,8996,8997],{},[144,8998],{"alt":8999,"src":9000,"variant":8792},"Ubuntu Server installer proxy screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_6.png",[109,9002,9003],{"v-slot:right":111},[25,9004,9005,9008,9011],{},[28,9006,9007],{},"Leave proxy blank",[28,9009,9010],{},"Only fill this in if your network requires a proxy",[28,9012,9013],{},"Most student home networks do not need one",[15,9015,9017,9021],{"id":9016,"level":99},"ubuntu-installer-mirror",[20,9018,9020],{"id":9019},"step-28-mirror","Step 2.8: Mirror",[104,9022,9023,9031],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9024,9025],{"v-slot:left":111},[41,9026,9027],{},[144,9028],{"alt":9029,"src":9030,"variant":8792},"Ubuntu Server installer archive mirror screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_7.png",[109,9032,9033],{"v-slot:right":111},[25,9034,9035,9038,9041],{},[28,9036,9037],{},"Keep the default Ubuntu archive mirror",[28,9039,9040],{},"Wait for the mirror check to finish",[28,9042,9043],{},"Continue when the installer allows it",[15,9045,9047,9051],{"id":9046,"level":99},"ubuntu-installer-storage-guided",[20,9048,9050],{"id":9049},"step-29-guided-storage","Step 2.9: Guided Storage",[104,9052,9053,9061],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9054,9055],{"v-slot:left":111},[41,9056,9057],{},[144,9058],{"alt":9059,"src":9060,"variant":8792},"Ubuntu Server installer guided storage screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_8.png",[109,9062,9063],{"v-slot:right":111},[25,9064,9065,9068,9071],{},[28,9066,9067],{},"Use the entire virtual disk",[28,9069,9070],{},"LVM is optional, not needed for this course VM",[28,9072,9073],{},"Leave encryption off",[15,9075,9077,9081],{"id":9076,"level":99},"ubuntu-installer-storage-summary",[20,9078,9080],{"id":9079},"step-210-storage-summary","Step 2.10: Storage Summary",[104,9082,9083,9091],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9084,9085],{"v-slot:left":111},[41,9086,9087],{},[144,9088],{"alt":9089,"src":9090,"variant":8792},"Ubuntu Server installer storage summary screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_9.png",[109,9092,9093],{"v-slot:right":111},[25,9094,9095,9098,9101],{},[28,9096,9097],{},"Confirm the virtual disk is selected",[28,9099,9100],{},"This only affects the VM disk file",[28,9102,9103],{},"Continue when the layout looks correct",[15,9105,9107,9111],{"id":9106,"level":99},"ubuntu-installer-confirm-storage",[20,9108,9110],{"id":9109},"step-211-confirm-storage","Step 2.11: Confirm Storage",[104,9112,9113,9121],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9114,9115],{"v-slot:left":111},[41,9116,9117],{},[144,9118],{"alt":9119,"src":9120,"variant":8792},"Ubuntu Server installer destructive action confirmation","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_10.png",[109,9122,9123],{"v-slot:right":111},[25,9124,9125,9128,9131],{},[28,9126,9127],{},"Confirm the virtual disk format",[28,9129,9130],{},"This does not erase your host computer files",[28,9132,9133],{},"It formats the VM's virtual disk",[15,9135,9137,9141],{"id":9136,"level":99},"ubuntu-installer-profile",[20,9138,9140],{"id":9139},"step-212-profile","Step 2.12: Profile",[104,9142,9143,9151],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9144,9145],{"v-slot:left":111},[41,9146,9147],{},[144,9148],{"alt":9149,"src":9150,"variant":8792},"Ubuntu Server installer profile configuration screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_11.png",[109,9152,9153],{"v-slot:right":111},[25,9154,9155,9158,9163,9165],{},[28,9156,9157],{},"Your name: your UCID or name is fine",[28,9159,9160,9161],{},"Server name: ",[266,9162,8523],{},[28,9164,4811],{},[28,9166,9167],{},"Choose a password you can type reliably (it can be simple since it's only for local work)",[15,9169,9171,9175],{"id":9170,"level":99},"ubuntu-installer-pro",[20,9172,9174],{"id":9173},"step-213-ubuntu-pro","Step 2.13: Ubuntu Pro",[104,9176,9177,9185],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9178,9179],{"v-slot:left":111},[41,9180,9181],{},[144,9182],{"alt":9183,"src":9184,"variant":8792},"Ubuntu Server installer Ubuntu Pro screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_12.png",[109,9186,9187],{"v-slot:right":111},[25,9188,9189,9194,9197],{},[28,9190,2680,9191],{},[266,9192,9193],{},"Skip for now",[28,9195,9196],{},"Ubuntu Pro is not needed for the course VM",[28,9198,9199],{},"You can continue without an Ubuntu account",[15,9201,9203,9207],{"id":9202,"level":99},"ubuntu-installer-ssh",[20,9204,9206],{"id":9205},"step-214-ssh","Step 2.14: SSH",[104,9208,9209,9217],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9210,9211],{"v-slot:left":111},[41,9212,9213],{},[144,9214],{"alt":9215,"src":9216,"variant":8792},"Ubuntu Server installer SSH configuration screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_13.png",[109,9218,9219],{"v-slot:right":111},[25,9220,9221,9226,9229],{},[28,9222,6881,9223],{},[266,9224,9225],{},"Install OpenSSH server",[28,9227,9228],{},"Password authentication is fine for this local VM",[28,9230,9231],{},"No need to import SSH keys for this course setup",[15,9233,9235,9239],{"id":9234,"level":99},"ubuntu-installer-snaps",[20,9236,9238],{"id":9237},"step-215-featured-snaps","Step 2.15: Featured Snaps",[104,9240,9241,9249],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9242,9243],{"v-slot:left":111},[41,9244,9245],{},[144,9246],{"alt":9247,"src":9248,"variant":8792},"Ubuntu Server installer featured server snaps screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_14.png",[109,9250,9251],{"v-slot:right":111},[25,9252,9253,9256,9261],{},[28,9254,9255],{},"Leave all featured snaps unchecked",[28,9257,9258,9259],{},"Apache, PHP, and MySQL are installed later with ",[266,9260,6091],{},[28,9262,9263],{},"Continue without selecting extra packages",[15,9265,9267,9271],{"id":9266,"level":99},"ubuntu-installer-installing",[20,9268,9270],{"id":9269},"step-216-installing","Step 2.16: Installing",[104,9272,9273,9281],{"gap":516,"left-width":8782,"right-width":8783,"stack":1711},[109,9274,9275],{"v-slot:left":111},[41,9276,9277],{},[144,9278],{"alt":9279,"src":9280,"variant":8792},"Ubuntu Server installer installing system screen","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_vm_15.png",[109,9282,9283,9308],{"v-slot:right":111},[25,9284,9285,9288,9291,9299,9305],{},[28,9286,9287],{},"Installation can take a while",[28,9289,9290],{},"High CPU during install is normal",[28,9292,9293,9294,9296,9297],{},"If install struggles at ",[266,9295,8458],{},", recreate the VM with ",[266,9298,8466],{},[28,9300,9301,9302,9304],{},"Keep the course target at ",[266,9303,8458],{}," after setup if possible",[28,9306,9307],{},"Reboot once complete",[1927,9309,9310],{"type":3202},[41,9311,9312],{},"These target resources stay close to common cloud free-tier VMs",[41,9314,1935],{},[15,9316,9318,9322,9325],{"id":9317,"level":18},"step-2-networking",[20,9319,9321],{"id":9320},"virtualbox-configure-networking","VirtualBox: Configure Networking",[41,9323,9324],{},"Use one NAT adapter with port forwarding:",[25,9326,9327,9333,9342,9350,9355],{},[28,9328,9329,9330],{},"VM internet: ",[266,9331,9332],{},"NAT",[28,9334,9335,9336,9339,9340],{},"Host SSH: host ",[266,9337,9338],{},"22"," -> guest ",[266,9341,9338],{},[28,9343,9344,9345,9339,9348],{},"Host browser: host ",[266,9346,9347],{},"3000",[266,9349,7937],{},[28,9351,1150,9352,9354],{},[266,9353,8155],{}," from the host computer",[28,9356,9357],{},"See the slides below for adapter and port-forwarding screens",[15,9359,9361,9365,9378],{"id":9360,"level":99},"adapter-settings-screen",[20,9362,9364],{"id":9363},"adapter-settings","Adapter Settings",[25,9366,9367,9370,9375],{},[28,9368,9369],{},"Adapter 1 enabled",[28,9371,9372,9373],{},"Attached to ",[266,9374,9332],{},[28,9376,9377],{},"No second adapter needed for the baseline path",[41,9379,9380],{},[144,9381],{"alt":9382,"src":9383,"variant":8792},"VirtualBox Adapter 1 configured as NAT","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_adapter_1.png",[15,9385,9387,9391,9419],{"id":9386,"level":99},"port-forwarding-screen",[20,9388,9390],{"id":9389},"port-forwarding","Port Forwarding",[25,9392,9393,9401,9408],{},[28,9394,9395,9396,9398,9399],{},"SSH: host ",[266,9397,9338],{}," to guest ",[266,9400,9338],{},[28,9402,9403,9404,9398,9406],{},"Apache HTTP: host ",[266,9405,9347],{},[266,9407,7937],{},[28,9409,9410,9411,9413,9414,9398,9417],{},"If host ",[266,9412,9338],{}," is already busy, use host ",[266,9415,9416],{},"2222",[266,9418,9338],{},[41,9420,9421],{},[144,9422],{"alt":9423,"src":9424,"variant":8792},"VirtualBox NAT port forwarding rules","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_adapter_1_ports.png",[15,9426,9428,9432,9435,9438,9441,9444],{"id":9427,"level":18},"step-3-connect-ssh",[20,9429,9431],{"id":9430},"step-3-connect-with-ssh","Step 3: Connect With SSH",[41,9433,9434],{},"Run from your host terminal:",[884,9436],{"language":886,"src":9437},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-3-connect-with-ssh-01.sh",[41,9439,9440],{},"First connection prompt:",[884,9442],{"language":3665,"src":9443},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-3-connect-with-ssh-02.txt",[25,9445,9446,9453,9462,9465,9468],{},[28,9447,9448,9449,9452],{},"Replace ",[266,9450,9451],{},"your_ucid"," with your UCID",[28,9454,9455,9456,9458,9459,9461],{},"Type ",[266,9457,3129],{}," once for this course VM on ",[266,9460,8155],{}," (if prompted like the example above)",[28,9463,9464],{},"Enter your Ubuntu password",[28,9466,9467],{},"After login, commands run inside Ubuntu",[28,9469,9470,1201,9473,9476],{},[266,9471,9472],{},"exit",[266,9474,9475],{},"logout"," disconnects from the VM",[15,9478,9480,9484,9487],{"id":9479,"level":18},"step-4-confirm-network",[20,9481,9483],{"id":9482},"step-4-confirm-vm-network","Step 4: Confirm VM Network",[41,9485,9486],{},"Run inside Ubuntu through SSH:",[104,9488,9489,9531],{"gap":106,"left-width":2255,"right-width":107,"stack":1711},[109,9490,9491,9494,9497],{"v-slot:left":111},[41,9492,9493],{},"Network check:",[884,9495],{"language":886,"src":9496},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-4-confirm-vm-networ-03.sh",[25,9498,9499,9505,9511,9517,9523],{},[28,9500,9501,9504],{},[266,9502,9503],{},"ping",": confirms basic network access",[28,9506,9507,9510],{},[266,9508,9509],{},"-c 4",": stop after four replies",[28,9512,9513,9516],{},[266,9514,9515],{},"apt update",": refreshes package indexes",[28,9518,9519,9522],{},[266,9520,9521],{},"apt upgrade",": applies available package updates",[28,9524,2172,9525,9527,9528],{},[266,9526,9503],{}," is not found, run ",[266,9529,9530],{},"sudo apt install iputils-ping",[109,9532,9533,9536,9539],{"v-slot:right":111},[41,9534,9535],{},"Port-forwarding check:",[884,9537],{"language":886,"src":9538},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fslide-id-summary-level-2-04.sh",[25,9540,9541,9546,9549,9553],{},[28,9542,9543,9544],{},"The VM may show ",[266,9545,8979],{},[28,9547,9548],{},"That is normal for VirtualBox NAT",[28,9550,1150,9551,9354],{},[266,9552,8155],{},[28,9554,9555],{},"Port forwarding routes host traffic into the VM",[15,9557,9559,9563],{"id":9558,"level":18},"step-5-shared-folder",[20,9560,9562],{"id":9561},"step-5-enable-shared-folder","Step 5: Enable Shared Folder",[104,9564,9565,9599],{"gap":106,"left-width":1710,"right-width":2255,"stack":1711},[109,9566,9567,9570],{"v-slot:left":111},[41,9568,9569],{},"In VirtualBox:",[25,9571,9572,9575,9578,9581,9584,9587,9590,9593,9596],{},[28,9573,9574],{},"Open VM settings",[28,9576,9577],{},"Choose Shared Folders",[28,9579,9580],{},"Folder Path: your cloned course repository folder",[28,9582,9583],{},"Folder Name: a simple repo name with no spaces",[28,9585,9586],{},"Mount Point: leave blank",[28,9588,9589],{},"Read-only: off",[28,9591,9592],{},"Auto-mount: on",[28,9594,9595],{},"Make Machine-permanent: on",[28,9597,9598],{},"Make Global: off",[109,9600,9601],{"v-slot:right":111},[41,9602,9603],{},[144,9604],{"alt":9605,"src":9606,"variant":148},"VirtualBox shared folder settings with the course repo selected","\u002Fimages\u002Finternet-applications\u002Fvirtualbox\u002Fvb_shared_folder.png",[15,9608,9610,9614,9617,9620],{"id":9609,"level":18},"step-6-guest-additions",[20,9611,9613],{"id":9612},"step-6-install-shared-folder-support","Step 6: Install Shared Folder Support",[41,9615,9616],{},"Run inside Ubuntu:",[884,9618],{"language":886,"src":9619},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-6-install-shared-fo-05.sh",[25,9621,9622,9629,9635],{},[28,9623,2362,9624,2328,9626,9628],{},[266,9625,9515],{},[266,9627,9521],{}," first only if you skipped the Step 4 updates",[28,9630,9631,9634],{},[266,9632,9633],{},"virtualbox-guest-utils",": VirtualBox shared-folder support",[28,9636,9637],{},"Reboot after the group step on the next slide",[15,9639,9641,9645,9648,9651],{"id":9640,"level":99},"step-6b-confirm-vboxsf",[20,9642,9644],{"id":9643},"step-61-check-the-shared-folder","Step 6.1: Check The Shared Folder",[41,9646,9647],{},"Reconnect with SSH, then run inside Ubuntu:",[884,9649],{"language":886,"src":9650},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-6-1-check-the-share-06.sh",[25,9652,9653,9659,9665],{},[28,9654,9655,9658],{},[266,9656,9657],{},"ls \u002Fmedia",": shows available mounted folders",[28,9660,9661,9664],{},[266,9662,9663],{},"ls \u002Fmedia\u002F\u003Cshared-folder>",": checks your course repo share",[28,9666,9667],{},"Permission denied is common the first time",[15,9669,9671,9675,9678,9681],{"id":9670,"level":18},"step-7-locate-share",[20,9672,9674],{"id":9673},"step-7-allow-shared-folder-access","Step 7: Allow Shared Folder Access",[41,9676,9677],{},"If the shared folder exists but says permission denied:",[884,9679],{"language":886,"src":9680},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-7-allow-shared-fold-07.sh",[25,9682,9683,9689,9695],{},[28,9684,9685,9688],{},[266,9686,9687],{},"vboxsf",": group allowed to read VirtualBox shared folders",[28,9690,9691,9694],{},[266,9692,9693],{},"$USER",": your Ubuntu login user for terminal access",[28,9696,9697],{},"Reboot applies the shared-folder support and new group membership",[15,9699,9701,9705,9707,9710,9727,9730],{"id":9700,"level":99},"step-7b-locate-share",[20,9702,9704],{"id":9703},"step-71-locate-the-shared-repo","Step 7.1: Locate The Shared Repo",[41,9706,9647],{},[884,9708],{"language":886,"src":9709},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-7-1-locate-the-shar-08.sh",[25,9711,9712,9718,9724],{},[28,9713,9714,9717],{},[266,9715,9716],{},"\u002Fmedia",": VirtualBox auto-mounted shared folders",[28,9719,9720,9723],{},[266,9721,9722],{},"\u003Cshared-folder>",": your shared course repo folder name",[28,9725,9726],{},"Use the folder that points to your repository",[41,9728,9729],{},"Expected repo folders:",[25,9731,9732,9736,9740,9744],{},[28,9733,9734],{},[266,9735,824],{},[28,9737,9738],{},[266,9739,5532],{},[28,9741,9742],{},[266,9743,5535],{},[28,9745,9746],{},[266,9747,5538],{},[15,9749,9751,9755,9770],{"id":9750,"level":99},"step-7-2-shared-folder-check",[20,9752,9754],{"id":9753},"step-72-shared-folder-check","Step 7.2: Shared Folder Check",[25,9756,9757,9760,9767],{},[28,9758,9759],{},"Edit a small file from VS Code on host",[28,9761,2362,9762,1201,9764,9766],{},[266,9763,813],{},[266,9765,1033],{}," inside Ubuntu",[28,9768,9769],{},"Confirm Ubuntu sees the same file content",[41,9771,9772],{},"If the file does not match, stop and fix the share before Apache setup",[15,9774,9776,9780,9782,9785],{"id":9775,"level":18},"step-8-install-apache-php-mysql",[20,9777,9779],{"id":9778},"step-8-install-apache-php-and-mysql","Step 8: Install Apache, PHP, And MySQL",[41,9781,9616],{},[884,9783],{"language":886,"src":9784},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-8-install-apache-ph-09.sh",[25,9786,9787,9793,9798,9804,9810,9816],{},[28,9788,9789,9792],{},[266,9790,9791],{},"apache2",": web server",[28,9794,9795,9797],{},[266,9796,5325],{},": PHP runtime",[28,9799,9800,9803],{},[266,9801,9802],{},"libapache2-mod-php",": lets Apache execute PHP files",[28,9805,9806,9809],{},[266,9807,9808],{},"mysql-server",": local MySQL database server",[28,9811,9812,9815],{},[266,9813,9814],{},"php-mysql",": lets PHP connect to MySQL",[28,9817,2362,9818,2328,9820,9822],{},[266,9819,9515],{},[266,9821,9521],{}," first only if they have not been run recently",[15,9824,9826,9830,9837],{"id":9825,"level":99},"optional-swap-check",[20,9827,9829],{"id":9828},"optional-add-swap-if-swap-is-off","Optional: Add Swap If Swap Is Off",[41,9831,9832,9833,9836],{},"Ubuntu usually has swap already. Only add this if ",[266,9834,9835],{},"swapon --show"," prints nothing.",[104,9838,9839,9853],{"gap":106,"left-width":107,"right-width":107},[109,9840,9841,9844,9847,9850],{"v-slot:left":111},[41,9842,9843],{},"Check first:",[884,9845],{"language":886,"src":9846},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-add-swap-if-swa-10.sh",[41,9848,9849],{},"Add a small swap file only if swap is off:",[884,9851],{"language":886,"src":9852},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-add-swap-if-swa-11.sh",[109,9854,9855],{"v-slot:right":111},[25,9856,9857,9860,9865,9868],{},[28,9858,9859],{},"Swap gives Ubuntu emergency disk-backed memory",[28,9861,9862,9863],{},"It helps when installs or MySQL briefly need more than ",[266,9864,8458],{},[28,9866,9867],{},"It is slower than RAM, so it is not a performance upgrade",[28,9869,9870],{},"Do not run the setup again if swap already exists",[15,9872,9874,9878,9884],{"id":9873,"level":99},"optional-apache-low-memory",[20,9875,9877],{"id":9876},"optional-limit-apache-memory-use","Optional: Limit Apache Memory Use",[41,9879,9880,9881,9883],{},"Use this if the ",[266,9882,8458],{}," VM feels unstable or Apache starts too many PHP workers.",[104,9885,9886,9899],{"gap":106,"left-width":107,"right-width":107},[109,9887,9888,9891,9896],{"v-slot:left":111},[41,9889,9890],{},"Edit Apache prefork settings in:",[41,9892,9893],{},[266,9894,9895],{},"\u002Fetc\u002Fapache2\u002Fmods-available\u002Fmpm_prefork.conf",[884,9897],{"language":886,"src":9898},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-limit-apache-me-12.sh",[109,9900,9901,9904,9908],{"v-slot:right":111},[41,9902,9903],{},"Change the existing values to:",[884,9905],{"language":9906,"src":9907},"apache","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-limit-apache-me-13.txt",[25,9909,9910,9916,9919,9926],{},[28,9911,9912,9913],{},"Edit the existing lines inside ",[266,9914,9915],{},"\u003CIfModule mpm_prefork_module>",[28,9917,9918],{},"If a line is missing, add it inside that same block",[28,9920,9921,9922,9925],{},"Do not paste a second ",[266,9923,9924],{},"\u003CIfModule>"," block",[28,9927,9928],{},"Restart Apache after config changes",[15,9930,9932,9936,9942],{"id":9931,"level":99},"optional-mysql-low-memory",[20,9933,9935],{"id":9934},"optional-limit-mysql-memory-use","Optional: Limit MySQL Memory Use",[41,9937,9938,9939,9941],{},"Use this only if MySQL struggles on the ",[266,9940,8458],{}," VM.",[104,9943,9944,9957],{"gap":106,"left-width":107,"right-width":107},[109,9945,9946,9949,9954],{"v-slot:left":111},[41,9947,9948],{},"Edit MySQL server settings in:",[41,9950,9951],{},[266,9952,9953],{},"\u002Fetc\u002Fmysql\u002Fmysql.conf.d\u002Fmysqld.cnf",[884,9955],{"language":886,"src":9956},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-limit-mysql-mem-14.sh",[109,9958,9959,9965,9968],{"v-slot:right":111},[41,9960,9961,9962,1258],{},"Add or edit these under ",[266,9963,9964],{},"[mysqld]",[884,9966],{"language":6132,"src":9967},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Foptional-limit-mysql-mem-15.txt",[25,9969,9970,9976,9981,9984],{},[28,9971,9972,9973,9975],{},"Keep these under the existing ",[266,9974,9964],{}," heading",[28,9977,9978,9979,9975],{},"Do not create a second ",[266,9980,9964],{},[28,9982,9983],{},"If either setting already exists, edit it instead of adding a duplicate",[28,9985,9986],{},"Restart MySQL after config changes",[15,9988,9990,9993,9996,9999],{"id":9989,"level":99},"low-memory-diagnostics",[20,9991,9992],{"id":9989},"Low Memory Diagnostics",[41,9994,9995],{},"Run these after the minor tuning checks:",[884,9997],{"language":886,"src":9998},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Flow-memory-diagnostics-10.sh",[25,10000,10001,10007,10012,10018,10025],{},[28,10002,10003,10006],{},[266,10004,10005],{},"free -h",": shows RAM and swap",[28,10008,10009,10011],{},[266,10010,9835],{},": confirms whether swap is active",[28,10013,10014,10017],{},[266,10015,10016],{},"systemctl status",": checks whether Apache and MySQL are running",[28,10019,10020,10021,10024],{},"No output from the ",[266,10022,10023],{},"grep"," line is usually good",[28,10026,10027],{},"Do not tune randomly; change one setting, restart, then retest",[15,10029,10031,10035,10037,10040,10043,10046],{"id":10030,"level":18},"step-9-create-local-mysql-db",[20,10032,10034],{"id":10033},"step-9-create-a-local-mysql-database","Step 9: Create A Local MySQL Database",[41,10036,9616],{},[884,10038],{"language":886,"src":10039},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-9-create-a-local-my-11.sh",[41,10041,10042],{},"Then run in the MySQL prompt:",[884,10044],{"language":5538,"src":10045},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-9-create-a-local-my-12.sql",[25,10047,10048,10052,10055],{},[28,10049,9448,10050,9452],{},[266,10051,9451],{},[28,10053,10054],{},"Database name and username should match your UCID",[28,10056,10057],{},"Password is local-only unless your instructor says otherwise",[15,10059,10061,10064,10067,10080,10083,10089],{"id":10060,"level":18},"local-vs-remote-database",[20,10062,10063],{"id":10060},"Local Vs Remote Database",[41,10065,10066],{},"This MySQL database is only for local testing:",[25,10068,10069,10073,10075,10077],{},[28,10070,4799,10071],{},[266,10072,8155],{},[28,10074,4814],{},[28,10076,4811],{},[28,10078,10079],{},"Password: your local password",[41,10081,10082],{},"Render uses the instructor-provided remote database connection string",[41,10084,10085,10086],{},"Get that string from ",[45,10087,4825],{"href":4825,"rel":10088},[49],[41,10090,10091],{},"After this lesson, you may optionally point local code at that remote database for extra testing",[15,10093,10095,10099,10101,10104,10106,10109,10112],{"id":10094,"level":18},"step-10-confirm-local-mysql",[20,10096,10098],{"id":10097},"step-10-confirm-local-mysql-login","Step 10: Confirm Local MySQL Login",[41,10100,9616],{},[884,10102],{"language":886,"src":10103},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-10-confirm-local-my-13.sh",[41,10105,4311],{},[884,10107],{"language":5538,"src":10108},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-10-confirm-local-my-14.sql",[41,10110,10111],{},"Expected:",[25,10113,10114,10120],{},[28,10115,10116,10119],{},[266,10117,10118],{},"SELECT DATABASE()"," returns your UCID",[28,10121,10122,10125],{},[266,10123,10124],{},"SHOW TABLES"," is empty or shows starter tables later",[15,10127,10129,10135,10138,10141,10144],{"id":10128,"level":18},"step-11-documentroot",[20,10130,10132,10133],{"id":10131},"step-11-point-apache-at-public_html","Step 11: Point Apache At ",[266,10134,824],{},[41,10136,10137],{},"Apache should serve:",[884,10139],{"language":3665,"src":10140},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-11-point-apache-at--15.txt",[41,10142,10143],{},"Do not serve the whole repo",[25,10145,10146,10155],{},[28,10147,10148,622,10150,626,10152,10154],{},[266,10149,5532],{},[266,10151,5535],{},[266,10153,5538],{}," stay outside the web root",[28,10156,10157,10159],{},[266,10158,824],{}," is the browser-facing folder",[15,10161,10163,10167,10170,10175,10177,10182,10185,10188],{"id":10162,"level":99},"apache-site-config",[20,10164,10166],{"id":10165},"step-111-apache-site-config","Step 11.1: Apache Site Config",[41,10168,10169],{},"Create or edit this Apache site config file inside Ubuntu:",[41,10171,10172],{},[266,10173,10174],{},"\u002Fetc\u002Fapache2\u002Fsites-available\u002Fit202.conf",[41,10176,882],{},[41,10178,10179],{},[266,10180,10181],{},"sudo nano \u002Fetc\u002Fapache2\u002Fsites-available\u002Fit202.conf",[41,10183,10184],{},"Add this content to that file:",[884,10186],{"language":9906,"src":10187},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-11-1-apache-site-co-16.txt",[25,10189,10190,10195,10201,10206],{},[28,10191,9448,10192,10194],{},[266,10193,9722],{}," with the actual shared folder name",[28,10196,10197,10198],{},"Save the file as ",[266,10199,10200],{},"it202.conf",[28,10202,10203,10204],{},"Apache listens on guest port ",[266,10205,7937],{},[28,10207,10208,10209],{},"Host browser reaches it through ",[266,10210,8013],{},[15,10212,10214,10218,10220,10223],{"id":10213,"level":99},"enable-site",[20,10215,10217],{"id":10216},"step-112-enable-the-site","Step 11.2: Enable The Site",[41,10219,9616],{},[884,10221],{"language":886,"src":10222},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-11-2-enable-the-sit-17.sh",[25,10224,10225,10231,10237,10243,10251,10257],{},[28,10226,10227,10230],{},[266,10228,10229],{},"a2ensite",": enable a site config",[28,10232,10233,10236],{},[266,10234,10235],{},"a2dissite",": disable a site config",[28,10238,10239,10242],{},[266,10240,10241],{},"www-data",": Apache's user for browser requests",[28,10244,10245,10246,6285,10248,10250],{},"Adding ",[266,10247,10241],{},[266,10249,9687],{}," lets Apache read the shared folder",[28,10252,10253,10256],{},[266,10254,10255],{},"configtest",": check syntax before reload",[28,10258,10259,10262],{},[266,10260,10261],{},"restart",": applies the Apache user group change",[15,10264,10266,10270,10273,10276,10279],{"id":10265,"level":18},"step-12-php-check-page",[20,10267,10269],{"id":10268},"step-12-create-a-php-check-page","Step 12: Create A PHP Check Page",[41,10271,10272],{},"Create this file on the host:",[884,10274],{"language":3665,"src":10275},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-12-create-a-php-che-18.txt",[41,10277,10278],{},"Example content:",[884,10280],{"language":5325,"src":10281},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Fstep-12-create-a-php-che-19.php",[15,10283,10285,10288,10291,10294,10296],{"id":10284,"level":18},"final-browser-check",[20,10286,10287],{"id":10284},"Final Browser Check",[41,10289,10290],{},"Open from host browser:",[884,10292],{"language":3665,"src":10293},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox\u002Ffinal-browser-check-20.txt",[41,10295,10111],{},[25,10297,10298,10301,10304,10307],{},[28,10299,10300],{},"Message appears",[28,10302,10303],{},"Time appears",[28,10305,10306],{},"PHP code is not shown as raw text",[28,10308,10309],{},"Editing the file on host changes output after refresh",[15,10311,10313,10316],{"id":10312,"level":18},"common-problems",[20,10314,10315],{"id":10312},"Common Problems",[25,10317,10318,10321,10324,10329,10332,10345,10355],{},[28,10319,10320],{},"Browser timeout: missing or wrong port-forwarding rule",[28,10322,10323],{},"Connection refused: Apache not running",[28,10325,10326,10327],{},"No internet in VM: check Adapter 1 is still ",[266,10328,9332],{},[28,10330,10331],{},"Shared folder missing: check Auto-mount and guest utilities",[28,10333,10334,10335,10338,10339,10341,10342,10344],{},"Browser shows ",[266,10336,10337],{},"403 Forbidden",": confirm ",[266,10340,10241],{}," is in ",[266,10343,9687],{},", then restart Apache or reboot",[28,10346,10347,10348,10351,10352,10354],{},"Permission denied on ",[266,10349,10350],{},"\u002Fmedia\u002Fsf_...",": confirm your Ubuntu user is in ",[266,10353,9687],{}," and reboot",[28,10356,10357],{},"Raw PHP code: PHP module not running through Apache",[15,10359,10361,10364,10367],{"id":10360,"level":18},"recovery-routine",[20,10362,10363],{"id":10360},"Recovery Routine",[41,10365,10366],{},"Check in this order:",[163,10368,10369,10372,10378,10384,10389,10397,10404,10410,10415,10424],{},[28,10370,10371],{},"VM is running",[28,10373,10374,10377],{},[266,10375,10376],{},"ping github.com"," works inside Ubuntu",[28,10379,10380,10383],{},[266,10381,10382],{},"ssh username@localhost"," works from host",[28,10385,10386,10388],{},[266,10387,9663],{}," shows the shared repo",[28,10390,10391,10394,10395],{},[266,10392,10393],{},"groups"," includes ",[266,10396,9687],{},[28,10398,10399,10394,10402],{},[266,10400,10401],{},"id www-data",[266,10403,9687],{},[28,10405,10406,10409],{},[266,10407,10408],{},"sudo systemctl status apache2"," is active",[28,10411,10412,10409],{},[266,10413,10414],{},"sudo systemctl status mysql",[28,10416,10417,10420,10421],{},[266,10418,10419],{},"sudo apache2ctl configtest"," says ",[266,10422,10423],{},"Syntax OK",[28,10425,10426,10429],{},[266,10427,10428],{},"http:\u002F\u002Flocalhost:3000\u002Fsystem\u002Fvm-check.php"," loads from the host browser",[15,10431,10432,10434],{"id":1455,"level":18},[20,10433,1456],{"id":1455},[104,10435,10436,10477],{"gap":106,"left-width":107,"right-width":107},[109,10437,10438,10440,10446,10455,10460,10466,10472],{"v-slot:left":111},[365,10439,1464],{"id":1463},[41,10441,10442,10445],{},[126,10443,10444],{},"VM"," - separate computer running inside your host computer",[41,10447,10448,10451,10452,10454],{},[126,10449,10450],{},"Port forwarding"," - host ",[266,10453,8155],{}," traffic routed into the VM",[41,10456,10457,10459],{},[126,10458,9687],{}," - VirtualBox shared-folder permission group",[41,10461,10462,10465],{},[126,10463,10464],{},"Guest utilities"," - VirtualBox tools that help shared folders work inside Ubuntu",[41,10467,10468,10471],{},[126,10469,10470],{},"DocumentRoot"," - folder Apache serves to browsers",[41,10473,10474,10476],{},[126,10475,9332],{}," - VM network mode that gives the VM outbound internet access",[109,10478,10479,10481],{"v-slot:right":111},[365,10480,1495],{"id":1452},[25,10482,10483,10489,10496,10503,10510,10517,10523],{},[28,10484,10485],{},[45,10486,10488],{"href":8079,"rel":10487},[49],"VirtualBox Downloads",[28,10490,10491],{},[45,10492,10495],{"href":10493,"rel":10494},"https:\u002F\u002Fdocs.oracle.com\u002Fen\u002Fvirtualization\u002Fvirtualbox\u002F7.2\u002Fuser\u002FIntroduction.html",[49],"VirtualBox Manual: Host And Guest Combinations",[28,10497,10498],{},[45,10499,10502],{"href":10500,"rel":10501},"https:\u002F\u002Fdocs.oracle.com\u002Fen\u002Fvirtualization\u002Fvirtualbox\u002F7.2\u002Fuser\u002Finstallation.html",[49],"VirtualBox Manual: Installation",[28,10504,10505],{},[45,10506,10509],{"href":10507,"rel":10508},"https:\u002F\u002Fdocs.oracle.com\u002Fen\u002Fvirtualization\u002Fvirtualbox\u002F7.2\u002Fuser\u002Fsharedfolders.html",[49],"VirtualBox Manual: Shared Folders",[28,10511,10512],{},[45,10513,10516],{"href":10514,"rel":10515},"https:\u002F\u002Fdocs.oracle.com\u002Fen\u002Fvirtualization\u002Fvirtualbox\u002F7.2\u002Fuser\u002Fnetworkingdetails.html#network_nat_service",[49],"VirtualBox Manual: NAT Port Forwarding",[28,10518,10519],{},[45,10520,10522],{"href":8097,"rel":10521},[49],"Ubuntu Server: Installer",[28,10524,10525],{},[45,10526,10529],{"href":10527,"rel":10528},"https:\u002F\u002Fdocumentation.ubuntu.com\u002Fserver\u002Fhow-to\u002Fsecurity\u002Fopenssh-server\u002F",[49],"Ubuntu Server: OpenSSH Server",[15,10531,10532,10534,10536],{"id":466,"level":18},[20,10533,469],{"id":466},[41,10535,1525],{},[25,10537,10538,10541,10544,10547,10550,10555],{},[28,10539,10540],{},"Pick the correct Ubuntu ISO for your host CPU",[28,10542,10543],{},"Configure NAT port forwarding",[28,10545,10546],{},"Connect to Ubuntu with SSH",[28,10548,10549],{},"Find the VirtualBox shared repo",[28,10551,10552,10553],{},"Configure Apache to serve ",[266,10554,824],{},[28,10556,10557],{},"Create a local MySQL database and user named after your UCID",{"title":111,"searchDepth":493,"depth":493,"links":10559},[10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,10614,10615,10616,10618,10619,10620,10621,10622,10623,10624,10625],{"id":7959,"depth":493,"text":7951},{"id":7985,"depth":493,"text":7988},{"id":8030,"depth":493,"text":8033},{"id":638,"depth":493,"text":641},{"id":8135,"depth":493,"text":8138},{"id":8170,"depth":493,"text":8171},{"id":8194,"depth":493,"text":8197},{"id":8226,"depth":493,"text":8229},{"id":8252,"depth":493,"text":8255},{"id":8281,"depth":493,"text":8284},{"id":8313,"depth":493,"text":8314},{"id":8337,"depth":493,"text":8340},{"id":8368,"depth":493,"text":8371},{"id":8399,"depth":493,"text":8400},{"id":8435,"depth":493,"text":8436},{"id":8497,"depth":493,"text":8500},{"id":8532,"depth":493,"text":8535},{"id":8578,"depth":493,"text":8581},{"id":8621,"depth":493,"text":8624},{"id":8665,"depth":493,"text":8668},{"id":8715,"depth":493,"text":8716},{"id":8778,"depth":493,"text":8779},{"id":8814,"depth":493,"text":8815},{"id":8849,"depth":493,"text":8850},{"id":8886,"depth":493,"text":8887},{"id":8919,"depth":493,"text":8920},{"id":8956,"depth":493,"text":8957},{"id":8989,"depth":493,"text":8990},{"id":9019,"depth":493,"text":9020},{"id":9049,"depth":493,"text":9050},{"id":9079,"depth":493,"text":9080},{"id":9109,"depth":493,"text":9110},{"id":9139,"depth":493,"text":9140},{"id":9173,"depth":493,"text":9174},{"id":9205,"depth":493,"text":9206},{"id":9237,"depth":493,"text":9238},{"id":9269,"depth":493,"text":9270},{"id":9320,"depth":493,"text":9321},{"id":9363,"depth":493,"text":9364},{"id":9389,"depth":493,"text":9390},{"id":9430,"depth":493,"text":9431},{"id":9482,"depth":493,"text":9483},{"id":9561,"depth":493,"text":9562},{"id":9612,"depth":493,"text":9613},{"id":9643,"depth":493,"text":9644},{"id":9673,"depth":493,"text":9674},{"id":9703,"depth":493,"text":9704},{"id":9753,"depth":493,"text":9754},{"id":9778,"depth":493,"text":9779},{"id":9828,"depth":493,"text":9829},{"id":9876,"depth":493,"text":9877},{"id":9934,"depth":493,"text":9935},{"id":9989,"depth":493,"text":9992},{"id":10033,"depth":493,"text":10034},{"id":10060,"depth":493,"text":10063},{"id":10097,"depth":493,"text":10098},{"id":10131,"depth":493,"text":10617},"Step 11: Point Apache At public_html",{"id":10165,"depth":493,"text":10166},{"id":10216,"depth":493,"text":10217},{"id":10268,"depth":493,"text":10269},{"id":10284,"depth":493,"text":10287},{"id":10312,"depth":493,"text":10315},{"id":10360,"depth":493,"text":10363},{"id":1455,"depth":493,"text":1456},{"id":466,"depth":493,"text":469},"Build the local Ubuntu VM path with VirtualBox, Apache, PHP, MySQL, SSH, and shared folders.","Face-to-face class of about 40 students; includes VirtualBox install differences, CPU\u002FISO selection, networking, SSH, shared folders, Apache\u002FPHP\u002FMySQL, browser checks, and beginner troubleshooting.","25","95","120",{},"\u002Finternet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox",{"title":7951,"description":10626},"internet-applications\u002Fpresentations\u002F01-git-github-and-course-workflow\u002F09-local-ubuntu-web-server-virtualbox",[10636,10637,9906,10638,10639],"virtualbox","ubuntu","mysql","vm","1:06:16","ArTDIgihfd4","https:\u002F\u002Fyoutu.be\u002FArTDIgihfd4","IT202 VirtualBox and VM Setup","CNlzYvIiYNPSzbQ6tvCdcnJLlvvGSGmurOGWR_mSnms",{"id":10646,"title":10647,"audience":10,"body":10648,"contentType":509,"course":510,"description":12541,"estimateBasis":12542,"estimatedDiscussionMinutes":3585,"estimatedLiveMinutes":3586,"estimatedTotalMinutes":3587,"extension":516,"meta":12543,"module":18,"navigation":519,"order":513,"path":12544,"promptAssist":522,"seo":12545,"status":524,"stem":12546,"tags":12547,"videoDuration":12550,"videoId":12551,"videoLink":12552,"videoTitle":12553,"week":18,"__hash__":12554},"content\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript.md","Compare PHP And JavaScript",{"type":12,"value":10649,"toc":12506},[10650,10673,10715,10750,10806,10876,10885,10951,11018,11101,11153,11242,11296,11340,11440,11498,11553,11610,11674,11719,11786,11950,12028,12054,12099,12139,12180,12214,12246,12264,12319,12377,12405],[15,10651,10653,10656],{"id":10652,"level":18},"main-idea",[20,10654,10655],{"id":10652},"Main Idea",[25,10657,10658,10661,10664,10667,10670],{},[28,10659,10660],{},"PHP and JavaScript share programming ideas",[28,10662,10663],{},"PHP runs on the server; JavaScript usually runs in the browser",[28,10665,10666],{},"Output appears in different places depending on where the code runs",[28,10668,10669],{},"Types, variables, arrays, and operators look similar but have important differences",[28,10671,10672],{},"Error messages usually give a file, line, and clue before you change code",[15,10674,10676,10679],{"id":10675,"level":18},"practice-workspace",[20,10677,10678],{"id":10675},"Practice Workspace",[25,10680,10681,10687,10693,10696,10706,10709],{},[28,10682,10683,10684],{},"Work inside ",[266,10685,10686],{},"public_html\u002Fm02\u002Flessons\u002F",[28,10688,10689,10690],{},"Lesson branch: ",[266,10691,10692],{},"Module02-PHP-vs-JS",[28,10694,10695],{},"Create the folder if it is missing",[28,10697,10698,10699,10702,10703],{},"Use file prefix ",[266,10700,10701],{},"php-js-",", such as ",[266,10704,10705],{},"php-js-type-check.php",[28,10707,10708],{},"Keep each practice file small enough to debug directly",[28,10710,10711,10712,10714],{},"After a working change: run ",[266,10713,3856],{},", stage the changed files, and commit",[15,10716,10718,10721,10724,10747],{"id":10717,"level":18},"lesson-path",[20,10719,10720],{"id":10717},"Lesson Path",[41,10722,10723],{},"This presentation compares the same programming ideas in both languages:",[163,10725,10726,10729,10732,10735,10738,10741,10744],{},[28,10727,10728],{},"Where code runs",[28,10730,10731],{},"Comments",[28,10733,10734],{},"Output and inspection tools",[28,10736,10737],{},"Variables and scope",[28,10739,10740],{},"Data types and examples",[28,10742,10743],{},"Operators and comparisons",[28,10745,10746],{},"Beginner PHP error reading",[41,10748,10749],{},"Loops, conditions, and functions continue in the next presentation.",[15,10751,10753,10757,10803],{"id":10752,"level":18},"server-vs-browser",[20,10754,10756],{"id":10755},"server-code-and-browser-code","Server Code And Browser Code",[104,10758,10759,10780],{"gap":106,"left-width":107,"right-width":107},[109,10760,10761,10763],{"v-slot:left":111},[365,10762,4683],{"id":5325},[25,10764,10765,10768,10771,10774,10777],{},[28,10766,10767],{},"Runs on the server",[28,10769,10770],{},"Can read server files",[28,10772,10773],{},"Can connect to a database, such as MySQL",[28,10775,10776],{},"Builds HTML, JSON, or redirects",[28,10778,10779],{},"Output becomes part of the response",[109,10781,10782,10786],{"v-slot:right":111},[365,10783,10785],{"id":10784},"javascript","JavaScript",[25,10787,10788,10791,10794,10797,10800],{},[28,10789,10790],{},"Usually runs in the browser",[28,10792,10793],{},"Reacts to clicks and inputs",[28,10795,10796],{},"Can update the page after it loads",[28,10798,10799],{},"Can send later requests to the server",[28,10801,10802],{},"Output usually appears in DevTools Console unless it changes the page",[41,10804,10805],{},"Quick rule: server-side code prepares the response; browser-side code works with the response.",[15,10807,10809,10812],{"id":10808,"level":18},"where-code-lives",[20,10810,10811],{"id":10808},"Where Code Lives",[104,10813,10814,10847],{"gap":106,"left-width":107,"right-width":107},[109,10815,10816,10820,10823],{"v-slot:left":111},[365,10817,10819],{"id":10818},"php-page","PHP Page",[884,10821],{"language":5325,"src":10822},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fwhere-code-lives-10.php",[25,10824,10825,10831,10837,10844],{},[28,10826,10827,10828],{},"File normally ends in ",[266,10829,10830],{},".php",[28,10832,10833,10836],{},[266,10834,10835],{},"\u003C?php"," starts PHP mode inside the file",[28,10838,10839,10840,10843],{},"Closing ",[266,10841,10842],{},"?>"," is needed when a file switches from PHP back to HTML",[28,10845,10846],{},"The server executes PHP before the browser sees the response",[109,10848,10849,10853,10857],{"v-slot:right":111},[365,10850,10852],{"id":10851},"javascript-page","JavaScript Page",[884,10854],{"language":10855,"src":10856},"html","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fwhere-code-lives-11.html",[25,10858,10859,10870,10873],{},[28,10860,10861,10862,10865,10866,10869],{},"JavaScript can live in a ",[266,10863,10864],{},"\u003Cscript>"," tag or separate ",[266,10867,10868],{},".js"," file",[28,10871,10872],{},"The browser runs it after the page reaches the user",[28,10874,10875],{},"Console output appears in DevTools, not in the page body",[15,10877,10879,10882],{"id":10878,"level":18},"request-flow",[20,10880,10881],{"id":10878},"Request Flow",[2586,10883],{"code":10884},"sequenceDiagram\n  participant Browser\n  participant WebServer as Web Server\n  participant PHP as Server-side Code\n  participant DB as Database\n  Browser->>WebServer: GET \u002Fm02\u002Flessons\u002Fphp-js-type-check.php\n  WebServer->>PHP: Run PHP file\n  PHP-->>DB: Optional data work\n  PHP-->>WebServer: Finished response\n  WebServer-->>Browser: HTML or JSON\n  Browser->>Browser: Run JavaScript\n",[15,10886,10888,10891,10894,10897],{"id":10887,"level":18},"php-syntax-first",[20,10889,10890],{"id":10887},"PHP Syntax First",[884,10892],{"language":5325,"src":10893},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-syntax-first-08.php",[41,10895,10896],{},"Required pieces:",[104,10898,10899,10928],{"gap":106,"left-width":107,"right-width":107},[109,10900,10901],{"v-slot:left":111},[25,10902,10903,10908,10919,10925],{},[28,10904,10905,10907],{},[266,10906,10835],{},": starts PHP mode",[28,10909,10910,10913,10914],{},[266,10911,10912],{},"$",": starts a variable name",[25,10915,10916],{},[28,10917,10918],{},"This tells PHP the next name is a variable, not plain text, a keyword, or a function name",[28,10920,10921,10924],{},[266,10922,10923],{},";",": ends a PHP statement",[28,10926,10927],{},"Variable names are case-sensitive",[109,10929,10930,10935,10948],{"v-slot:right":111},[28,10931,10197,10932,10934],{},[266,10933,10830],{}," so server-side code can run",[28,10936,10937,10938,10940,10941],{},"Omit the closing ",[266,10939,10842],{}," when a file contains only PHP\n",[25,10942,10943],{},[28,10944,1150,10945,10947],{},[266,10946,10842],{}," only when switching back to HTML in the same file",[28,10949,10950],{},"Raw PHP tags in the browser usually mean the file was opened directly or not served as PHP",[15,10952,10954,10956,11015],{"id":10953,"level":18},"comments",[20,10955,10731],{"id":10953},[104,10957,10958,10992],{"gap":106,"left-width":107,"right-width":107},[109,10959,10960,10963,10966],{"v-slot:left":111},[365,10961,4683],{"id":10962},"php-1",[884,10964],{"language":5325,"src":10965},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fcomments-16.php",[25,10967,10968,10974,10980,10986],{},[28,10969,10970,10973],{},[266,10971,10972],{},"\u002F\u002F",": single-line comment",[28,10975,10976,10979],{},[266,10977,10978],{},"#",": PHP single-line comment",[28,10981,10982,10985],{},[266,10983,10984],{},"\u002F* ... *\u002F",": block comment",[28,10987,10988,10991],{},[266,10989,10990],{},"\u002F** ... *\u002F",": documentation style",[109,10993,10994,10997,11001],{"v-slot:right":111},[365,10995,10785],{"id":10996},"javascript-1",[884,10998],{"language":10999,"src":11000},"js","\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fcomments-17.js",[25,11002,11003,11007,11011],{},[28,11004,11005,10973],{},[266,11006,10972],{},[28,11008,11009,10985],{},[266,11010,10984],{},[28,11012,11013,10991],{},[266,11014,10990],{},[41,11016,11017],{},"Block comments can't be nested in either language.",[15,11019,11021,11025],{"id":11020,"level":18},"output-tools",[20,11022,11024],{"id":11023},"output-and-inspection-tools","Output And Inspection Tools",[104,11026,11027,11064],{"gap":106,"left-width":107,"right-width":107},[109,11028,11029,11033,11036],{"v-slot:left":111},[365,11030,11032],{"id":11031},"php-checks","PHP Checks",[884,11034],{"language":5325,"src":11035},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-checks-01.php",[25,11037,11038,11046,11052,11058],{},[28,11039,11040,8754,11042,11045],{},[266,11041,1002],{},[266,11043,11044],{},"print",": send simple text into the response",[28,11047,11048,11051],{},[266,11049,11050],{},"var_export()",": show array keys and values clearly",[28,11053,11054,11057],{},[266,11055,11056],{},"var_dump()",": show type, size, and value",[28,11059,1150,11060,11063],{},[266,11061,11062],{},"\u003Cpre>"," when debug output needs line breaks",[109,11065,11066,11070,11073],{"v-slot:right":111},[365,11067,11069],{"id":11068},"javascript-checks","JavaScript Checks",[884,11071],{"language":10999,"src":11072},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fjavascript-checks-02.js",[25,11074,11075,11081,11087,11090,11095],{},[28,11076,11077,11080],{},[266,11078,11079],{},"console.log()",": inspect values",[28,11082,11083,11086],{},[266,11084,11085],{},"console.table()",": inspect arrays or objects in table form",[28,11088,11089],{},"Open DevTools before judging behavior",[28,11091,4892,11092],{},[266,11093,11094],{},"Ctrl+Shift+J",[28,11096,11097,11098],{},"On macOS: ",[266,11099,11100],{},"Cmd+Option+J",[15,11102,11104,11108],{"id":11103,"level":18},"inspection-output-tools",[20,11105,11107],{"id":11106},"why-inspection-tools-help","Why Inspection Tools Help",[104,11109,11110,11128],{"gap":106,"left-width":107,"right-width":107},[109,11111,11112,11115,11118],{"v-slot:left":111},[41,11113,11114],{},"Snippet:",[884,11116],{"language":5325,"src":11117},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Finspection-output-tools-06.php",[41,11119,11120,2328,11122,11124,11125,11127],{},[266,11121,11050],{},[266,11123,11056],{}," show details ",[266,11126,1002],{}," cannot show clearly:",[109,11129,11130,11132,11135],{"v-slot:right":111},[41,11131,2225],{},[884,11133],{"language":3665,"src":11134},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Finspection-output-tools-07.txt",[25,11136,11137,11142,11148],{},[28,11138,11139,11141],{},[266,11140,1002],{}," can display a value, but it hides structure",[28,11143,11144,11145,11147],{},"Arrays need an inspection tool because ",[266,11146,1002],{}," cannot show array keys, indexes, or nested values",[28,11149,11150,11152],{},[266,11151,11056],{}," is best when type confusion is possible",[15,11154,11156,11159],{"id":11155,"level":18},"defining-variables",[20,11157,11158],{"id":11155},"Defining Variables",[104,11160,11161,11200],{"gap":106,"left-width":107,"right-width":107},[109,11162,11163,11166,11169],{"v-slot:left":111},[365,11164,4683],{"id":11165},"php-2",[884,11167],{"language":5325,"src":11168},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fdefining-variables-23.php",[25,11170,11171,11176,11179,11184,11194],{},[28,11172,11173,11174],{},"Variable names start with ",[266,11175,10912],{},[28,11177,11178],{},"Names can contain letters, numbers, and underscores",[28,11180,11181,11182],{},"Names cannot start with a number after ",[266,11183,10912],{},[28,11185,11186,11187,2328,11190,11193],{},"Case matters: ",[266,11188,11189],{},"$name",[266,11191,11192],{},"$Name"," are different",[28,11195,11196,11199],{},[266,11197,11198],{},"snake_case"," is common in beginner PHP examples",[109,11201,11202,11205,11208],{"v-slot:right":111},[365,11203,10785],{"id":11204},"javascript-2",[884,11206],{"language":10999,"src":11207},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fdefining-variables-24.js",[25,11209,11210,11213,11219,11225,11231,11239],{},[28,11211,11212],{},"Variables use a keyword before the name",[28,11214,11215,11218],{},[266,11216,11217],{},"let",": value may change",[28,11220,11221,11224],{},[266,11222,11223],{},"const",": value cannot be reassigned",[28,11226,11227,11230],{},[266,11228,11229],{},"var",": older keyword; avoid in new beginner code",[28,11232,11186,11233,2328,11236,11193],{},[266,11234,11235],{},"name",[266,11237,11238],{},"Name",[28,11240,11241],{},"See the below slide for the scope differences between these keywords",[15,11243,11245,11249],{"id":11244,"level":99},"variable-scope-keywords",[20,11246,11248],{"id":11247},"javascript-scope-keywords","JavaScript Scope Keywords",[104,11250,11251,11256],{"gap":106,"left-width":2255,"right-width":1710},[109,11252,11253],{"v-slot:left":111},[884,11254],{"language":10999,"src":11255},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fvariable-scope-keywords-18.js",[109,11257,11258,11261],{"v-slot:right":111},[41,11259,11260],{},"What to notice:",[25,11262,11263,11266,11271,11276,11281,11289],{},[28,11264,11265],{},"Scope means where a variable name can be used or seen in code",[28,11267,11268,11270],{},[266,11269,11217],{},": block-scoped",[28,11272,11273,11275],{},[266,11274,11223],{},": block-scoped and cannot be reassigned",[28,11277,11278,11280],{},[266,11279,11229],{},": function-scoped",[28,11282,11283,11284,2328,11286,11288],{},"Prefer ",[266,11285,11217],{},[266,11287,11223],{}," in new code",[28,11290,11186,11291,2328,11293,11295],{},[266,11292,11235],{},[266,11294,11238],{}," are different variables",[15,11297,11299,11302],{"id":11298,"level":18},"type-check",[20,11300,11301],{"id":11298},"Type Check",[104,11303,11304,11314],{"gap":106,"left-width":107,"right-width":107},[109,11305,11306,11311],{"v-slot:left":111},[41,11307,4678,11308,1258],{},[266,11309,11310],{},"public_html\u002Fm02\u002Flessons\u002Fphp-js-type-check.php",[884,11312],{"language":5325,"src":11313},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Ftype-check-03.php",[109,11315,11316,11318,11321,11324],{"v-slot:right":111},[41,11317,2754],{},[884,11319],{"language":3665,"src":11320},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fexample-output-04.txt",[41,11322,11323],{},"Easy mistake:",[25,11325,11326,11334,11337],{},[28,11327,11328,2328,11331,11333],{},[266,11329,11330],{},"\"2\"",[266,11332,18],{}," look similar on screen",[28,11335,11336],{},"They are not the same type",[28,11338,11339],{},"Check the type before changing the comparison or math",[15,11341,11343,11347],{"id":11342,"level":18},"common-types",[20,11344,11346],{"id":11345},"common-value-types","Common Value Types",[104,11348,11349,11397],{"gap":106,"left-width":107,"right-width":107},[109,11350,11351,11354,11357],{"v-slot:left":111},[365,11352,4683],{"id":11353},"php-3",[884,11355],{"language":5325,"src":11356},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fcommon-types-12.php",[25,11358,11359,11382,11385,11388],{},[28,11360,11361,622,11364,622,11367,622,11370,622,11373,622,11376,622,11379],{},[266,11362,11363],{},"string",[266,11365,11366],{},"int",[266,11368,11369],{},"float",[266,11371,11372],{},"bool",[266,11374,11375],{},"array",[266,11377,11378],{},"object",[266,11380,11381],{},"null",[28,11383,11384],{},"Arrays can be ordered lists or key\u002Fvalue maps",[28,11386,11387],{},"Resources represent external handles, such as database connections",[28,11389,11390,2328,11393,11396],{},[266,11391,11392],{},"PHP_INT_MAX",[266,11394,11395],{},"PHP_FLOAT_MAX"," show platform limits",[109,11398,11399,11402,11405],{"v-slot:right":111},[365,11400,10785],{"id":11401},"javascript-3",[884,11403],{"language":10999,"src":11404},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fcommon-types-13.js",[25,11406,11407,11426,11432],{},[28,11408,11409,622,11411,622,11414,622,11417,622,11419,622,11421,622,11423],{},[266,11410,11363],{},[266,11412,11413],{},"number",[266,11415,11416],{},"boolean",[266,11418,11375],{},[266,11420,11378],{},[266,11422,11381],{},[266,11424,11425],{},"undefined",[28,11427,11428,11429,11431],{},"JavaScript uses one ",[266,11430,11413],{}," type for most numeric values",[28,11433,11434,11436,11437,11439],{},[266,11435,11381],{}," is intentional absence; ",[266,11438,11425],{}," usually means no value was assigned",[15,11441,11443,11446],{"id":11442,"level":18},"php-string-examples",[20,11444,11445],{"id":11442},"PHP String Examples",[104,11447,11448,11453],{"gap":106,"left-width":2255,"right-width":1710},[109,11449,11450],{"v-slot:left":111},[884,11451],{"language":5325,"src":11452},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-string-examples-19.php",[109,11454,11455,11458],{"v-slot:right":111},[41,11456,11457],{},"Key differences:",[25,11459,11460,11463,11478,11483,11488],{},[28,11461,11462],{},"Double quotes can interpolate variables",[28,11464,11465,11466],{},"Single quotes do not interpolate variables\n",[25,11467,11468],{},[28,11469,11470,11471,2328,11474,11477],{},"Escapes such as ",[266,11472,11473],{},"\\\\",[266,11475,11476],{},"\\'"," still have special meaning",[28,11479,11480,11482],{},[266,11481,757],{}," joins strings in PHP",[28,11484,11485,11487],{},[266,11486,2677],{}," is math, not PHP string joining",[28,11489,11490,11491],{},"If a string is used in math, PHP may try to convert it to a number first\n",[25,11492,11493],{},[28,11494,1150,11495,11497],{},[266,11496,11056],{}," to confirm the value and type before changing the expression",[15,11499,11501,11504],{"id":11500,"level":18},"php-number-examples",[20,11502,11503],{"id":11500},"PHP Number Examples",[104,11505,11506,11511],{"gap":106,"left-width":107,"right-width":107},[109,11507,11508],{"v-slot:left":111},[884,11509],{"language":5325,"src":11510},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-number-examples-20.php",[109,11512,11513,11515],{"v-slot:right":111},[41,11514,11260],{},[25,11516,11517,11520,11523,11531,11539,11545,11548],{},[28,11518,11519],{},"Integers are whole numbers",[28,11521,11522],{},"Floats use decimals",[28,11524,11525,11528,11529],{},[266,11526,11527],{},"++",": shorthand to increase a number by ",[266,11530,518],{},[28,11532,11533,11536,11537],{},[266,11534,11535],{},"--",": shorthand to decrease a number by ",[266,11538,518],{},[28,11540,11541,11544],{},[266,11542,11543],{},"+=",": shorthand to add a value and store the result",[28,11546,11547],{},"Float math can have precision surprises",[28,11549,1150,11550,11552],{},[266,11551,11056],{}," when printed output hides detail",[15,11554,11556,11559],{"id":11555,"level":18},"php-array-examples",[20,11557,11558],{"id":11555},"PHP Array Examples",[104,11560,11561,11566],{"gap":106,"left-width":2255,"right-width":1710},[109,11562,11563],{"v-slot:left":111},[884,11564],{"language":5325,"src":11565},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-array-examples-21.php",[109,11567,11568,11571],{"v-slot:right":111},[41,11569,11570],{},"Array shapes:",[25,11572,11573,11576,11579,11584,11591],{},[28,11574,11575],{},"Indexed array: values by numeric position",[28,11577,11578],{},"Associative array: values by named key",[28,11580,11581,11582],{},"Indexes start at ",[266,11583,520],{},[28,11585,11586,1201,11588,11590],{},[266,11587,11056],{},[266,11589,11050],{}," shows structure",[28,11592,11593,11596,11597],{},[266,11594,11595],{},"echo $array"," cannot print the full array structure\n",[25,11598,11599],{},[28,11600,11601,11602,11604,11605,1201,11607,11609],{},"PHP only has a single value slot for ",[266,11603,1002],{},", so use ",[266,11606,11056],{},[266,11608,11050],{}," to see keys and nested values",[15,11611,11613,11617],{"id":11612,"level":18},"javascript-typeof-examples",[20,11614,11616],{"id":11615},"javascript-type-examples","JavaScript Type Examples",[104,11618,11619,11624],{"gap":106,"left-width":2255,"right-width":1710},[109,11620,11621],{"v-slot:left":111},[884,11622],{"language":10999,"src":11623},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fjavascript-typeof-examples-22.js",[109,11625,11626,11628],{"v-slot:right":111},[41,11627,11260],{},[25,11629,11630,11636,11652,11664,11669],{},[28,11631,11632,11635],{},[266,11633,11634],{},"typeof"," helps identify primitive types",[28,11637,11638,11639,11641],{},"Arrays report as ",[266,11640,11378],{},[25,11642,11643,11646],{},[28,11644,11645],{},"Arrays are a specialized kind of object in JavaScript",[28,11647,1150,11648,11651],{},[266,11649,11650],{},"Array.isArray(value)"," when you need to know if the value is an array",[28,11653,11654,11656,11657,11659],{},[266,11655,11381],{}," also reports as ",[266,11658,11378],{},[25,11660,11661],{},[28,11662,11663],{},"This is old JavaScript behavior kept for compatibility",[28,11665,11666,11668],{},[266,11667,11381],{},": a deliberately assigned empty value",[28,11670,11671,11673],{},[266,11672,11425],{},": a missing or not-yet-assigned value",[15,11675,11677,11680],{"id":11676,"level":18},"string-joining",[20,11678,11679],{"id":11676},"String Joining",[104,11681,11682,11701],{"gap":106,"left-width":107,"right-width":107},[109,11683,11684,11687,11690],{"v-slot:left":111},[365,11685,4683],{"id":11686},"php-4",[884,11688],{"language":5325,"src":11689},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fphp-05.php",[25,11691,11692,11696],{},[28,11693,11694,11482],{},[266,11695,757],{},[28,11697,11698,11700],{},[266,11699,2677],{}," is for math",[109,11702,11703,11706,11709],{"v-slot:right":111},[365,11704,10785],{"id":11705},"javascript-4",[884,11707],{"language":10999,"src":11708},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fjavascript-06.js",[25,11710,11711,11714],{},[28,11712,11713],{},"Template literals use backticks",[28,11715,11716,11718],{},[266,11717,2677],{}," can join strings in JavaScript",[15,11720,11722,11725],{"id":11721,"level":18},"operators-and-equality",[20,11723,11724],{"id":11721},"Operators And Equality",[104,11726,11727,11758],{"gap":106,"left-width":107,"right-width":107},[109,11728,11729,11732,11735],{"v-slot:left":111},[365,11730,4683],{"id":11731},"php-5",[884,11733],{"language":5325,"src":11734},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Foperators-and-equality-14.php",[25,11736,11737,11742,11746,11752],{},[28,11738,11739,11741],{},[266,11740,757],{}," joins strings",[28,11743,11744,11700],{},[266,11745,2677],{},[28,11747,11748,11751],{},[266,11749,11750],{},"=="," checks loose equality and can convert types",[28,11753,11754,11757],{},[266,11755,11756],{},"==="," checks value and type",[109,11759,11760,11763,11766],{"v-slot:right":111},[365,11761,10785],{"id":11762},"javascript-5",[884,11764],{"language":10999,"src":11765},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Foperators-and-equality-15.js",[25,11767,11768,11773,11778,11782],{},[28,11769,11770,11771],{},"Template literals are usually clearer than ",[266,11772,2677],{},[28,11774,11775,11777],{},[266,11776,2677],{}," can do math or string joining",[28,11779,11780,11751],{},[266,11781,11750],{},[28,11783,11784,11757],{},[266,11785,11756],{},[15,11787,11789,11792],{"id":11788,"level":18},"operator-categories",[20,11790,11791],{"id":11788},"Operator Categories",[104,11793,11794,11868],{"gap":106,"left-width":107,"right-width":107},[109,11795,11796,11800],{"v-slot:left":111},[365,11797,11799],{"id":11798},"common-in-both","Common In Both",[25,11801,11802,11836,11851],{},[28,11803,11804,11805],{},"Arithmetic operators",[25,11806,11807,11812,11818,11824,11830],{},[28,11808,11809,11811],{},[266,11810,2677],{},": addition",[28,11813,11814,11817],{},[266,11815,11816],{},"-",": subtraction",[28,11819,11820,11823],{},[266,11821,11822],{},"*",": multiplication",[28,11825,11826,11829],{},[266,11827,11828],{},"\u002F",": division",[28,11831,11832,11835],{},[266,11833,11834],{},"%",": remainder after division",[28,11837,11838,11839],{},"Equality operators",[25,11840,11841,11846],{},[28,11842,11843,11845],{},[266,11844,11750],{},": loose equality; may convert types",[28,11847,11848,11850],{},[266,11849,11756],{},": strict equality; checks value and type",[28,11852,11853,11854],{},"Inequality operators",[25,11855,11856,11862],{},[28,11857,11858,11861],{},[266,11859,11860],{},"!=",": loose inequality",[28,11863,11864,11867],{},[266,11865,11866],{},"!==",": strict inequality",[109,11869,11870,11898,11921,11935],{"v-slot:right":111},[28,11871,11872,11873],{},"Comparison operators\n",[25,11874,11875,11880,11886,11892],{},[28,11876,11877,11879],{},[266,11878,1008],{},": greater than",[28,11881,11882,11885],{},[266,11883,11884],{},"\u003C",": less than",[28,11887,11888,11891],{},[266,11889,11890],{},">=",": greater than or equal to",[28,11893,11894,11897],{},[266,11895,11896],{},"\u003C=",": less than or equal to",[28,11899,11900,11901],{},"Logical operators\n",[25,11902,11903,11909,11915],{},[28,11904,11905,11908],{},[266,11906,11907],{},"&&",": both sides must be true",[28,11910,11911,11914],{},[266,11912,11913],{},"||",": at least one side must be true",[28,11916,11917,11920],{},[266,11918,11919],{},"!",": flips true to false or false to true",[28,11922,11923,11924,11927],{},"Ternary operator: ",[266,11925,11926],{},"condition ? valueA : valueB",[25,11928,11929,11932],{},[28,11930,11931],{},"Short way to choose between two values",[28,11933,11934],{},"Avoid nested ternaries when readability suffers",[28,11936,11937,11938],{},"String joining\n",[25,11939,11940,11945],{},[28,11941,11942,11943],{},"PHP uses ",[266,11944,757],{},[28,11946,11947,11948],{},"JavaScript usually uses template literals or ",[266,11949,2677],{},[15,11951,11953,11956,11959],{"id":11952,"level":18},"type-conversion-examples",[20,11954,11955],{"id":11952},"Type Conversion Examples",[41,11957,11958],{},"Type conversion means a value is treated as a different type.",[104,11960,11961,11995],{"gap":106,"left-width":107,"right-width":107},[109,11962,11963,11966,11969],{"v-slot:left":111},[365,11964,4683],{"id":11965},"php-6",[884,11967],{"language":5325,"src":11968},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Ftype-conversion-examples-25.php",[25,11970,11971,11977,11983,11989],{},[28,11972,11973,11976],{},[266,11974,11975],{},"(int)"," turns numeric text into an integer",[28,11978,11979,11982],{},[266,11980,11981],{},"(float)"," turns decimal text into a float",[28,11984,11985,11988],{},[266,11986,11987],{},"(string)"," turns a value into text",[28,11990,11991,11994],{},[266,11992,11993],{},"explode()"," can split text into an array",[109,11996,11997,12000,12003],{"v-slot:right":111},[365,11998,10785],{"id":11999},"javascript-6",[884,12001],{"language":10999,"src":12002},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Ftype-conversion-examples-26.js",[25,12004,12005,12011,12017,12023],{},[28,12006,12007,12010],{},[266,12008,12009],{},"Number()"," turns numeric text into a number",[28,12012,12013,12016],{},[266,12014,12015],{},"parseFloat()"," reads decimal text as a number",[28,12018,12019,12022],{},[266,12020,12021],{},"Boolean()"," turns truthy\u002Ffalsy values into a boolean",[28,12024,12025,11994],{},[266,12026,12027],{},"split()",[15,12029,12031,12034],{"id":12030,"level":18},"php-error-reading",[20,12032,12033],{"id":12030},"PHP Error Reading",[25,12035,12036,12039,12042,12045,12048,12051],{},[28,12037,12038],{},"Start from a page that already worked",[28,12040,12041],{},"Break one line on purpose only while practicing",[28,12043,12044],{},"Read the newest error entry before changing code",[28,12046,12047],{},"Extract the error type, file path, and line number",[28,12049,12050],{},"Check the reported line and the line above it",[28,12052,12053],{},"See the slides below for common error examples and the fix loop",[15,12055,12057,12061],{"id":12056,"level":99},"syntax-error-example",[20,12058,12060],{"id":12059},"example-syntax-error","Example: Syntax Error",[104,12062,12063,12077],{"gap":106,"left-width":107,"right-width":107},[109,12064,12065,12068,12071,12074],{"v-slot:left":111},[41,12066,12067],{},"Working line:",[884,12069],{"language":5325,"src":12070},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fbreak-one-line-on-purpos-02.php",[41,12072,12073],{},"Broken line:",[884,12075],{"language":5325,"src":12076},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fbreak-one-line-on-purpos-03.php",[109,12078,12079,12082],{"v-slot:right":111},[41,12080,12081],{},"What changed:",[25,12083,12084,12087,12090,12093,12096],{},[28,12085,12086],{},"Removed the semicolon",[28,12088,12089],{},"PHP statement is no longer complete",[28,12091,12092],{},"The browser may show a server error or blank output",[28,12094,12095],{},"Keep the change small so the clue points to one likely cause",[28,12097,12098],{},"Next slide shows how to check the error",[15,12100,12102,12105],{"id":12101,"level":99},"server-error-log",[20,12103,12104],{"id":12101},"Server Error Log",[104,12106,12107,12118],{"gap":106,"left-width":107,"right-width":107},[109,12108,12109,12112,12115],{"v-slot:left":111},[41,12110,12111],{},"If the local server uses Apache, run inside Ubuntu:",[884,12113],{"language":886,"src":12114},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fread-the-apache-error-lo-04.sh",[41,12116,12117],{},"Read the newest entry after each refresh.",[109,12119,12120,12122,12125],{"v-slot:right":111},[41,12121,5094],{},[884,12123],{"language":3665,"src":12124},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fexample-output-05.txt",[25,12126,12127,12130,12133,12136],{},[28,12128,12129],{},"Error type",[28,12131,12132],{},"File path",[28,12134,12135],{},"Line number",[28,12137,12138],{},"Nearby token or variable name",[15,12140,12142,12146],{"id":12141,"level":99},"undefined-variable",[20,12143,12145],{"id":12144},"example-undefined-variable","Example: Undefined Variable",[104,12147,12148,12156],{"gap":106,"left-width":107,"right-width":107},[109,12149,12150,12153],{"v-slot:left":111},[41,12151,12152],{},"Broken code:",[884,12154],{"language":5325,"src":12155},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fundefined-variable-15.php",[109,12157,12158,12161,12164],{"v-slot:right":111},[41,12159,12160],{},"Likely message:",[884,12162],{"language":3665,"src":12163},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fundefined-variable-output-16.txt",[25,12165,12166,12174,12177],{},[28,12167,12168,2328,12171,3738],{},[266,12169,12170],{},"$courseCode",[266,12172,12173],{},"$coursecode",[28,12175,12176],{},"The page may keep running, but the output is wrong",[28,12178,12179],{},"Fix the variable name that does not match",[15,12181,12183,12187],{"id":12182,"level":99},"undefined-function",[20,12184,12186],{"id":12185},"example-undefined-function","Example: Undefined Function",[104,12188,12189,12196],{"gap":106,"left-width":107,"right-width":107},[109,12190,12191,12193],{"v-slot:left":111},[41,12192,12152],{},[884,12194],{"language":5325,"src":12195},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fundefined-function-17.php",[109,12197,12198,12200,12203],{"v-slot:right":111},[41,12199,12160],{},[884,12201],{"language":3665,"src":12202},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fundefined-function-output-18.txt",[25,12204,12205,12208,12211],{},[28,12206,12207],{},"PHP found a function call it does not know",[28,12209,12210],{},"Check spelling first",[28,12212,12213],{},"Then check whether the file that defines the function was included",[15,12215,12217,12220,12240],{"id":12216,"level":99},"debugging-loop",[20,12218,12219],{"id":12216},"Debugging Loop",[163,12221,12222,12225,12228,12231,12234,12237],{},[28,12223,12224],{},"Reproduce the issue",[28,12226,12227],{},"Read the newest error message",[28,12229,12230],{},"Identify file and line",[28,12232,12233],{},"Check that line and the line above it",[28,12235,12236],{},"Change one thing",[28,12238,12239],{},"Retest the same URL",[1927,12241,12243],{"type":12242},"warning",[41,12244,12245],{},"Change one thing, then retest. Several edits at once make it harder to know which line caused the new result.",[15,12247,12249,12252,12255,12258,12261],{"id":12248,"level":18},"predict-the-output",[20,12250,12251],{"id":12248},"Predict The Output",[41,12253,12254],{},"Before running this, decide what each line prints:",[884,12256],{"language":5325,"src":12257},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript\u002Fpredict-the-output-09.php",[41,12259,12260],{},"Then run it and compare.",[41,12262,12263],{},"The goal is to check assumptions with evidence rather than trying to memorize every conversion.",[15,12265,12267,12270],{"id":12266,"level":18},"knowledge-check",[20,12268,12269],{"id":12266},"Knowledge Check",[25,12271,12272,12278,12281,12284,12292,12295,12298,12305,12311,12316],{},[28,12273,12274,12275,12277],{},"Which language runs first when a ",[266,12276,10830],{}," page is requested?",[28,12279,12280],{},"Which tool shows PHP type and value?",[28,12282,12283],{},"Which tool shows JavaScript console output?",[28,12285,12286,12287,2328,12289,12291],{},"What is the difference between ",[266,12288,11330],{},[266,12290,18],{},"?",[28,12293,12294],{},"What does raw PHP in the browser usually mean?",[28,12296,12297],{},"What is the PHP operator for joining strings?",[28,12299,12300,12301,1201,12303,12291],{},"What does JavaScript have that PHP does not: ",[266,12302,11381],{},[266,12304,11425],{},[28,12306,12307,12308,12310],{},"Why can ",[266,12309,11634],{}," on a JavaScript array surprise beginners?",[28,12312,12313,12314,12291],{},"Why do PHP variables start with ",[266,12315,10912],{},[28,12317,12318],{},"Why should error reading start with the newest log entry?",[15,12320,12322,12326],{"id":12321,"level":18},"finish-lesson-branch",[20,12323,12325],{"id":12324},"finish-the-lesson-branch","Finish The Lesson Branch",[163,12327,12328,12333,12339,12345,12351,12359,12369],{},[28,12329,12330,12331],{},"Check the final file list: ",[266,12332,3856],{},[28,12334,12335,12336],{},"Stage the lesson work: ",[266,12337,12338],{},"git add public_html\u002Fm02\u002Flessons\u002F",[28,12340,12341,12342],{},"Commit the practice work: ",[266,12343,12344],{},"git commit -m \"Complete lesson practice\"",[28,12346,12347,12348],{},"Push the branch: ",[266,12349,12350],{},"git push origin Module02-PHP-vs-JS",[28,12352,12353,12354,6169,12356,12358],{},"On GitHub, open a pull request from ",[266,12355,10692],{},[266,12357,6416],{},", review it, then merge",[28,12360,12361,12362,12364,12365,6169,12367],{},"Briefly test ",[266,12363,6416],{},", then open and merge a pull request from ",[266,12366,6416],{},[266,12368,6419],{},[28,12370,12371,12372,12374,12375],{},"Prepare for the next lesson: ",[266,12373,6860],{}," then ",[266,12376,6865],{},[15,12378,12379,12381],{"id":466,"level":18},[20,12380,469],{"id":466},[25,12382,12383,12386,12389,12392,12395,12398],{},[28,12384,12385],{},"PHP runs on the server before the browser receives the response",[28,12387,12388],{},"JavaScript usually runs in the browser after the page loads",[28,12390,12391],{},"Output and inspection tools show different details depending on where the code runs",[28,12393,12394],{},"Type checks help explain why similar-looking values can behave differently",[28,12396,12397],{},"Error reading starts with the newest message, file path, and line number",[28,12399,12400,12401,2328,12403],{},"Lesson work should end with a reviewed branch merge through ",[266,12402,6416],{},[266,12404,6419],{},[15,12406,12407,12409],{"id":1463,"level":18},[20,12408,1456],{"id":1455},[104,12410,12411,12451],{"gap":106,"left-width":107,"right-width":107},[109,12412,12413,12415,12421,12427,12433,12439,12445],{"v-slot:left":111},[365,12414,1464],{"id":1463},[41,12416,12417,12420],{},[126,12418,12419],{},"Runtime"," - The place where code executes",[41,12422,12423,12426],{},[126,12424,12425],{},"Type"," - The kind of value, such as string, integer, boolean, array, or null",[41,12428,12429,12432],{},[126,12430,12431],{},"Console"," - Browser developer tool panel for JavaScript output",[41,12434,12435,12438],{},[126,12436,12437],{},"Strict comparison"," - Comparison that checks value and type",[41,12440,12441,12444],{},[126,12442,12443],{},"Undefined"," - JavaScript value used when a variable or property has no assigned value",[41,12446,12447,12450],{},[126,12448,12449],{},"Parse error"," - PHP could not understand the code structure",[109,12452,12453,12455],{"v-slot:right":111},[365,12454,1495],{"id":1452},[25,12456,12457,12464,12471,12478,12485,12492,12499],{},[28,12458,12459],{},[45,12460,12463],{"href":12461,"rel":12462},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Flanguage.basic-syntax.php",[49],"PHP Manual: Basic syntax",[28,12465,12466],{},[45,12467,12470],{"href":12468,"rel":12469},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Flanguage.types.type-juggling.php",[49],"PHP Manual: Type juggling",[28,12472,12473],{},[45,12474,12477],{"href":12475,"rel":12476},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Flanguage.operators.php",[49],"PHP Manual: Operators",[28,12479,12480],{},[45,12481,12484],{"href":12482,"rel":12483},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Flanguage.errors.php",[49],"PHP Manual: Errors",[28,12486,12487],{},[45,12488,12491],{"href":12489,"rel":12490},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FData_structures",[49],"MDN: JavaScript data types",[28,12493,12494],{},[45,12495,12498],{"href":12496,"rel":12497},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FOperators\u002Ftypeof",[49],"MDN: typeof",[28,12500,12501],{},[45,12502,12505],{"href":12503,"rel":12504},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FEquality_comparisons_and_sameness",[49],"MDN: Equality comparisons",{"title":111,"searchDepth":493,"depth":493,"links":12507},[12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12539,12540],{"id":10652,"depth":493,"text":10655},{"id":10675,"depth":493,"text":10678},{"id":10717,"depth":493,"text":10720},{"id":10755,"depth":493,"text":10756},{"id":10808,"depth":493,"text":10811},{"id":10878,"depth":493,"text":10881},{"id":10887,"depth":493,"text":10890},{"id":10953,"depth":493,"text":10731},{"id":11023,"depth":493,"text":11024},{"id":11106,"depth":493,"text":11107},{"id":11155,"depth":493,"text":11158},{"id":11247,"depth":493,"text":11248},{"id":11298,"depth":493,"text":11301},{"id":11345,"depth":493,"text":11346},{"id":11442,"depth":493,"text":11445},{"id":11500,"depth":493,"text":11503},{"id":11555,"depth":493,"text":11558},{"id":11615,"depth":493,"text":11616},{"id":11676,"depth":493,"text":11679},{"id":11721,"depth":493,"text":11724},{"id":11788,"depth":493,"text":11791},{"id":11952,"depth":493,"text":11955},{"id":12030,"depth":493,"text":12033},{"id":12059,"depth":493,"text":12060},{"id":12101,"depth":493,"text":12104},{"id":12144,"depth":493,"text":12145},{"id":12185,"depth":493,"text":12186},{"id":12216,"depth":493,"text":12219},{"id":12248,"depth":493,"text":12251},{"id":12266,"depth":493,"text":12269},{"id":12324,"depth":493,"text":12325},{"id":466,"depth":493,"text":469},{"id":1455,"depth":493,"text":1456},"Compare where PHP and JavaScript run, how each language stores and prints values, and how to read beginner PHP errors.","Face-to-face class of about 40 students; includes comparison prompts, short coding checks, browser output checks, and controlled debugging examples.",{},"\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript",{"title":10647,"description":12541},"internet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F01-compare-php-and-javascript",[5325,10784,12548,12549],"syntax","debugging","1:16:00","-tJOAgjl6XU","https:\u002F\u002Fyoutu.be\u002F-tJOAgjl6XU","Comparing PHP and JavaScript","sFnFWEQxWJ5G4aR3awi7HQRy4HpMeqT5B4JOTjWhUvI",{"id":12556,"title":12557,"audience":10,"body":12558,"contentType":509,"course":510,"description":13804,"estimateBasis":13805,"estimatedDiscussionMinutes":513,"estimatedLiveMinutes":13806,"estimatedTotalMinutes":13807,"extension":516,"meta":13808,"module":18,"navigation":519,"order":514,"path":13809,"promptAssist":522,"seo":13810,"status":524,"stem":13811,"tags":13812,"videoDuration":13816,"videoId":13817,"videoLink":13818,"videoTitle":13819,"week":18,"__hash__":13820},"content\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions.md","Use Conditions Loops And Functions",{"type":12,"value":12559,"toc":13763},[12560,12581,12613,12691,12723,12768,12813,12858,12898,12959,13005,13073,13111,13165,13209,13256,13297,13338,13377,13418,13448,13480,13500,13527,13557,13612,13655,13681],[15,12561,12562,12564],{"id":10652,"level":18},[20,12563,10655],{"id":10652},[25,12565,12566,12569,12572,12575,12578],{},[28,12567,12568],{},"Conditions choose which block runs",[28,12570,12571],{},"Loops repeat work until the pattern is finished",[28,12573,12574],{},"Functions name reusable logic",[28,12576,12577],{},"PHP and JavaScript use similar control-flow ideas with different syntax",[28,12579,12580],{},"In this lesson, compare the patterns before using them in practice files",[15,12582,12583,12585],{"id":10675,"level":18},[20,12584,10678],{"id":10675},[25,12586,12587,12591,12596,12598,12606,12609],{},[28,12588,10683,12589],{},[266,12590,10686],{},[28,12592,10689,12593],{},[266,12594,12595],{},"Module02-Control-Flow-Functions",[28,12597,10695],{},[28,12599,10698,12600,10702,12603],{},[266,12601,12602],{},"control-flow-",[266,12604,12605],{},"control-flow-even-odd.php",[28,12607,12608],{},"Keep each practice file focused on one idea",[28,12610,10711,12611,10714],{},[266,12612,3856],{},[15,12614,12616,12619],{"id":12615,"level":18},"loop-types",[20,12617,12618],{"id":12615},"Loop Types",[104,12620,12621,12656],{"gap":106,"left-width":107,"right-width":107},[109,12622,12623,12627],{"v-slot:left":111},[365,12624,12626],{"id":12625},"use-these-in-php","Use These In PHP",[25,12628,12629,12635,12641,12647,12653],{},[28,12630,12631,12634],{},[266,12632,12633],{},"for",": use when a counter, index, or fixed number of passes matters",[28,12636,12637,12640],{},[266,12638,12639],{},"while",": use when the loop should continue as long as a condition stays true",[28,12642,12643,12646],{},[266,12644,12645],{},"do while",": use when the body must run once before the condition is checked",[28,12648,12649,12652],{},[266,12650,12651],{},"foreach",": use when reading each array value or each key\u002Fvalue pair",[28,12654,12655],{},"Update loop variables inside the loop so it can finish",[109,12657,12658,12662],{"v-slot:right":111},[365,12659,12661],{"id":12660},"use-these-in-javascript","Use These In JavaScript",[25,12663,12664,12668,12672,12676,12682,12688],{},[28,12665,12666,12634],{},[266,12667,12633],{},[28,12669,12670,12640],{},[266,12671,12639],{},[28,12673,12674,12646],{},[266,12675,12645],{},[28,12677,12678,12681],{},[266,12679,12680],{},"for...of",": use for array values and other iterable values",[28,12683,12684,12687],{},[266,12685,12686],{},"for...in",": use for object keys or property names",[28,12689,12690],{},"Avoid loop conditions that can never become false",[15,12692,12694,12701],{"id":12693,"level":18},"for-vs-foreach",[20,12695,12696,12698,12699],{"id":12693},[266,12697,12633],{}," Vs ",[266,12700,12651],{},[104,12702,12703,12713],{"gap":106,"left-width":107,"right-width":107},[109,12704,12705,12710],{"v-slot:left":111},[41,12706,1150,12707,12709],{},[266,12708,12633],{}," when the counter matters:",[884,12711],{"language":5325,"src":12712},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Ffor-vs-foreach-06.php",[109,12714,12715,12720],{"v-slot:right":111},[41,12716,1150,12717,12719],{},[266,12718,12651],{}," when the values matter:",[884,12721],{"language":5325,"src":12722},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Ffor-vs-foreach-07.php",[15,12724,12726,12733],{"id":12725,"level":18},"while-and-do-while",[20,12727,12728,12730,12731],{"id":12725},[266,12729,12639],{}," And ",[266,12732,12645],{},[104,12734,12735,12742],{"gap":106,"left-width":107,"right-width":107},[109,12736,12737,12739],{"v-slot:left":111},[365,12738,4683],{"id":5325},[884,12740],{"language":5325,"src":12741},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fwhile-and-do-while-17.php",[109,12743,12744,12746,12749,12752],{"v-slot:right":111},[365,12745,10785],{"id":10784},[884,12747],{"language":10999,"src":12748},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fwhile-and-do-while-18.js",[41,12750,12751],{},"Both versions:",[25,12753,12754,12757,12760,12763],{},[28,12755,12756],{},"Start with a counter",[28,12758,12759],{},"Check a condition",[28,12761,12762],{},"Update the counter",[28,12764,12765,12767],{},[266,12766,12645],{}," runs at least once",[15,12769,12771,12778],{"id":12770,"level":18},"foreach-key-value",[20,12772,12774,12775,12777],{"id":12773},"php-foreach-key-and-value","PHP ",[266,12776,12651],{}," Key And Value",[104,12779,12780,12785],{"gap":106,"left-width":2255,"right-width":1710},[109,12781,12782],{"v-slot:left":111},[884,12783],{"language":5325,"src":12784},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fforeach-key-value-19.php",[109,12786,12787,12790],{"v-slot:right":111},[41,12788,12789],{},"Two common forms:",[25,12791,12792,12798,12804,12807,12810],{},[28,12793,12794,12797],{},[266,12795,12796],{},"foreach ($items as $value)",": use when each value is enough",[28,12799,12800,12803],{},[266,12801,12802],{},"foreach ($items as $key => $value)",": use when the key matters",[28,12805,12806],{},"Use key\u002Fvalue loops for associative arrays",[28,12808,12809],{},"Later database rows are arrays with column names as keys",[28,12811,12812],{},"Read values from the array; avoid changing the source array unless that is the point",[15,12814,12816,12824],{"id":12815,"level":18},"for-in-vs-for-of",[20,12817,12819,12820,12698,12822],{"id":12818},"javascript-forin-vs-forof","JavaScript ",[266,12821,12686],{},[266,12823,12680],{},[104,12825,12826,12831],{"gap":106,"left-width":2255,"right-width":1710},[109,12827,12828],{"v-slot:left":111},[884,12829],{"language":10999,"src":12830},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Ffor-in-vs-for-of-20.js",[109,12832,12833,12836],{"v-slot:right":111},[41,12834,12835],{},"Practical rule:",[25,12837,12838,12843,12848,12853],{},[28,12839,12840,12842],{},[266,12841,12680],{},": values from an array or iterable",[28,12844,12845,12847],{},[266,12846,12686],{},": keys or property names",[28,12849,1150,12850,12852],{},[266,12851,12680],{}," for most array value loops",[28,12854,12855,12857],{},[266,12856,12686],{}," can include custom properties",[15,12859,12861,12865],{"id":12860,"level":18},"modulo-and-loop",[20,12862,12864],{"id":12863},"even-and-odd-loop","Even And Odd Loop",[104,12866,12867,12872],{"gap":106,"left-width":107,"right-width":107},[109,12868,12869],{"v-slot:left":111},[884,12870],{"language":5325,"src":12871},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Feven-and-odd-loop-04.php",[109,12873,12874,12876,12879,12882],{"v-slot:right":111},[41,12875,2754],{},[884,12877],{"language":3665,"src":12878},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fexample-output-05.txt",[41,12880,12881],{},"Notes:",[25,12883,12884,12888,12893],{},[28,12885,12886,11835],{},[266,12887,11834],{},[28,12889,12890,12892],{},[266,12891,12651],{},": loop through each array value",[28,12894,12895,12897],{},[266,12896,11756],{},": compare value and type",[15,12899,12901,12904,12909],{"id":12900,"level":18},"loop-risk-examples",[20,12902,12903],{"id":12900},"Loop Risk Examples",[1927,12905,12906],{"type":12242},[41,12907,12908],{},"Read these as risk examples. Do not run them in a normal browser request unless the instructor explicitly asks you to test a controlled version.",[104,12910,12911,12936],{"gap":106,"left-width":107,"right-width":107},[109,12912,12913,12919,12922],{"v-slot:left":111},[365,12914,12916,12917],{"id":12915},"infinite-while","Infinite ",[266,12918,12639],{},[884,12920],{"language":5325,"src":12921},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Finfinite-while-example-25.php",[25,12923,12924,12927,12933],{},[28,12925,12926],{},"The condition starts true",[28,12928,12929,12932],{},[266,12930,12931],{},"true"," never becomes false",[28,12934,12935],{},"The page keeps printing until PHP stops the request",[109,12937,12938,12943,12946],{"v-slot:right":111},[365,12939,12916,12941],{"id":12940},"infinite-for",[266,12942,12633],{},[884,12944],{"language":5325,"src":12945},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Finfinite-for-example-26.php",[25,12947,12948,12954,12957],{},[28,12949,12950,12953],{},[266,12951,12952],{},"for (;;)"," has no setup, condition, or update sections",[28,12955,12956],{},"No condition means there is no planned stopping point",[28,12958,12935],{},[15,12960,12962,12965],{"id":12961,"level":99},"growing-array-loop",[20,12963,12964],{"id":12961},"Growing Array Loop",[104,12966,12967,12972],{"gap":106,"left-width":4857,"right-width":2665},[109,12968,12969],{"v-slot:left":111},[884,12970],{"language":5325,"src":12971},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fgrowing-array-loop-27.php",[109,12973,12974,12977],{"v-slot:right":111},[41,12975,12976],{},"Why this is dangerous:",[25,12978,12979,12985,12991,12999,13002],{},[28,12980,12981,12984],{},[266,12982,12983],{},"count($a)"," is recalculated on each pass",[28,12986,12987,12990],{},[266,12988,12989],{},"array_push($a, $i)"," makes the array longer",[28,12992,12993,2328,12996,12998],{},[266,12994,12995],{},"$i",[266,12997,12983],{}," both keep increasing",[28,13000,13001],{},"The loop does not reach a normal stopping point",[28,13003,13004],{},"It is not truly infinite because PHP eventually stops when memory or execution time runs out",[15,13006,13008,13011],{"id":13007,"level":18},"flow-control-summary",[20,13009,13010],{"id":13007},"Flow Control Summary",[104,13012,13013,13048],{"gap":106,"left-width":107,"right-width":107},[109,13014,13015,13019],{"v-slot:left":111},[365,13016,13018],{"id":13017},"decision-tools","Decision Tools",[25,13020,13021,13027,13036,13042],{},[28,13022,13023,13026],{},[266,13024,13025],{},"if",": run a block when a condition is true",[28,13028,13029,8754,13032,13035],{},[266,13030,13031],{},"elseif",[266,13033,13034],{},"else if",": test another condition",[28,13037,13038,13041],{},[266,13039,13040],{},"else",": fallback when no condition matched",[28,13043,13044,13047],{},[266,13045,13046],{},"switch",": compare one value to several cases",[109,13049,13050,13054],{"v-slot:right":111},[365,13051,13053],{"id":13052},"risk-to-watch","Risk To Watch",[25,13055,13056,13059,13062,13070],{},[28,13057,13058],{},"First matching branch wins",[28,13060,13061],{},"Bad branch order can create dead code",[28,13063,13064,13066,13067],{},[266,13065,13046],{}," can fall through without ",[266,13068,13069],{},"break",[28,13071,13072],{},"Predict the output before running the page",[15,13074,13076,13079],{"id":13075,"level":18},"condition-example",[20,13077,13078],{"id":13075},"Condition Example",[104,13080,13081,13086],{"gap":106,"left-width":107,"right-width":107},[109,13082,13083],{"v-slot:left":111},[884,13084],{"language":5325,"src":13085},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fcondition-example-01.php",[109,13087,13088,13090,13093,13095],{"v-slot:right":111},[41,13089,2754],{},[884,13091],{"language":3665,"src":13092},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fexample-output-02.txt",[41,13094,12881],{},[25,13096,13097,13100,13103,13106],{},[28,13098,13099],{},"First true branch runs",[28,13101,13102],{},"Later branches are skipped",[28,13104,13105],{},"Branch order matters",[28,13107,13108,13110],{},[266,13109,13031],{}," is checked only if earlier checks failed",[15,13112,13114,13117],{"id":13113,"level":18},"comparison-risk",[20,13115,13116],{"id":13113},"Comparison Risk",[104,13118,13119,13124],{"gap":106,"left-width":107,"right-width":107},[109,13120,13121],{"v-slot:left":111},[884,13122],{"language":5325,"src":13123},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fcomparison-risk-03.php",[109,13125,13126,13129,13148,13151],{"v-slot:right":111},[41,13127,13128],{},"Problem:",[25,13130,13131,13139,13142],{},[28,13132,13133,13135,13136],{},[266,13134,10629],{}," is already ",[266,13137,13138],{},">= 60",[28,13140,13141],{},"First branch catches it",[28,13143,13144,13147],{},[266,13145,13146],{},"Excellent"," can never print",[41,13149,13150],{},"Correction:",[25,13152,13153,13156,13159],{},[28,13154,13155],{},"Check the most specific condition first",[28,13157,13158],{},"Use the broad fallback later",[28,13160,13161,13162,13164],{},"The skipped ",[266,13163,13146],{}," branch is dead code because the earlier branch catches the value first",[15,13166,13168,13173],{"id":13167,"level":18},"switch-example",[20,13169,13170,13172],{"id":13167},[266,13171,13046],{}," Example",[104,13174,13175,13180],{"gap":106,"left-width":107,"right-width":107},[109,13176,13177],{"v-slot:left":111},[884,13178],{"language":5325,"src":13179},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fswitch-example-15.php",[109,13181,13182,13184],{"v-slot:right":111},[41,13183,11260],{},[25,13185,13186,13191,13196,13202],{},[28,13187,13188,13190],{},[266,13189,13046],{}," compares one value against several cases",[28,13192,13193,13195],{},[266,13194,13069],{}," stops fall-through into the next case",[28,13197,13198,13201],{},[266,13199,13200],{},"default"," is the fallback",[28,13203,1150,13204,11828,13206,13208],{},[266,13205,13025],{},[266,13207,13031],{}," when each condition checks something different",[15,13210,13212,13221],{"id":13211,"level":18},"switch-fallthrough",[20,13213,13215,13216,13218,13219],{"id":13214},"missing-break-in-switch","Missing ",[266,13217,13069],{}," In ",[266,13220,13046],{},[104,13222,13223,13228],{"gap":106,"left-width":107,"right-width":107},[109,13224,13225],{"v-slot:left":111},[884,13226],{"language":5325,"src":13227},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fswitch-fallthrough-16.php",[109,13229,13230,13233],{"v-slot:right":111},[41,13231,13232],{},"Prediction:",[25,13234,13235,13241,13247,13253],{},[28,13236,13237,13240],{},[266,13238,13239],{},"Monday"," matches the first case",[28,13242,13243,13244,13246],{},"No ",[266,13245,13069],{}," means execution continues",[28,13248,13249,13252],{},[266,13250,13251],{},"Tuesday"," also prints",[28,13254,13255],{},"Fall-through is sometimes intentional, but only use it when you mean to group cases",[15,13257,13259,13266],{"id":13258,"level":18},"break-and-continue",[20,13260,13261,12730,13263],{"id":13258},[266,13262,13069],{},[266,13264,13265],{},"continue",[104,13267,13268,13273],{"gap":106,"left-width":107,"right-width":107},[109,13269,13270],{"v-slot:left":111},[884,13271],{"language":5325,"src":13272},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fbreak-and-continue-08.php",[109,13274,13275,13277,13280,13282],{"v-slot:right":111},[41,13276,2754],{},[884,13278],{"language":3665,"src":13279},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fexample-output-09.txt",[41,13281,12881],{},[25,13283,13284,13289,13294],{},[28,13285,13286,13288],{},[266,13287,13265],{},": skip the rest of this loop pass",[28,13290,13291,13293],{},[266,13292,13069],{},": stop the loop completely",[28,13295,13296],{},"Use sparingly so the loop still reads clearly",[15,13298,13300,13308],{"id":13299,"level":18},"break-continue-js",[20,13301,13303,12730,13305,13307],{"id":13302},"break-and-continue-in-javascript",[266,13304,13069],{},[266,13306,13265],{}," In JavaScript",[104,13309,13310,13315],{"gap":106,"left-width":107,"right-width":107},[109,13311,13312],{"v-slot:left":111},[884,13313],{"language":10999,"src":13314},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fbreak-continue-js-21.js",[109,13316,13317,13320],{"v-slot:right":111},[41,13318,13319],{},"Same control idea:",[25,13321,13322,13327,13332,13335],{},[28,13323,13324,13326],{},[266,13325,13265],{},": skip this pass",[28,13328,13329,13331],{},[266,13330,13069],{},": exit the loop",[28,13333,13334],{},"Use both carefully so the loop still reads clearly",[28,13336,13337],{},"The same ideas appear in PHP and JavaScript",[15,13339,13341,13344],{"id":13340,"level":18},"function-example",[20,13342,13343],{"id":13340},"Function Example",[104,13345,13346,13351],{"gap":106,"left-width":107,"right-width":107},[109,13347,13348],{"v-slot:left":111},[884,13349],{"language":5325,"src":13350},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Ffunction-example-10.php",[109,13352,13353,13355,13358,13360],{"v-slot:right":111},[41,13354,2754],{},[884,13356],{"language":3665,"src":13357},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fexample-output-11.txt",[41,13359,12881],{},[25,13361,13362,13365,13368,13374],{},[28,13363,13364],{},"Function name describes the reusable job",[28,13366,13367],{},"Parameters are inputs",[28,13369,13370,13373],{},[266,13371,13372],{},"return"," sends a value back",[28,13375,13376],{},"Type hints document expected values",[15,13378,13380,13384],{"id":13379,"level":18},"same-idea-javascript",[20,13381,13383],{"id":13382},"same-idea-in-javascript","Same Idea In JavaScript",[104,13385,13386,13391],{"gap":106,"left-width":107,"right-width":107},[109,13387,13388],{"v-slot:left":111},[884,13389],{"language":10999,"src":13390},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fsame-idea-in-javascript-12.js",[109,13392,13393,13396,13407,13410],{"v-slot:right":111},[41,13394,13395],{},"Same idea:",[25,13397,13398,13401,13404],{},[28,13399,13400],{},"Function accepts inputs",[28,13402,13403],{},"Function returns one result",[28,13405,13406],{},"Output goes to the browser console here",[41,13408,13409],{},"Different runtime:",[25,13411,13412,13415],{},[28,13413,13414],{},"PHP prints into the server response",[28,13416,13417],{},"JavaScript runs after the browser receives the page",[15,13419,13421,13424,13427,13443],{"id":13420,"level":18},"debugging-flow",[20,13422,13423],{"id":13420},"Debugging Flow",[41,13425,13426],{},"When output is wrong:",[163,13428,13429,13432,13435,13438,13440],{},[28,13430,13431],{},"Print the input value",[28,13433,13434],{},"Print the type if text\u002Fnumber confusion is possible",[28,13436,13437],{},"Test one condition or loop boundary",[28,13439,12236],{},[28,13441,13442],{},"Refresh or rerun",[1927,13444,13445],{"type":12242},[41,13446,13447],{},"Change one thing, then retest. Rewriting the whole example makes it harder to know which line caused the new result.",[15,13449,13451,13454],{"id":13450,"level":18},"built-in-functions-practice",[20,13452,13453],{"id":13450},"Built-in Functions Practice",[25,13455,13456,13462,13468,13474,13477],{},[28,13457,13458,13461],{},[266,13459,13460],{},"abs()",": Work with distance from zero",[28,13463,13464,13467],{},[266,13465,13466],{},"number_format()",": Display a number with a fixed number of decimal places",[28,13469,13470,13473],{},[266,13471,13472],{},"preg_replace()",": Replace text that matches a regular expression",[28,13475,13476],{},"These helpers are useful in practice work, but the exact project logic depends on the task",[28,13478,13479],{},"See the slides below for small examples of each helper",[15,13481,13483,13487,13490],{"id":13482,"level":99},"abs-example",[20,13484,13485,13172],{"id":13482},[266,13486,13460],{},[884,13488],{"language":5325,"src":13489},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fabs-example-22.php",[25,13491,13492,13497],{},[28,13493,13494,13496],{},[266,13495,13460],{}," returns the positive distance from zero",[28,13498,13499],{},"This is useful when only the size of the difference matters",[15,13501,13503,13508,13511],{"id":13502,"level":99},"number-format-example",[20,13504,13506,13172],{"id":13505},"number_format-example",[266,13507,13466],{},[884,13509],{"language":5325,"src":13510},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fnumber-format-example-23.php",[25,13512,13513,13518,13524],{},[28,13514,13515,13517],{},[266,13516,13466],{}," returns display text",[28,13519,13520,13521],{},"Crypto-style values often need more decimal places, such as ",[266,13522,13523],{},"8",[28,13525,13526],{},"Add the transaction first, then format the final display value",[15,13528,13530,13535,13538],{"id":13529,"level":99},"preg-replace-example",[20,13531,13533,13172],{"id":13532},"preg_replace-example",[266,13534,13472],{},[884,13536],{"language":5325,"src":13537},"\u002Fgenerated-snippets\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions\u002Fpreg-replace-example-24.php",[25,13539,13540,13545,13548,13551,13554],{},[28,13541,13542,13544],{},[266,13543,13472],{}," changes text that matches a pattern",[28,13546,13547],{},"This example changes spaces to hyphens",[28,13549,13550],{},"It also changes hyphens back to spaces",[28,13552,13553],{},"Use a different pattern when the allowed text rules are different",[28,13555,13556],{},"Regular expressions will be covered separately later",[15,13558,13559,13561],{"id":12266,"level":18},[20,13560,12269],{"id":12266},[25,13562,13563,13569,13574,13582,13588,13596,13603,13609],{},[28,13564,13565,13566,13568],{},"Which branch runs first in an ",[266,13567,13025],{}," chain?",[28,13570,13571,13572,13568],{},"What is dead code in an ",[266,13573,13025],{},[28,13575,13576,13577,13579,13580,12291],{},"Why does a ",[266,13578,13046],{}," case usually need ",[266,13581,13069],{},[28,13583,13584,13585,13587],{},"What does ",[266,13586,11834],{}," tell you?",[28,13589,13590,13591,13593,13594,12291],{},"When is ",[266,13592,12651],{}," cleaner than ",[266,13595,12633],{},[28,13597,13598,13599,2328,13601,12291],{},"What is the difference between JavaScript ",[266,13600,12686],{},[266,13602,12680],{},[28,13604,12286,13605,2328,13607,12291],{},[266,13606,13069],{},[266,13608,13265],{},[28,13610,13611],{},"Why move repeated logic into a function?",[15,13613,13614,13616],{"id":12321,"level":18},[20,13615,12325],{"id":12324},[163,13617,13618,13622,13626,13630,13635,13641,13649],{},[28,13619,12330,13620],{},[266,13621,3856],{},[28,13623,12335,13624],{},[266,13625,12338],{},[28,13627,12341,13628],{},[266,13629,12344],{},[28,13631,12347,13632],{},[266,13633,13634],{},"git push origin Module02-Control-Flow-Functions",[28,13636,12353,13637,6169,13639,12358],{},[266,13638,12595],{},[266,13640,6416],{},[28,13642,12361,13643,12364,13645,6169,13647],{},[266,13644,6416],{},[266,13646,6416],{},[266,13648,6419],{},[28,13650,12371,13651,12374,13653],{},[266,13652,6860],{},[266,13654,6865],{},[15,13656,13657,13659],{"id":466,"level":18},[20,13658,469],{"id":466},[25,13660,13661,13664,13667,13672,13675,13678],{},[28,13662,13663],{},"Conditions choose between branches",[28,13665,13666],{},"Loop choice depends on whether the counter, condition, value, or key matters",[28,13668,13669,13671],{},[266,13670,12651],{}," is the normal PHP choice for reading array values",[28,13673,13674],{},"Functions make repeated logic easier to test and reuse",[28,13676,13677],{},"Small helper functions can prepare numbers or text before output",[28,13679,13680],{},"Debug control-flow problems by checking one input, one condition, or one loop boundary at a time",[15,13682,13683,13685],{"id":1463,"level":18},[20,13684,1456],{"id":1455},[104,13686,13687,13715],{"gap":106,"left-width":107,"right-width":107},[109,13688,13689,13691,13697,13703,13709],{"v-slot:left":111},[365,13690,1464],{"id":1463},[41,13692,13693,13696],{},[126,13694,13695],{},"Condition"," - A true\u002Ffalse check that controls which code runs",[41,13698,13699,13702],{},[126,13700,13701],{},"Loop"," - Code that repeats while a pattern continues",[41,13704,13705,13708],{},[126,13706,13707],{},"Dead code"," - Code that cannot run because earlier logic prevents it",[41,13710,13711,13714],{},[126,13712,13713],{},"Function"," - Named reusable logic with optional inputs and a result",[109,13716,13717,13719],{"v-slot:right":111},[365,13718,1495],{"id":1452},[25,13720,13721,13728,13735,13742,13749,13756],{},[28,13722,13723],{},[45,13724,13727],{"href":13725,"rel":13726},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Fcontrol-structures.if.php",[49],"PHP Manual: if",[28,13729,13730],{},[45,13731,13734],{"href":13732,"rel":13733},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Fcontrol-structures.foreach.php",[49],"PHP Manual: foreach",[28,13736,13737],{},[45,13738,13741],{"href":13739,"rel":13740},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Fcontrol-structures.switch.php",[49],"PHP Manual: switch",[28,13743,13744],{},[45,13745,13748],{"href":13746,"rel":13747},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FLoops_and_iteration",[49],"MDN: Loops and iteration",[28,13750,13751],{},[45,13752,13755],{"href":13753,"rel":13754},"https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Ffunctions.user-defined.php",[49],"PHP Manual: functions",[28,13757,13758],{},[45,13759,13762],{"href":13760,"rel":13761},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FFunctions",[49],"MDN: JavaScript functions",{"title":111,"searchDepth":493,"depth":493,"links":13764},[13765,13766,13767,13768,13770,13772,13774,13776,13777,13778,13779,13780,13781,13782,13784,13786,13788,13790,13791,13792,13793,13794,13796,13798,13800,13801,13802,13803],{"id":10652,"depth":493,"text":10655},{"id":10675,"depth":493,"text":10678},{"id":12615,"depth":493,"text":12618},{"id":12693,"depth":493,"text":13769},"for Vs foreach",{"id":12725,"depth":493,"text":13771},"while And do while",{"id":12773,"depth":493,"text":13773},"PHP foreach Key And Value",{"id":12818,"depth":493,"text":13775},"JavaScript for...in Vs for...of",{"id":12863,"depth":493,"text":12864},{"id":12900,"depth":493,"text":12903},{"id":12961,"depth":493,"text":12964},{"id":13007,"depth":493,"text":13010},{"id":13075,"depth":493,"text":13078},{"id":13113,"depth":493,"text":13116},{"id":13167,"depth":493,"text":13783},"switch Example",{"id":13214,"depth":493,"text":13785},"Missing break In switch",{"id":13258,"depth":493,"text":13787},"break And continue",{"id":13302,"depth":493,"text":13789},"break And continue In JavaScript",{"id":13340,"depth":493,"text":13343},{"id":13382,"depth":493,"text":13383},{"id":13420,"depth":493,"text":13423},{"id":13450,"depth":493,"text":13453},{"id":13482,"depth":493,"text":13795},"abs() Example",{"id":13505,"depth":493,"text":13797},"number_format() Example",{"id":13532,"depth":493,"text":13799},"preg_replace() Example",{"id":12266,"depth":493,"text":12269},{"id":12324,"depth":493,"text":12325},{"id":466,"depth":493,"text":469},{"id":1455,"depth":493,"text":1456},"Practice decisions, repetition, and reusable logic with small PHP and JavaScript examples that produce visible output.","Face-to-face class of about 40 students; includes prediction prompts, short coding checks, debugging discussion, and comparison between PHP and JavaScript.","65","75",{},"\u002Finternet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions",{"title":12557,"description":13804},"internet-applications\u002Fpresentations\u002F02-php-and-javascript-basics\u002F02-conditions-loops-functions",[5325,13813,13814,13815],"conditions","loops","functions","1:01:13","aTmU0kABQms","https:\u002F\u002Fyoutu.be\u002FaTmU0kABQms","Conditions Loops and Functions","qaCmjtbulmPmiFJ-F5imZHK9Q2JoKEDvzB78n7TlMWk",1780581685657]