aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--.well-known/button.json13
-rw-r--r--.well-known/fursona19
-rw-r--r--LICENSE57
-rw-r--r--README.md5
-rw-r--r--about/bg.jpgbin0 -> 442443 bytes
-rw-r--r--about/bg.jxlbin0 -> 482705 bytes
-rw-r--r--about/images/crackship_quiz_result.pngbin0 -> 24970 bytes
-rw-r--r--about/images/isopod_quiz_result.pngbin0 -> 11140 bytes
-rw-r--r--about/index.php138
-rw-r--r--blog/bg.jpgbin0 -> 910875 bytes
-rw-r--r--blog/bg.jxlbin0 -> 651503 bytes
-rw-r--r--blog/blog.atom247
-rw-r--r--blog/comment/comments.css92
-rw-r--r--blog/comment/feed.php29
-rw-r--r--blog/comment/index.php40
-rw-r--r--blog/comment/submit.php81
-rw-r--r--blog/index.php164
-rw-r--r--blog/media/banner-statuscafe.pngbin0 -> 832 bytes
-rw-r--r--blog/posts/ai_art/index.md76
-rw-r--r--blog/posts/ai_art/index.php1
-rw-r--r--blog/posts/building_a_normal_server/index.md174
-rw-r--r--blog/posts/building_a_normal_server/index.php1
-rw-r--r--blog/posts/building_a_normal_server/media/2023-11-20_contraption.mp4bin0 -> 431696506 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jpgbin0 -> 225783 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jxlbin0 -> 155972 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/ChenYang.jpgbin0 -> 60326 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/ChenYang.jxlbin0 -> 74743 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/ECS07.jpgbin0 -> 93965 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/ECS07.jxlbin0 -> 35545 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/bare_frame.jpgbin0 -> 393312 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/bare_frame.jxlbin0 -> 362631 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/drive_spaghet.jpgbin0 -> 452166 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/drive_spaghet.jxlbin0 -> 385807 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jpgbin0 -> 658802 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jxlbin0 -> 556921 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/fully_assembled.jpgbin0 -> 457500 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/fully_assembled.jxlbin0 -> 405078 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/m2_slot.jpgbin0 -> 311224 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/m2_slot.jxlbin0 -> 224030 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/partially_assembled_1.jpgbin0 -> 290042 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/partially_assembled_1.jxlbin0 -> 270957 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/partially_assembled_2.jpgbin0 -> 285405 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/partially_assembled_2.jxlbin0 -> 256847 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/pcie_slots.jpgbin0 -> 310128 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/pcie_slots.jxlbin0 -> 235558 bytes
-rw-r--r--blog/posts/building_a_normal_server/media/power_spaghet.pngbin0 -> 45454 bytes
-rw-r--r--blog/posts/building_a_sensible_server/ebaypoweredge.pngbin0 -> 541642 bytes
-rw-r--r--blog/posts/building_a_sensible_server/index.md142
-rw-r--r--blog/posts/building_a_sensible_server/index.php1
-rw-r--r--blog/posts/building_a_sensible_server/nictua.jpgbin0 -> 242887 bytes
-rw-r--r--blog/posts/building_a_sensible_server/servercase.jpgbin0 -> 148090 bytes
-rw-r--r--blog/posts/building_a_sensible_server/servercaseinside.jpgbin0 -> 335938 bytes
-rw-r--r--blog/posts/building_a_sensible_server/servercaseinsidefront.jpgbin0 -> 424991 bytes
-rw-r--r--blog/posts/building_a_sensible_server/ziptiemount.jpgbin0 -> 156703 bytes
-rw-r--r--blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/background.pngbin0 -> 1237600 bytes
-rw-r--r--blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.md87
-rw-r--r--blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.php1
-rw-r--r--blog/posts/discord/discord-no-way-2.gifbin0 -> 1961 bytes
-rw-r--r--blog/posts/discord/discord.pngbin0 -> 13432 bytes
-rw-r--r--blog/posts/discord/federation.pngbin0 -> 130233 bytes
-rw-r--r--blog/posts/discord/index.md204
-rw-r--r--blog/posts/discord/index.php1
-rw-r--r--blog/posts/fediverse_dms/bg.svg17
-rw-r--r--blog/posts/fediverse_dms/index.md19
-rw-r--r--blog/posts/fediverse_dms/index.php1
-rw-r--r--blog/posts/foodhero/index.md3
-rw-r--r--blog/posts/foodhero/index.php1
-rw-r--r--blog/posts/guide_blacklist_websites_searxng/index.md21
-rw-r--r--blog/posts/guide_blacklist_websites_searxng/index.php1
-rw-r--r--blog/posts/guide_blacklist_websites_searxng/searxng.svg19
-rw-r--r--blog/posts/guide_blocking_user_agents_nginx/bg.svg2
-rw-r--r--blog/posts/guide_blocking_user_agents_nginx/index.md73
-rw-r--r--blog/posts/guide_blocking_user_agents_nginx/index.php1
-rw-r--r--blog/posts/guide_fix_youtube_buffering_firefox/bg.svg8
-rw-r--r--blog/posts/guide_fix_youtube_buffering_firefox/index.md15
-rw-r--r--blog/posts/guide_fix_youtube_buffering_firefox/index.php1
-rw-r--r--blog/posts/guide_fix_youtube_buffering_firefox/what_they_took_from_you.pngbin0 -> 111068 bytes
-rw-r--r--blog/posts/guide_how_to_automount_drives_on_boot_in_linux/fstab.pngbin0 -> 21466 bytes
-rw-r--r--blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.md78
-rw-r--r--blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.php1
-rw-r--r--blog/posts/guide_pihole_lepotato/bg.pngbin0 -> 13792 bytes
-rw-r--r--blog/posts/guide_pihole_lepotato/index.md77
-rw-r--r--blog/posts/guide_pihole_lepotato/index.php1
-rw-r--r--blog/posts/guide_self_host_safely_with_wireguard/index.php84
-rw-r--r--blog/posts/guide_self_host_safely_with_wireguard/wireguard_logo.pngbin0 -> 12772 bytes
-rw-r--r--blog/posts/guide_things_i_keep_having_to_google/index.php126
-rw-r--r--blog/posts/how_my_blog_works/index.md0
-rw-r--r--blog/posts/how_my_blog_works/index.php1
-rw-r--r--blog/posts/make_your_own_cables/2pindin.jpgbin0 -> 44061 bytes
-rw-r--r--blog/posts/make_your_own_cables/4pinminixlr.pngbin0 -> 60880 bytes
-rw-r--r--blog/posts/make_your_own_cables/homebrew2pindincable.jpgbin0 -> 4023505 bytes
-rw-r--r--blog/posts/make_your_own_cables/homebrewxlrcablefinished.jpgbin0 -> 2561659 bytes
-rw-r--r--blog/posts/make_your_own_cables/index.md37
-rw-r--r--blog/posts/make_your_own_cables/index.php1
-rw-r--r--blog/posts/my_terrible_distro_hop/bg.pngbin0 -> 406989 bytes
-rw-r--r--blog/posts/my_terrible_distro_hop/index.md116
-rw-r--r--blog/posts/my_terrible_distro_hop/index.php1
-rw-r--r--blog/posts/post.php105
-rw-r--r--blog/posts/renting_an_unremarkable_server/index.md40
-rw-r--r--blog/posts/renting_an_unremarkable_server/index.php1
-rw-r--r--blog/posts/toshiba_chromebook/chromebook.jpgbin0 -> 121656 bytes
-rw-r--r--blog/posts/toshiba_chromebook/index.md46
-rw-r--r--blog/posts/toshiba_chromebook/index.php1
-rw-r--r--blog/posts/unity_runtime_fee_and_proprietary_software/bg.svg22
-rw-r--r--blog/posts/unity_runtime_fee_and_proprietary_software/devprotest.pngbin0 -> 8970706 bytes
-rw-r--r--blog/posts/unity_runtime_fee_and_proprietary_software/index.md55
-rw-r--r--blog/posts/unity_runtime_fee_and_proprietary_software/index.php1
-rw-r--r--chromealert.php21
-rw-r--r--deeptwisty.pngbin0 -> 1763 bytes
-rw-r--r--etc/bg.jpgbin0 -> 419224 bytes
-rw-r--r--etc/bg.jxlbin0 -> 164764 bytes
-rw-r--r--etc/buttons/35mm.gifbin0 -> 3747 bytes
-rw-r--r--etc/buttons/ace.pngbin0 -> 656 bytes
-rw-r--r--etc/buttons/agender.pngbin0 -> 6523 bytes
-rw-r--r--etc/buttons/amd_powered.gifbin0 -> 706 bytes
-rw-r--r--etc/buttons/antinft.gifbin0 -> 1669 bytes
-rw-r--r--etc/buttons/aro.pngbin0 -> 6180 bytes
-rw-r--r--etc/buttons/aromantic-80x15.pngbin0 -> 598 bytes
-rw-r--r--etc/buttons/asexual-80x15.pngbin0 -> 2379 bytes
-rw-r--r--etc/buttons/badhtml.pngbin0 -> 1247 bytes
-rw-r--r--etc/buttons/bantimetravel.pngbin0 -> 3223 bytes
-rw-r--r--etc/buttons/bestviewed.gifbin0 -> 9419 bytes
-rw-r--r--etc/buttons/canadian.gifbin0 -> 4083 bytes
-rw-r--r--etc/buttons/chrome.gifbin0 -> 8964 bytes
-rw-r--r--etc/buttons/css.pngbin0 -> 3176 bytes
-rw-r--r--etc/buttons/deeptwisty_button.pngbin0 -> 4676 bytes
-rw-r--r--etc/buttons/dontclick.gifbin0 -> 3687 bytes
-rw-r--r--etc/buttons/dontyouhate.gifbin0 -> 3987 bytes
-rw-r--r--etc/buttons/drpepper.gifbin0 -> 2412 bytes
-rw-r--r--etc/buttons/epicblazed.pngbin0 -> 3433 bytes
-rw-r--r--etc/buttons/floof_explode_88x31.gifbin0 -> 37149 bytes
-rw-r--r--etc/buttons/getvlcnow.pngbin0 -> 14305 bytes
-rw-r--r--etc/buttons/google_stand.gifbin0 -> 21247 bytes
-rw-r--r--etc/buttons/handcode.pngbin0 -> 6504 bytes
-rw-r--r--etc/buttons/i_hate_microsoft.pngbin0 -> 2957 bytes
-rw-r--r--etc/buttons/isopodhours.pngbin0 -> 6331 bytes
-rw-r--r--etc/buttons/krisbtn.pngbin0 -> 1146 bytes
-rw-r--r--etc/buttons/linux_powered.gifbin0 -> 14619 bytes
-rw-r--r--etc/buttons/neocities_stamp.gifbin0 -> 2431 bytes
-rw-r--r--etc/buttons/niceopod_button.pngbin0 -> 5163 bytes
-rw-r--r--etc/buttons/niceopod_button_2.pngbin0 -> 4664 bytes
-rw-r--r--etc/buttons/nonbinary-80x15.pngbin0 -> 593 bytes
-rw-r--r--etc/buttons/nonbinary.pngbin0 -> 196 bytes
-rw-r--r--etc/buttons/notoweb3.gifbin0 -> 483 bytes
-rw-r--r--etc/buttons/nowebp.gifbin0 -> 7372 bytes
-rw-r--r--etc/buttons/piracy.gifbin0 -> 910 bytes
-rw-r--r--etc/buttons/queercoded.pngbin0 -> 4500 bytes
-rw-r--r--etc/buttons/righttorepair.pngbin0 -> 6203 bytes
-rw-r--r--etc/buttons/shrimp.pngbin0 -> 1545 bytes
-rw-r--r--etc/buttons/smokepowered.gifbin0 -> 999 bytes
-rw-r--r--etc/buttons/svg.svg76
-rw-r--r--etc/buttons/tested_on_firefox.gifbin0 -> 2754 bytes
-rw-r--r--etc/buttons/the_void.gifbin0 -> 1609 bytes
-rw-r--r--etc/buttons/trans.pngbin0 -> 250 bytes
-rw-r--r--etc/buttons/usatoday.gifbin0 -> 5717 bytes
-rw-r--r--etc/buttons/web-pi.pngbin0 -> 1857 bytes
-rw-r--r--etc/buttons/win11no.gifbin0 -> 1691 bytes
-rw-r--r--etc/images/apiopage.pngbin0 -> 8589 bytes
-rw-r--r--etc/index.php92
-rw-r--r--etc/quotes/bg.jpgbin0 -> 172455 bytes
-rw-r--r--etc/quotes/bg.jxlbin0 -> 81156 bytes
-rw-r--r--etc/quotes/images/c_pfp.pngbin0 -> 3122 bytes
-rw-r--r--etc/quotes/images/g_pfp.pngbin0 -> 1684 bytes
-rw-r--r--etc/quotes/images/h_pfp.pngbin0 -> 1434 bytes
-rw-r--r--etc/quotes/images/j_pfp.pngbin0 -> 5182 bytes
-rw-r--r--etc/quotes/images/m_pfp.pngbin0 -> 3406 bytes
-rw-r--r--etc/quotes/images/p_pfp.pngbin0 -> 1672 bytes
-rw-r--r--etc/quotes/images/s_pfp.pngbin0 -> 2350 bytes
-rw-r--r--etc/quotes/images/t_pfp.pngbin0 -> 11460 bytes
-rw-r--r--etc/quotes/images/v_pfp.pngbin0 -> 1906 bytes
-rw-r--r--etc/quotes/index.php409
-rw-r--r--favicon.icobin0 -> 28838 bytes
-rw-r--r--favicon.pngbin0 -> 8057 bytes
-rw-r--r--greenhouse/bg.jpgbin0 -> 539379 bytes
-rw-r--r--greenhouse/bg.jxlbin0 -> 454813 bytes
-rw-r--r--greenhouse/index.php62
-rw-r--r--guestbook/bg.jpgbin0 -> 1184070 bytes
-rw-r--r--guestbook/bg.jxlbin0 -> 664811 bytes
-rw-r--r--guestbook/feed.php47
-rw-r--r--guestbook/index.php244
-rw-r--r--guestbook/submit.php87
-rw-r--r--images/Ophiocordyceps_unilateralis.pngbin0 -> 30142 bytes
-rw-r--r--images/benlet1.pngbin0 -> 263 bytes
-rw-r--r--images/bg.jpgbin0 -> 303826 bytes
-rw-r--r--images/bg.jxlbin0 -> 130798 bytes
-rw-r--r--images/birthday_isopod.pngbin0 -> 27073 bytes
-rw-r--r--images/birthday_isopod_small.pngbin0 -> 13828 bytes
-rw-r--r--images/blahaj.pngbin0 -> 153065 bytes
-rw-r--r--images/bubblecolumn1.gifbin0 -> 17577 bytes
-rw-r--r--images/casiopea_isopod.pngbin0 -> 4853 bytes
-rw-r--r--images/deeptwisty.pngbin0 -> 1763 bytes
-rw-r--r--images/flatworm friday 1.mp4bin0 -> 16179927 bytes
-rw-r--r--images/flatworm friday 2.mp4bin0 -> 4262901 bytes
-rw-r--r--images/fry.pngbin0 -> 5084 bytes
-rw-r--r--images/isopod.php15
-rw-r--r--images/isopod3.pngbin0 -> 408 bytes
-rw-r--r--images/isopod_with_aviators.pngbin0 -> 25897 bytes
-rw-r--r--images/isopod_with_aviators_small.pngbin0 -> 13301 bytes
-rw-r--r--images/isopumpkin.pngbin0 -> 22949 bytes
-rw-r--r--images/isopumpkin_small.pngbin0 -> 13576 bytes
-rw-r--r--images/new.gifbin0 -> 926 bytes
-rw-r--r--images/place_him.pngbin0 -> 3631 bytes
-rw-r--r--images/plant1-2.pngbin0 -> 13422 bytes
-rw-r--r--images/shadow.pngbin0 -> 18598 bytes
-rw-r--r--images/spruce_planks.pngbin0 -> 5709 bytes
-rw-r--r--images/wobble_mc_house_bg.pngbin0 -> 1610661 bytes
-rw-r--r--index.php380
-rw-r--r--links/bg.jpgbin0 -> 27376 bytes
-rw-r--r--links/bg.jxlbin0 -> 17032 bytes
-rw-r--r--links/buttons/64thsanctum.gifbin0 -> 101413 bytes
-rw-r--r--links/buttons/Icelog.gifbin0 -> 933 bytes
-rw-r--r--links/buttons/corru.gifbin0 -> 123640 bytes
-rw-r--r--links/buttons/josef.gifbin0 -> 4306 bytes
-rw-r--r--links/buttons/kalechips.pngbin0 -> 7878 bytes
-rw-r--r--links/buttons/kopper.pngbin0 -> 1109 bytes
-rw-r--r--links/buttons/melonland-forum.gifbin0 -> 5342 bytes
-rw-r--r--links/buttons/morrysillusion.pngbin0 -> 931 bytes
-rw-r--r--links/buttons/moth-88x31.svg12
-rw-r--r--links/buttons/onlysans.pngbin0 -> 228 bytes
-rw-r--r--links/buttons/robophobia.pngbin0 -> 642 bytes
-rw-r--r--links/buttons/sadgrl.gifbin0 -> 2262 bytes
-rw-r--r--links/buttons/seaslug.pngbin0 -> 922 bytes
-rw-r--r--links/buttons/sizeofcat.pngbin0 -> 3630 bytes
-rw-r--r--links/buttons/xaselgio.gifbin0 -> 1683 bytes
-rw-r--r--links/index.php381
-rw-r--r--links/media/bacteriabird.pngbin0 -> 7619 bytes
-rw-r--r--links/media/caution.pngbin0 -> 15430 bytes
-rw-r--r--links/media/scorpionshark.pngbin0 -> 6310 bytes
-rw-r--r--music/bg.jpgbin0 -> 5175465 bytes
-rw-r--r--music/bg.jxlbin0 -> 1758211 bytes
-rw-r--r--music/covers/aeon_core.jpgbin0 -> 115848 bytes
-rw-r--r--music/covers/american_automatic.jpgbin0 -> 166607 bytes
-rw-r--r--music/covers/audio_video_disco.jpgbin0 -> 1842890 bytes
-rw-r--r--music/covers/concrete_and_gold.jpgbin0 -> 48035 bytes
-rw-r--r--music/covers/el_camino.jpgbin0 -> 304380 bytes
-rw-r--r--music/covers/for_science.jpgbin0 -> 276866 bytes
-rw-r--r--music/covers/fucked_up_friends_3.jpgbin0 -> 60480 bytes
-rw-r--r--music/covers/funeral.jpgbin0 -> 131431 bytes
-rw-r--r--music/covers/hawaii_part_ii.jpgbin0 -> 1583902 bytes
-rw-r--r--music/covers/millenialism.jpgbin0 -> 100627 bytes
-rw-r--r--music/covers/peaks_and_valleys.jpgbin0 -> 172688 bytes
-rw-r--r--music/covers/raw_data_feel.jpgbin0 -> 6995519 bytes
-rw-r--r--music/covers/realign.jpgbin0 -> 551354 bytes
-rw-r--r--music/covers/revolution_radio.jpgbin0 -> 55720 bytes
-rw-r--r--music/covers/spectrum.jpgbin0 -> 55373 bytes
-rw-r--r--music/covers/spirit_phone.jpgbin0 -> 265224 bytes
-rw-r--r--music/covers/synthicate.jpgbin0 -> 103467 bytes
-rw-r--r--music/covers/the_last_ninja_2_c64_ost.jpgbin0 -> 97958 bytes
-rw-r--r--music/covers/this_is_all_yours.jpgbin0 -> 412294 bytes
-rw-r--r--music/covers/tortured_waters.jpgbin0 -> 82365 bytes
-rw-r--r--music/covers/triangle_unicode.jpgbin0 -> 143324 bytes
-rw-r--r--music/covers/two_house.jpgbin0 -> 548212 bytes
-rw-r--r--music/covers/ultrakill_imperfect_hatred.jpgbin0 -> 467632 bytes
-rw-r--r--music/covers/unstoppable_force.jpgbin0 -> 259859 bytes
-rw-r--r--music/covers/vast.jpgbin0 -> 95173 bytes
-rw-r--r--music/covers/walks_of_lung.jpgbin0 -> 49218 bytes
-rw-r--r--music/covers/with_teeth.jpgbin0 -> 41128 bytes
-rw-r--r--music/index.php99
-rw-r--r--nav.php52
-rw-r--r--not_found.html27
-rw-r--r--old/1/icons/deeptwisty.pngbin0 -> 1763 bytes
-rw-r--r--old/1/icons/kirby.pngbin0 -> 1237 bytes
-rw-r--r--old/1/icons/message.pngbin0 -> 345 bytes
-rw-r--r--old/1/icons/tumblr.pngbin0 -> 386 bytes
-rw-r--r--old/1/icons/twitter.pngbin0 -> 711 bytes
-rw-r--r--old/1/icons/youtube.pngbin0 -> 539 bytes
-rw-r--r--old/1/images/allism.jpgbin0 -> 61186 bytes
-rw-r--r--old/1/images/bg_default.pngbin0 -> 7238262 bytes
-rw-r--r--old/1/images/bg_old1.pngbin0 -> 573420 bytes
-rw-r--r--old/1/images/bg_old2.pngbin0 -> 1645363 bytes
-rw-r--r--old/1/images/friaday.pngbin0 -> 515725 bytes
-rw-r--r--old/1/images/moday.pngbin0 -> 344390 bytes
-rw-r--r--old/1/images/paperbg.jpgbin0 -> 94123 bytes
-rw-r--r--old/1/images/satuaday.pngbin0 -> 1006865 bytes
-rw-r--r--old/1/images/suday.pngbin0 -> 536088 bytes
-rw-r--r--old/1/images/thuday.pngbin0 -> 674116 bytes
-rw-r--r--old/1/images/tueaday.pngbin0 -> 211383 bytes
-rw-r--r--old/1/images/weaday.pngbin0 -> 348053 bytes
-rw-r--r--old/1/index.html233
-rw-r--r--old/1/mobile.html118
-rw-r--r--old/1/stamps/antinft.gifbin0 -> 1669 bytes
-rw-r--r--old/1/stamps/bestviewed.gifbin0 -> 9419 bytes
-rw-r--r--old/1/stamps/bob.gifbin0 -> 142993 bytes
-rw-r--r--old/1/stamps/chrome2.gifbin0 -> 8964 bytes
-rw-r--r--old/1/stamps/deeptwistybutton.pngbin0 -> 2237 bytes
-rw-r--r--old/1/stamps/google_stand.gifbin0 -> 21247 bytes
-rw-r--r--old/1/stamps/h-free-anim.gifbin0 -> 6970 bytes
-rw-r--r--old/1/stamps/handcode.pngbin0 -> 6504 bytes
-rw-r--r--old/1/stamps/linux_powered.gifbin0 -> 14619 bytes
-rw-r--r--old/1/stamps/neocities_stamp.gifbin0 -> 2319 bytes
-rw-r--r--old/1/stamps/piracy.gifbin0 -> 910 bytes
-rw-r--r--old/1/stamps/tiredaf.gifbin0 -> 1701 bytes
-rw-r--r--old/1/stamps/usatoday.gifbin0 -> 5717 bytes
-rw-r--r--old/1/style.css57
-rw-r--r--old/1/tueaday.js62
-rw-r--r--old/2/audio/bridges.mp3bin0 -> 6326543 bytes
-rw-r--r--old/2/buttons/ace.pngbin0 -> 656 bytes
-rw-r--r--old/2/buttons/antinft.gifbin0 -> 1669 bytes
-rw-r--r--old/2/buttons/aro.pngbin0 -> 6180 bytes
-rw-r--r--old/2/buttons/bantimetravel.pngbin0 -> 3223 bytes
-rw-r--r--old/2/buttons/bestviewed.gifbin0 -> 9419 bytes
-rw-r--r--old/2/buttons/canadian.gifbin0 -> 4083 bytes
-rw-r--r--old/2/buttons/chrome.gifbin0 -> 8964 bytes
-rw-r--r--old/2/buttons/deeptwisty_button.pngbin0 -> 3995 bytes
-rw-r--r--old/2/buttons/google_stand.gifbin0 -> 21247 bytes
-rw-r--r--old/2/buttons/handcode.pngbin0 -> 6504 bytes
-rw-r--r--old/2/buttons/krisbtn.pngbin0 -> 1146 bytes
-rw-r--r--old/2/buttons/linux_powered.gifbin0 -> 14619 bytes
-rw-r--r--old/2/buttons/neocities_stamp.gifbin0 -> 2431 bytes
-rw-r--r--old/2/buttons/niceopod_button.pngbin0 -> 5163 bytes
-rw-r--r--old/2/buttons/notoweb3.gifbin0 -> 483 bytes
-rw-r--r--old/2/buttons/nowebp.gifbin0 -> 7372 bytes
-rw-r--r--old/2/buttons/piracy.gifbin0 -> 910 bytes
-rw-r--r--old/2/buttons/righttorepair.pngbin0 -> 6203 bytes
-rw-r--r--old/2/buttons/tested_on_firefox.gifbin0 -> 2754 bytes
-rw-r--r--old/2/buttons/usatoday.gifbin0 -> 5717 bytes
-rw-r--r--old/2/icons/deeptwisty.pngbin0 -> 1763 bytes
-rw-r--r--old/2/images/2022-05-21_blog_image_1.pngbin0 -> 18766 bytes
-rw-r--r--old/2/images/2022-05-21_blog_image_2.pngbin0 -> 3865646 bytes
-rw-r--r--old/2/images/albums/aeon_core.jpgbin0 -> 83183 bytes
-rw-r--r--old/2/images/albums/concrete_and_gold.jpgbin0 -> 34821 bytes
-rw-r--r--old/2/images/albums/fucked_up_friends_3.jpgbin0 -> 36786 bytes
-rw-r--r--old/2/images/albums/funeral.pngbin0 -> 321310 bytes
-rw-r--r--old/2/images/albums/millenialism.jpgbin0 -> 63417 bytes
-rw-r--r--old/2/images/albums/revolution_radio.jpgbin0 -> 36894 bytes
-rw-r--r--old/2/images/albums/spectrum.pngbin0 -> 25428 bytes
-rw-r--r--old/2/images/albums/tortured_waters.jpgbin0 -> 53215 bytes
-rw-r--r--old/2/images/albums/unstoppable_force.pngbin0 -> 552537 bytes
-rw-r--r--old/2/images/albums/vast.pngbin0 -> 174100 bytes
-rw-r--r--old/2/images/albums/walks_of_lung.jpgbin0 -> 30765 bytes
-rw-r--r--old/2/images/isopod.pngbin0 -> 37297 bytes
-rw-r--r--old/2/images/isopod_with_aviators.pngbin0 -> 25897 bytes
-rw-r--r--old/2/images/this_burning.gifbin0 -> 20897 bytes
-rw-r--r--old/2/index.html58
-rw-r--r--old/2/pages/blog.html41
-rw-r--r--old/2/pages/home.html152
-rw-r--r--old/2/pages/links.html64
-rw-r--r--old/2/pages/music.html49
-rw-r--r--old/2/pages/stats.html95
-rw-r--r--old/2/script.js102
-rw-r--r--old/2/shared.css224
-rw-r--r--old/2/themes/alterra/bg.jpgbin0 -> 401922 bytes
-rw-r--r--old/2/themes/alterra/style.css193
-rw-r--r--old/2/themes/deeptwisty/bg.pngbin0 -> 1002687 bytes
-rw-r--r--old/2/themes/deeptwisty/style.css127
-rw-r--r--old/2/themes/default/bg.jpgbin0 -> 250876 bytes
-rw-r--r--old/2/themes/default/div-bg.pngbin0 -> 11420 bytes
-rw-r--r--old/2/themes/default/style.css127
-rw-r--r--old/2/themes/geocities/beam.pngbin0 -> 604 bytes
-rw-r--r--old/2/themes/geocities/bg.gifbin0 -> 18572 bytes
-rw-r--r--old/2/themes/geocities/butterfly.gifbin0 -> 5636 bytes
-rw-r--r--old/2/themes/geocities/butterflyrockplant.gifbin0 -> 37030 bytes
-rw-r--r--old/2/themes/geocities/fire.gifbin0 -> 16956 bytes
-rw-r--r--old/2/themes/geocities/ocean-div.gifbin0 -> 2815 bytes
-rw-r--r--old/2/themes/geocities/orb.gifbin0 -> 1792 bytes
-rw-r--r--old/2/themes/geocities/rainbowball.gifbin0 -> 13366 bytes
-rw-r--r--old/2/themes/geocities/rose.gifbin0 -> 9880 bytes
-rw-r--r--old/2/themes/geocities/snail.gifbin0 -> 19432 bytes
-rw-r--r--old/2/themes/geocities/snake.gifbin0 -> 7044 bytes
-rw-r--r--old/2/themes/geocities/star.gifbin0 -> 1354 bytes
-rw-r--r--old/2/themes/geocities/star2.gifbin0 -> 1098 bytes
-rw-r--r--old/2/themes/geocities/star3.gifbin0 -> 8098 bytes
-rw-r--r--old/2/themes/geocities/star4.gifbin0 -> 251 bytes
-rw-r--r--old/2/themes/geocities/style.css138
-rw-r--r--old/2/themes/geocities/sun.gifbin0 -> 8783 bytes
-rw-r--r--old/2/themes/geocities/torch.gifbin0 -> 10745 bytes
-rw-r--r--old/2/themes/geocities/world.gifbin0 -> 22294 bytes
-rw-r--r--old/2/themes/gruvbox/bg.pngbin0 -> 3162 bytes
-rw-r--r--old/2/themes/gruvbox/style.css121
-rw-r--r--old/2/themes/none/style.css62
-rw-r--r--seasonal.php9
-rw-r--r--stats/bg.jpgbin0 -> 1946715 bytes
-rw-r--r--stats/bg.jxlbin0 -> 1069930 bytes
-rw-r--r--stats/index.php222
-rw-r--r--stuff/EnchantedToolsPack_v1.zipbin0 -> 80277 bytes
-rw-r--r--stuff/beat/digital.css10
-rw-r--r--stuff/beat/frame.php41
-rw-r--r--stuff/beat/index.php39
-rw-r--r--stuff/beat/pixel.css10
-rw-r--r--stuff/beat/sketch.css13
-rw-r--r--stuff/beat/time.php4
-rw-r--r--stuff/bg.jpgbin0 -> 551864 bytes
-rw-r--r--stuff/bg.jxlbin0 -> 247039 bytes
-rw-r--r--stuff/dirtomp3.sh58
-rw-r--r--stuff/firefoxrss/feed.php62
-rw-r--r--stuff/index.php105
-rw-r--r--stuff/neon_boost_times.html103
-rw-r--r--stuff/rssfilter.php288
-rw-r--r--stuff/spotifycdnsilly/ip.php21
-rw-r--r--stuff/webgarden/image1.html20
-rw-r--r--stuff/webgarden/image2.html20
-rw-r--r--stuff/webgarden/image3.html20
-rw-r--r--stuff/webgarden/image4.html20
-rw-r--r--stuff/webgarden/images/bubblecolumn1.gifbin0 -> 17577 bytes
-rw-r--r--stuff/webgarden/images/image1.pngbin0 -> 62759 bytes
-rw-r--r--stuff/webgarden/images/image2.pngbin0 -> 88013 bytes
-rw-r--r--stuff/webgarden/images/image3.pngbin0 -> 58953 bytes
-rw-r--r--stuff/webgarden/images/image4.pngbin0 -> 29488 bytes
-rw-r--r--stuff/webgarden/images/isopod_with_aviators_small.pngbin0 -> 13301 bytes
-rw-r--r--stuff/webgarden/images/webgarden-bg.pngbin0 -> 77765 bytes
-rw-r--r--stuff/webgarden/index.php192
-rw-r--r--stuff/webgarden/music.mp3bin0 -> 5532009 bytes
-rw-r--r--stuff/webgarden/status.php49
-rw-r--r--stuff/webgarden/style.css54
-rw-r--r--stuff/webpkiller/webpkiller.cmd31
-rw-r--r--stuff/webpkiller/webpkiller.py27
-rw-r--r--stuff/webpkiller/webpkiller.sh20
-rw-r--r--stuff/webpkiller/webpkiller_win.zipbin0 -> 9383795 bytes
-rw-r--r--style.css444
-rw-r--r--uses/bg.jpgbin0 -> 197536 bytes
-rw-r--r--uses/bg.jxlbin0 -> 134435 bytes
-rw-r--r--uses/compier/bg.jpgbin0 -> 1609376 bytes
-rw-r--r--uses/compier/images/cans.jpgbin0 -> 1016664 bytes
-rw-r--r--uses/compier/images/cans.jxlbin0 -> 791805 bytes
-rw-r--r--uses/compier/images/pc1.jpgbin0 -> 3355760 bytes
-rw-r--r--uses/compier/images/pc1.jxlbin0 -> 831754 bytes
-rw-r--r--uses/compier/images/pc2.jpgbin0 -> 631680 bytes
-rw-r--r--uses/compier/images/pc2.jxlbin0 -> 206993 bytes
-rw-r--r--uses/compier/index.php105
-rw-r--r--uses/cumulonimbus/bg.jpgbin0 -> 269779 bytes
-rw-r--r--uses/cumulonimbus/bg.jxlbin0 -> 259514 bytes
-rw-r--r--uses/cumulonimbus/index.php52
-rw-r--r--uses/images/switchback.jpgbin0 -> 241472 bytes
-rw-r--r--uses/images/switchfront.jpgbin0 -> 227498 bytes
-rw-r--r--uses/index.php94
-rw-r--r--uses/servy586/4k_in_more_ways_than_one.pngbin0 -> 384095 bytes
-rw-r--r--uses/servy586/bg.jpgbin0 -> 1072812 bytes
-rw-r--r--uses/servy586/index.php84
-rw-r--r--uses/servy586/nictua.jpgbin0 -> 242887 bytes
-rw-r--r--uses/servy586/servercase.jpgbin0 -> 148090 bytes
-rw-r--r--uses/servy586/servercaseinside.jpgbin0 -> 335938 bytes
-rw-r--r--uses/servy586/ziptiemount.jpgbin0 -> 156703 bytes
-rw-r--r--wimpod.js198
434 files changed, 8994 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7e54634
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+pronouns.txt
+blog/posts/invaluable_contributions
+Parsedown.php
+/stuff/fonts/* \ No newline at end of file
diff --git a/.well-known/button.json b/.well-known/button.json
new file mode 100644
index 0000000..2b582bd
--- /dev/null
+++ b/.well-known/button.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://codeberg.org/LunarEclipse/well-known-button/raw/branch/main/drafts/button-2024-06.schema.json",
+ "default": "isopod.cool",
+ "buttons": [
+ {
+ "id": "isopod.cool",
+ "uri": "https://isopod.cool/etc/buttons/isopodhours.png",
+ "alt": "isopod.cool button",
+ "link": "https://isopod.cool/",
+ "sha256": "0a18cabc99db5a98a9b1d0ca69fd22783919c8e2e3996290a18780cfb3a54646"
+ }
+ ]
+} \ No newline at end of file
diff --git a/.well-known/fursona b/.well-known/fursona
new file mode 100644
index 0000000..acd2f49
--- /dev/null
+++ b/.well-known/fursona
@@ -0,0 +1,19 @@
+{
+ "sonas": [
+ {
+ "name": "Example Fursona",
+ "pronouns": "she/it",
+ "gender": "Female",
+ "species": "Bathynomus Giganteus",
+ "description": "A description of the fursona, max 250 characters",
+ "ref": "https://isopod.cool/images/fursona/ref.png",
+ "avatar": "https://isopod.cool/images/fursona/avatar.png",
+ "age": 22,
+ "colors": [
+ "#82828d",
+ "#cccccc",
+ "#222222"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..344290b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,57 @@
+# 🏳️‍🌈 Opinionated Queer License v1.2
+
+© Copyright {Licensor}
+
+## Permissions
+
+The creators of this Work (“The Licensor”) grant permission
+to any person, group or legal entity that doesn't violate the prohibitions below (“The User”),
+to do everything with this Work that would otherwise infringe their copyright or any patent claims,
+subject to the following conditions:
+
+## Obligations
+
+The User must give appropriate credit to the Licensor,
+provide a copy of this license or a (clickable, if the medium allows) link to
+[oql.avris.it/license/v1.2](https://oql.avris.it/license/v1.2),
+and indicate whether and what kind of changes were made.
+The User may do so in any reasonable manner,
+but not in any way that suggests the Licensor endorses the User or their use.
+
+## Prohibitions
+
+No one may use this Work for prejudiced or bigoted purposes, including but not limited to:
+racism, xenophobia, queerphobia, queer exclusionism, homophobia, transphobia, enbyphobia, misogyny.
+
+No one may use this Work to inflict or facilitate violence or abuse of human rights,
+as defined in either of the following documents:
+[Universal Declaration of Human Rights](https://www.un.org/en/about-us/universal-declaration-of-human-rights),
+[European Convention on Human Rights](https://prd-echr.coe.int/web/echr/european-convention-on-human-rights)
+along with the rulings of the [European Court of Human Rights](https://www.echr.coe.int/).
+
+No law enforcement, carceral institutions, immigration enforcement entities, military entities or military contractors
+may use the Work for any reason. This also applies to any individuals employed by those entities.
+
+No business entity where the ratio of pay (salaried, freelance, stocks, or other benefits)
+between the highest and lowest individual in the entity is greater than 50 : 1
+may use the Work for any reason.
+
+No private business run for profit with more than a thousand employees
+may use the Work for any reason.
+
+Unless the User has made substantial changes to the Work,
+or uses it only as a part of a new work (eg. as a library, as a part of an anthology, etc.),
+they are prohibited from selling the Work.
+That prohibition includes processing the Work with machine learning models.
+
+## Sanctions
+
+If the Licensor notifies the User that they have not complied with the rules of the license,
+they can keep their license by complying within 30 days after the notice.
+If they do not do so, their license ends immediately.
+
+## Warranty
+
+This Work is provided “as is”, without warranty of any kind, express or implied.
+The Licensor will not be liable to anyone for any damages related to the Work or this license,
+under any kind of legal claim as far as the law allows. \ No newline at end of file
diff --git a/README.md b/README.md
index 7527752..dc3d103 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,6 @@
# isopod.cool
-My personal website \ No newline at end of file
+My personal website.
+
+**TODO:**
+- Add more isopods.
diff --git a/about/bg.jpg b/about/bg.jpg
new file mode 100644
index 0000000..b5d9e55
--- /dev/null
+++ b/about/bg.jpg
Binary files differ
diff --git a/about/bg.jxl b/about/bg.jxl
new file mode 100644
index 0000000..b05abc2
--- /dev/null
+++ b/about/bg.jxl
Binary files differ
diff --git a/about/images/crackship_quiz_result.png b/about/images/crackship_quiz_result.png
new file mode 100644
index 0000000..8b4d701
--- /dev/null
+++ b/about/images/crackship_quiz_result.png
Binary files differ
diff --git a/about/images/isopod_quiz_result.png b/about/images/isopod_quiz_result.png
new file mode 100644
index 0000000..31d29e1
--- /dev/null
+++ b/about/images/isopod_quiz_result.png
Binary files differ
diff --git a/about/index.php b/about/index.php
new file mode 100644
index 0000000..652ddc9
--- /dev/null
+++ b/about/index.php
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>About</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true, 1000, "Pictured: Me on my daily walk") ?>
+ <h1>about me</h1>
+ <h2 id="caption" title="General Kenobi!">Hello there!</h2>
+ <div class="buttons">
+ <img src="/etc/buttons/isopodhours.png" alt="isopod hours">
+ <a target="_blank" href="https://deeptwisty.com/"><img src="/etc/buttons/deeptwisty_button.png" alt="deep twisty"></a>
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=pixel" style="width: 84px; height: 27px;"></iframe>
+ </div>
+ <div class="buttons">
+ <img src="/etc/buttons/aro.png" alt="Aromantic pride flag">
+ <a href="https://rainy.gay/pride/pridebuttons.html"><img src="/etc/buttons/trans.png" alt="Trans pride flag"></a>
+ </div>
+ <h2>Specs</h2>
+ <table>
+ <tr>
+ <td>Known aliases</td>
+ <td>deep twisty, isopod gaming, bathynomus, Hannah, Dawn</td>
+ </tr>
+ <tr>
+ <td>Pronouns</td>
+ <td><?php echo file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/pronouns.txt'); ?></td>
+ </tr>
+ <tr>
+ <td>Preoccupations</td>
+ <td>Computer hardware, computer software, electronics, the creation of music and 3D art, any DIY project that'll fit on a desk, and some that won't</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><a href="/stats">More info</a></td>
+ </tr>
+ </table>
+ <h2>Links</h2>
+ <table>
+ <tr>
+ <td><a href="mailto:webmaster@isopod.cool" rel="me">webmaster@isopod.cool</a></td>
+ <td>Email</td>
+ </tr>
+ <tr>
+ <td><a href="https://signal.me/#eu/Q5Z321Fn6bCsLhj3kNwXxvSgAUmbFiVtx2F-oG0A9_Egl_uTUmNLLYHs1WwbUE4B" rel="me">isopod.97</a></td>
+ <td>Signal</td>
+ </tr>
+ <tr>
+ <td>bathynomus#5230</td>
+ <td>Revolt</td>
+ </tr>
+ <tr>
+ <td><a href="https://isopod.zone/@root" rel="me">@root@isopod.zone</a></td>
+ <td>Fediverse</td>
+ </tr>
+ <tr><td><a href="https://tumblr.isopod.cool/" rel="me">@isopodhours</a></td><td>Tumblr</td></tr>
+ <tr><td><a href="https://bsky.app/profile/isopod.cool" rel="me">@isopod.cool</a></td><td>Bluesky</td></tr>
+ <tr>
+ <td><a href="https://www.youtube.com/@deeptwisty" rel="me">deep twisty</a></td>
+ <td>Youtube for music</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.youtube.com/@isopodgaming" rel="me">isopod gaming</a></td>
+ <td>Youtube for other stuff</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.twitch.tv/deeptwistygaming" rel="me">deeptwistygaming</a></td>
+ <td>Twitch</td>
+ </tr>
+ <tr>
+ <td><a href="https://deeptwisty.bandcamp.com/" rel="me">deeptwisty.bandcamp.com</a></td>
+ <td>Bandcamp</td>
+ </tr>
+ <tr>
+ <td><a href="https://deeptwisty.itch.io/" rel="me">deeptwisty.itch.io</a></td>
+ <td>itch.io</td>
+ </tr>
+ <tr>
+ <td><a href="https://ko-fi.com/deeptwisty" rel="me">deeptwisty</a></td>
+ <td>Ko-fi</td>
+ </tr>
+ <tr>
+ <td><a href="https://git.isopod.cool/root/" rel="me">git.isopod.cool/root</a></td>
+ <td>Forgejo</td>
+ </tr>
+ </table>
+ <h2>What's a "deep twisty"?</h2>
+ <p>"deep twisty" is a pseudonym I came up with to post my music and such things under. At this point it exists largely as a way to compartmentalize my online identity such that I can link my art to people who I might not want seeing all this. It comes from some tweets from an <a href="https://web.archive.org/web/20221214182955/https://twitter.com/SubnauticaSCM/status/1095774020446744576">official Subnautica twitter account</a> where they referred to the then-work-in-progress Deep Twisty Bridges biome as just "deep twisty". I thought it sounded funny. Funny enough to brand myself based on, apparently.</p>
+ <h2>About the site</h2>
+ <p>This website is written in pure HTML, CSS, and a tiny bit of Javascript with the server-side stuff done in PHP. It (and everything else I host) is hosted using Caddy on a OVH dedicated server running Ubuntu Server, with domains registered with <a href="https://porkbun.com/">Porkbun</a>. You can read about its history <a href="../blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/">here</a>.</p>
+ <p>I was helped immensely in building this thing by <a href="https://www.w3schools.com/">W3Schools</a>, the <a href="https://developer.mozilla.org/en-US/docs/Web">MDN Web Docs</a>, the official <a href="https://www.php.net/manual/en/">PHP manual</a>, <a href="https://landchad.net/">LandChad.net</a>, Stack Overflow, and whatever disgusting bottom-feeding SEO leech sites came up first in the search results.</p>
+ <h2>Quiz results</h2>
+ <div>
+ <a href="https://casiopea.neocities.org/isopod/isopodquiz.html"><img src="images/isopod_quiz_result.png"></a>
+ <a href="https://ouroboreas.neocities.org/quizzes/crackships/quiz"><img src="images/crackship_quiz_result.png" height="100px"></a>
+ <a href="https://andou.gay/quiz/donutquiz"><img src="https://andou.gay/quiz/chocolate donut.png" height="100px"></a>
+ <a href="https://swiftyshq.neocities.org/fun/quiz/rock/" title="Description: ough.... youre so relaxed.... this rock is PERFECT for napping on.... it's warmed by the sun too... .yo.... snzz"><img src="https://swiftyshq.neocities.org/img/quiz/rock/r2.png" height="100px"></a>
+ <a href="https://swiftyshq.neocities.org/fun/quiz/creature/" title="Description: http creature not found. you are maybe toxic but in a funny way. gods little meow meow"><img src="https://swiftyshq.neocities.org/img/quiz/creature/res3.png" height="100px"></a>
+ </div>
+ <h2>Testimonials</h2>
+ <figure class="quote">
+ <blockquote>
+ Most of it goes over my head, but it's still fun to read and look at, and I am not immune to isopods.
+ </blockquote>
+ <figcaption>
+ &mdash; <a href="https://kalechips.net/">Kalechips</a>
+ </figcaption>
+ </figure>
+ <figure class="quote">
+ <blockquote>
+ Furry behavior
+ </blockquote>
+ <figcaption>
+ &mdash; <a href="https://seaslug.neocities.org/">Seaslug</a>
+ </figcaption>
+ </figure>
+ <figure class="quote">
+ <blockquote>
+ hi for the love of god hello
+ </blockquote>
+ <figcaption>
+ &mdash; <a href="https://mifs.tumblr.com/">mifs</a>
+ </figcaption>
+ </figure>
+ <figure class="quote">
+ <blockquote>
+ isopod isopod isopod isopod isopod isopod isopod isopod isopod
+ </blockquote>
+ <figcaption>
+ &mdash; Twiggy
+ </figcaption>
+ </figure>
+ </body>
+</html>
diff --git a/blog/bg.jpg b/blog/bg.jpg
new file mode 100644
index 0000000..a27cf66
--- /dev/null
+++ b/blog/bg.jpg
Binary files differ
diff --git a/blog/bg.jxl b/blog/bg.jxl
new file mode 100644
index 0000000..a56559f
--- /dev/null
+++ b/blog/bg.jxl
Binary files differ
diff --git a/blog/blog.atom b/blog/blog.atom
new file mode 100644
index 0000000..ddb59dd
--- /dev/null
+++ b/blog/blog.atom
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title>isopod.cool blog</title>
+ <id>https://isopod.cool/blog/</id>
+ <link rel="alternate" href="https://isopod.cool/blog/"></link>
+ <updated>2025-04-29T00:00:00+00:00</updated>
+ <author>
+ <name>Hannah Isopod</name>
+ <uri>https://isopod.cool/</uri>
+ </author>
+ <generator>ME</generator>
+ <category term="personal"/>
+ <category term="blog"/>
+ <category term="tech"/>
+ <!--entry>
+ <title>Succumbing to the Inevitable</title>
+ <id>how_my_blog_works</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/how_my_blog_works/" type="html" title="Succumbing to the Inevitable"></link>
+ <published>2024-12-18T00:00:00+00:00</published>
+ <updated>2024-12-18T00:00:00+00:00</updated>
+ <summary>The explanation of my blog's under-the-hood workings that became inevitable the minute I started writing custom code for it.</summary>
+ <category term="self-hosting"/>
+ <category term="php"/>
+ </entry-->
+ <entry>
+ <title>I've Just Moved Hosting Providers</title>
+ <id>renting_an_unremarkable_server</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/renting_an_unremarkable_server/" type="html" title="I've Just Moved Hosting Providers"></link>
+ <published>2025-04-29T00:00:00+00:00</published>
+ <updated>2025-04-29T00:00:00+00:00</updated>
+ <summary>I've just migrated all my self-hosted stuff onto a new type of hosting solution with a new provider, and apparently I had a lot more to say about it than I thought. I promise my next post will be about something other than a computer.</summary>
+ <category term="personal"/>
+ <category term="self-hosting"/>
+ </entry>
+ <entry>
+ <title>Holiday Special: My First Computer</title>
+ <id>toshiba_chromebook</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/toshiba_chromebook/" type="html" title="Holiday Special: My First Computer"></link>
+ <published>2024-12-25T00:00:00+00:00</published>
+ <updated>2024-12-25T00:00:00+00:00</updated>
+ <summary>Reminiscing about the first computer I ever owned, which taught me everything I know, and in a just world would be turning 10 years old this Christmas.</summary>
+ <category term="personal"/>
+ <category term="hardware"/>
+ <category term="holiday special"/>
+ </entry>
+ <entry>
+ <title>Building a Relatively Sensible Server</title>
+ <id>building_a_sensible_server</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/building_a_sensible_server/" type="html" title="Building a Relatively Sensible Server"></link>
+ <published>2024-10-03T00:00:00+00:00</published>
+ <updated>2024-10-03T00:00:00+00:00</updated>
+ <summary>The wacky DIY NAS I built out of my old gaming laptop last year isn't working as well as I hoped. Follow me as I strip it for parts and construct a better one, properly this time.</summary>
+ <category term="personal"/>
+ <category term="self-hosting"/>
+ <category term="diy"/>
+ <category term="hardware"/>
+ </entry>
+ <entry>
+ <title>How to Set Up Pi-Hole (On a Le Potato)</title>
+ <id>guide_pihole_lepotato</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_pihole_lepotato/" type="html" title="How to Set Up Pi-Hole (On A Le Potato)"></link>
+ <published>2024-09-20T00:00:00+00:00</published>
+ <updated>2024-09-20T00:00:00+00:00</updated>
+ <summary>How to set up Pi-hole, a network-wide DNS-level ad-blocker, on the particular discount Raspberry Pi I did it on.</summary>
+ <category term="self-hosting"/>
+ <category term="diy"/>
+ <category term="capitalism"/>
+ <category term="hardware"/>
+ </entry>
+ <entry>
+ <title>You Should Learn To Make Cables</title>
+ <id>make_your_own_cables</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/make_your_own_cables/" type="html" title="You Should Learn To Make Cables"></link>
+ <published>2024-09-09T00:00:00+00:00</published>
+ <updated>2024-09-14T00:00:00+00:00</updated>
+ <summary>I saved $140 by splicing together my own audio cables, and you can too!</summary>
+ <category term="audio"/>
+ <category term="diy"/>
+ <category term="capitalism"/>
+ <category term="hardware"/>
+ </entry>
+ <entry>
+ <title>Admins Can Read Your DMs</title>
+ <id>fediverse_dms</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/fediverse_dms/" type="html" title="Admins Can Read Your DMs"></link>
+ <published>2024-05-09T00:00:00+00:00</published>
+ <updated>2024-05-09T00:00:00+00:00</updated>
+ <summary>Yes, the admins of your fediverse server can read your DMs. No, that's not actually a problem.</summary>
+ <category term="fediverse"/>
+ <category term="privacy"/>
+ <category term="pedantry"/>
+ </entry>
+ <entry>
+ <title>Building a Completely Normal Server</title>
+ <id>building_a_normal_server</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/building_a_normal_server/" type="html" title="Building a Completely Normal Server"></link>
+ <published>2024-02-28T00:00:00+00:00</published>
+ <updated>2024-02-28T00:00:00+00:00</updated>
+ <summary>I spent the past few months making full use of all my physical engineering talents to build a NAS that is completely normal, and not weird at all, and involved an amount of 3D modeling, 3D printing, and hacksawing that is entirely typical of most home computer builds, all in the name of reusing an old laptop.</summary>
+ <category term="personal"/>
+ <category term="self-hosting"/>
+ <category term="diy"/>
+ <category term="hardware"/>
+ </entry>
+ <entry>
+ <title>My Terrible, Horrible, No-Good, Very Bad Distro Hop</title>
+ <id>my_terrible_distro_hop</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/my_terrible_distro_hop/" type="html" title="My Terrible, Horrible, No-Good, Very Bad Distro Hop"></link>
+ <published>2024-02-25T00:00:00+00:00</published>
+ <updated>2024-07-06T00:00:00+00:00</updated>
+ <summary>A chronicle of my brief journey from EndeavourOS to Fedora to back to EndeavourOS, and wrestling with a VPN client that sees itself as above such trifling matters as "functioning".</summary>
+ <category term="personal"/>
+ <category term="linux"/>
+ <category term="protonvpn"/>
+ </entry>
+ <entry>
+ <title>How to Make Youtube Videos Buffer All The Way Like The Old Days (In Firefox)</title>
+ <id>guide_fix_youtube_buffering_firefox</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_fix_youtube_buffering_firefox/" type="html" title="How to Make Youtube Videos Buffer All The Way Like The Old Days (In Firefox)"></link>
+ <published>2024-02-13T00:00:00+00:00</published>
+ <updated>2024-03-18T00:00:00+00:00</updated>
+ <summary>Alternate title: Common Firefox W</summary>
+ <category term="guide"/>
+ <category term="youtube"/>
+ <category term="firefox"/>
+ </entry>
+ <entry>
+ <title>I Don't Like AI Art</title>
+ <id>ai_art</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/ai_art/" type="html" title="I Don't Like AI Art"></link>
+ <published>2024-01-03T00:00:00+00:00</published>
+ <updated>2024-01-03T00:00:00+00:00</updated>
+ <summary>My actual thoughts on AI, in case seeing an AI-generated article in your RSS feed didn't get the vibe across.</summary>
+ <category term="ai"/>
+ <category term="chatgpt"/>
+ <category term="capitalism"/>
+ </entry>
+ <entry>
+ <title>The Invaluable Contributions of AI Tools to Humanity: A Look at the Unparalleled Benefits</title>
+ <id>invaluable_contributions</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/invaluable_contributions/" type="html" title="The Invaluable Contributions of AI Tools to Humanity: A Look at the Unparalleled Benefits"></link>
+ <published>2024-01-02T00:00:00+00:00</published>
+ <updated>2024-01-02T00:00:00+00:00</updated>
+ <summary>AI tools offer unparalleled benefits to humanity, enhancing efficiency, healthcare, education, environmental sustainability, customer experiences, scientific research, and social accessibility. Despite ethical concerns, responsible development ensures that the positive impact of AI far outweighs potential downsides.</summary>
+ <category term="ai"/>
+ <category term="chatgpt"/>
+ </entry>
+ <entry>
+ <title>The Unity Runtime Fee and Proprietary Software</title>
+ <id>unity_runtime_fee_and_proprietary_software</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/unity_runtime_fee_and_proprietary_software/" type="html" title="The Unity Runtime Fee and Proprietary Software"></link>
+ <published>2023-09-15T00:00:00+00:00</published>
+ <updated>2023-09-23T00:00:00+00:00</updated>
+ <summary>Unity's new Runtime Fee is yet another data point on the pile against ever trusting for-profit software companies.</summary>
+ <category term="unity"/>
+ <category term="capitalism"/>
+ </entry>
+ <entry>
+ <title>Blacklisting Websites in SearXNG</title>
+ <id>guide_blacklist_websites_searxng</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_blacklist_websites_searxng/" type="html" title="Blacklisting Websites in SearXNG"></link>
+ <published>2023-09-02T00:00:00+00:00</published>
+ <updated>2023-09-02T00:00:00+00:00</updated>
+ <summary>How to permanently banish geeksforgeeks.org from your search results in the event you're using a self-hosted SearXNG instance and can't just install uBlacklist.</summary>
+ <category term="guide"/>
+ <category term="self-hosting"/>
+ <category term="searxng"/>
+ </entry>
+ <entry>
+ <title>Stop Using Chromium</title>
+ <id>stop_using_chromium</id>
+ <link rel="alternate" href="https://chrome.bathynomus.xyz/" type="html" title="Stop Using Chromium"></link>
+ <published>2023-08-16T00:00:00+00:00</published>
+ <updated>2023-08-16T00:00:00+00:00</updated>
+ <summary>An article about why you should quit using Chromium-based browsers, published as a standalone website for the purpose of automatically redirecting Chromium users to it.</summary>
+ <category term="chromium"/>
+ <category term="google"/>
+ <category term="capitalism"/>
+ </entry>
+ <entry>
+ <title>Discord - So Your Favourite Chat App Sucks Now</title>
+ <id>discord</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/discord/" type="html" title="Discord - So Your Favourite Chat App Sucks Now"></link>
+ <published>2023-06-28T00:00:00+00:00</published>
+ <updated>2024-09-10T00:00:00+00:00</updated>
+ <summary>Why Discord sucks, and how to find something that doesn't.</summary>
+ <category term="discord"/>
+ <category term="capitalism"/>
+ <category term="privacy"/>
+ </entry>
+ <entry>
+ <title>How to Automount Drives On Boot in Linux</title>
+ <id>guide_how_to_automount_drives_on_boot_in_linux</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/" type="html" title="How to Automount Drives On Boot in Linux"></link>
+ <published>2023-04-26T00:00:00+00:00</published>
+ <updated>2024-09-10T00:00:00+00:00</updated>
+ <summary>How to configure a Linux system to automatically mount drives on boot by editing /etc/fstab.</summary>
+ <category term="guide"/>
+ <category term="linux"/>
+ </entry>
+ <entry>
+ <title>How to Block User Agents With Nginx</title>
+ <id>guide_blocking_user_agents_nginx</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_blocking_user_agents_nginx/" type="html" title="How to Block User Agents With Nginx"></link>
+ <published>2023-02-23T00:00:00+00:00</published>
+ <updated>2024-09-10T00:00:00+00:00</updated>
+ <summary>How to configure Nginx to tell Cloudflare and their shitty centralized Fediverse server to go fuck themselves. And other unwelcome stuff too, I guess.</summary>
+ <category term="guide"/>
+ <category term="self-hosting"/>
+ <category term="nginx"/>
+ </entry>
+ <!--entry>
+ <title>Things I Keep Having To Google</title>
+ <id>guide_things_i_keep_having_to_google</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_things_i_keep_having_to_google/" type="html" title="Things I Keep Having To Google"></link>
+ <published>2023-01-12T00:00:00+00:00</published>
+ <updated>2023-01-12T00:00:00+00:00</updated>
+ <summary>A continually updating personal reference of random information I keep needing but keep forgetting.</summary>
+ <category term="guide"/>
+ <category term="linux"/>
+ <category term="bash"/>
+ <category term="html"/>
+ <category term="css"/>
+ <category term="php"/>
+ </entry-->
+ <entry>
+ <title>deeptwisty.com 2nd anniversary - A History of This Bullshit</title>
+ <id>deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/" type="html" title="deeptwisty.com 2nd anniversary - A History of This Bullshit"></link>
+ <published>2022-09-19T00:00:00+00:00</published>
+ <updated>2024-09-10T00:00:00+00:00</updated>
+ <summary>An abridged history of my presence on the World Wide Web, from my first customized Tumblr pages to now.</summary>
+ <category term="personal"/>
+ </entry>
+ <!--entry>
+ <title>Self-Host Safely with WireGuard</title>
+ <id>guide_self_host_safely_with_wireguard</id>
+ <link rel="alternate" href="https://isopod.cool/blog/posts/guide_self_host_safely_with_wireguard/" type="html" title="Self-Host Safely with WireGuard"></link>
+ <published>2022-08-25T00:00:00+00:00</published>
+ <updated>2022-08-25T00:00:00+00:00</updated>
+ <summary>A basic guide on connecting two Linux servers via WireGuard to make one publically accessible through the other.</summary>
+ <category term="guide"/>
+ <category term="self-hosting"/>
+ <category term="wireguard"/>
+ <category term="linux"/>
+ </entry-->
+</feed>
diff --git a/blog/comment/comments.css b/blog/comment/comments.css
new file mode 100644
index 0000000..7f97c4c
--- /dev/null
+++ b/blog/comment/comments.css
@@ -0,0 +1,92 @@
+table {
+ border-collapse: collapse;
+ table-layout: fixed;
+}
+td {
+ padding: 0.3rem;
+}
+
+form > table {
+ width: 100%;
+ margin: auto;
+ margin-bottom: 1.5rem;
+}
+
+article {
+ width: 100%;
+ margin: 2rem auto;
+ display: grid;
+ gap: 1rem;
+}
+
+input, textarea {
+ border: none;
+ font-family: var(--stdfont);
+}
+input[type="text"], input[type="email"], textarea {
+ width: 100%;
+ background: none;
+ border-bottom: 2px solid #444444;
+ color: gainsboro;
+ padding: 0.35rem;
+ box-sizing: border-box;
+ font-size: .9em;
+}
+input[type="submit"], input[type="reset"] {
+ padding: 0.35rem 0.5rem;
+ box-shadow: 2px 2px 6px black;
+ margin: 0.3rem;
+ display: inline-block;
+}
+input[type="submit"]:active, input[type="reset"]:active {
+ transform: translate(1px, 1px); box-shadow: 0 0 2px black;
+}
+input[type="submit"]:hover, input[type="reset"]:hover {
+ cursor: pointer;
+}
+.error {
+ color: red;
+ font-size: 0.85em;
+}
+.success {
+ color: #00ff00;
+ font-size: 0.85em;
+}
+.reply {
+ border-left: 3px solid gainsboro;
+ padding-left: 1rem;
+}
+.message {
+ padding-top: 1.5rem;
+}
+@media only screen and (hover: none) {
+ form td:first-child {
+ text-align: left;
+ }
+ form td:nth-child(2) {
+ padding-left: 0;
+ padding-right: 0;
+ }
+ input[type="text"], input[type="email"], textarea {
+ background: none;
+ border: 2px solid #00000033;
+ border-bottom: 2px solid #888888;
+ }
+ article {
+ margin: 2rem auto;
+ }
+}
+@media (prefers-contrast: more) {
+ input[type="text"], input[type="email"], textarea {
+ outline: 1px solid white;
+ color: white;
+ }
+ input:focus, textarea:focus {
+ outline: 3px solid white;
+ }
+ input[type="submit"] {
+ background: none;
+ color: white;
+ outline: 1px solid white;
+ }
+} \ No newline at end of file
diff --git a/blog/comment/feed.php b/blog/comment/feed.php
new file mode 100644
index 0000000..889514f
--- /dev/null
+++ b/blog/comment/feed.php
@@ -0,0 +1,29 @@
+<?php
+include("../../Parsedown.php");
+$Parsedown = new Parsedown();
+$Parsedown->setSafeMode(true);
+
+header('Content-Type: text/xml');
+
+echo '<rss version="2.0"><channel>';
+echo '<title>isopod.cool blog comments</title>';
+echo '<description>Every comment posted on my blog in chronological order.</description>';
+echo '<language>en-us</language>';
+echo '<link>https://isopod.cool/blog/comment/</link>';
+echo '<generator>My crappy PHP code</generator>';
+
+$postlist = json_decode(file_get_contents("posts.json"));
+$totaloutput = "";
+foreach($postlist as $post) {
+ $output = "";
+ $date = date("D, d M Y H:m:s", $post->date) . " GMT";
+ $name = $post->name;
+ $message = $Parsedown->text(html_entity_decode($post->message));
+ $entry = $post->entry;
+
+ $output = $output."Comment from ".$name." on ".$entry.":<br><br>".$message."<br><br>";
+ $totaloutput = "<item><title>Comment on " . $entry . " from " . $name . "</title><link>https://isopod.cool/blog/posts/" . $entry . "/</link><pubDate>" . $date . "</pubDate><description>".htmlentities($output)."</description><guid isPermaLink='false'>" . $entry . $post->date . $name . "</guid></item>".$totaloutput;
+}
+
+echo $totaloutput;
+echo "</channel></rss>"; \ No newline at end of file
diff --git a/blog/comment/index.php b/blog/comment/index.php
new file mode 100644
index 0000000..2d5f6a6
--- /dev/null
+++ b/blog/comment/index.php
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>blog comments</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <link href="comments.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); ?>
+ <h1>blog</h1>
+ <h2 id="caption">every comment</h2>
+ <nav>
+ <a href="feed.php">RSS</a>
+ </nav>
+ <?php
+ include("../../Parsedown.php");
+ $Parsedown = new Parsedown();
+ $Parsedown->setSafeMode(true);
+
+ $totaloutput = "";
+ $postlist = json_decode(file_get_contents("posts.json"));
+ foreach($postlist as $post) {
+ $output = "";
+ $date = date("Y-m-d h:iA", $post->date);
+ $name = $post->name;
+ $message = $Parsedown->text(html_entity_decode($post->message));
+ $entry = $post->entry;
+
+ $output = $output."<hr><article><table><tr><td style='text-align: left;'>".$name." <i>on</i> <a href='/blog/posts/".$entry."/'>".$entry."</a></td><td style='text-align: right;'>".$date."</td></tr><tr><td colspan='2'>".$message."</td></tr></table></article>";
+ $totaloutput = $output.$totaloutput;
+ }
+ echo $totaloutput; ?>
+ </body>
+</html>
diff --git a/blog/comment/submit.php b/blog/comment/submit.php
new file mode 100644
index 0000000..26e5647
--- /dev/null
+++ b/blog/comment/submit.php
@@ -0,0 +1,81 @@
+<?php
+ if ($_SERVER["REQUEST_METHOD"] == "POST") {
+
+ $returnLocation = $_POST["entry"];
+ $returnCode = "success";
+ if($_POST["botcheck"] != "isopod") {
+ $returnCode = "botcheckfailed";
+ } else if(!$_POST["name"]) {
+ $returnCode = "noname";
+ } else if(!$_POST["message"]) {
+ $returnCode = "nomessage";
+ } else {
+
+ date_default_timezone_set("America/Edmonton");
+ $currentPost = array(
+ "date" => time(),
+ "name" => htmlentities($_POST["name"]),
+ "message" => htmlentities($_POST["message"]),
+ "entry" => $_POST["entry"]
+ );
+
+ $filename = "posts.json";
+
+ $handle = @fopen($filename, 'r+');
+
+ // create the file if needed
+ if ($handle === null)
+ {
+ $handle = fopen($filename, 'w+');
+ }
+
+ if ($handle)
+ {
+ // seek to the end
+ fseek($handle, 0, SEEK_END);
+
+ // are we at the end of is the file empty
+ if (ftell($handle) > 0)
+ {
+ // move back a byte
+ fseek($handle, -2, SEEK_END);
+
+ // add the trailing comma
+ fwrite($handle, ",\n", 2);
+
+ // add the new json string
+ fwrite($handle, json_encode($currentPost) . "]\n");
+ }
+ else
+ {
+ // write the first event inside an array
+ fwrite($handle, json_encode(array($currentPost)));
+ }
+
+ // close the handle on the file
+ fclose($handle);
+ }
+ }
+ }
+ header("Location: ../posts/$returnLocation/?return=$returnCode");
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Guestbook</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ body {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <p>Your post has been submitted! It's weird that you're seeing this page though. Maybe your browser can't process location headers? At any rate, click <?php echo "<a href='./?return=$returnCode'>here</a>"; ?> to get where you're supposed to be right now.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/blog/index.php b/blog/index.php
new file mode 100644
index 0000000..2433e97
--- /dev/null
+++ b/blog/index.php
@@ -0,0 +1,164 @@
+<!--?php
+ini_set('display_errors', '1');
+ini_set('display_startup_errors', '1');
+error_reporting(E_ALL);
+?-->
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Blog</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ ul#articles {
+ margin: 0;
+ margin-top: 1rem;
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ list-style: none;
+ }
+ .blogentry {
+ max-width: 100%;
+ list-style: none;
+ display: inline-block;
+ margin: calc(var(--stdpadding)/2) 0;
+ padding: var(--stdpadding);
+
+ border-left: var(--stdaccentborder);
+ background: linear-gradient(var(--blockbghover) 0 0) 0 / var(--bgpos, 0) no-repeat;
+ transition: background .3s, border .3s;
+ }
+ .blogentry:hover {
+ --bgpos: 100%;
+ }
+ ul#articles h2 {
+ margin: calc(var(--stdpadding)/2) 0;
+ }
+ /*ul h2:first-of-type::before {
+ content: "Articles - "
+ }*/
+ article img, article video, article iframe {
+ filter:drop-shadow(var(--stddropshadow));
+ }
+ .blogentry > * {
+ display: block;
+ margin: 0.1rem 0;
+ box-sizing: border-box;
+ }
+ .entrysummary {
+ font-size: .9em;
+ color: gainsboro;
+ }
+ .entrytag {
+ font-size: .9em;
+ color: #bbbbbb;
+ font-style: italic;
+ display: inline-block;
+ margin-right: 1ch;
+ }
+ .entrydate {
+ font-weight: bold;
+ }
+ .entrytitle {
+ padding-left: initial;
+ border-left: initial;
+ }
+ article:first-of-type h2::before {
+ content: 'Journal - ';
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true); ?>
+ <h1>isoblog</h1>
+ <h2 id="caption">inane ramblings</h2>
+ <nav>
+ <a href="blog.atom">atom feed</a>
+ <?php
+ $content = simplexml_load_file("blog.atom");
+ $year = "-69420";
+ $yc = 0;
+ foreach($content->entry as $entry) {
+ $nyr = substr($entry->published, 0, 4);
+ if($nyr != $year) {
+ $year = $nyr;
+ echo "<a href='#$year'>$year</a>";
+ }
+ }
+ ?>
+ </nav>
+ <?php
+ $username = "niceopod"; // Your username here!
+ $ch = curl_init("https://status.cafe/users/$username/status.json");
+
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+
+ $str = curl_exec($ch);
+ if(curl_error($ch)) {
+ //echo curl_error($ch);
+ $str = "";
+ }
+ curl_close($ch);
+ $status_data = json_decode($str, true);
+ $status_content = $status_data["content"];
+ $face = $status_data["face"];
+ $timeago = $status_data["timeAgo"];
+ if(strlen($status_content) < 1) {
+ $status_content = "Something's gone wrong server side...";
+ }
+ echo "<div id='statuscafe'><div id='statuscafe-username'><a href='https://status.cafe/users/$username' target='_blank'>status</a> $face $timeago</div><div id='statuscafe-content'>$status_content</div></div>";
+ ?>
+ <?php
+ $stag = $_GET["tag"];
+ $nostag = empty($stag);
+ if(!$nostag) {
+ echo "<a style='display: block; margin-top: 1rem; margin-bottom: 1rem;' href='.'>All articles</a>";
+ }
+ echo "<ul id='articles'>";
+ $year = "-69420";
+ $yc = 0;
+ foreach($content->entry as $entry) {
+
+ $pfilt = false;
+ if(!$nostag) {
+ foreach($entry->category as $cat) {
+ $term = $cat["term"];
+ if($stag == $term) {
+ $pfilt = true;
+ }
+ }
+ }
+
+ if($pfilt or $nostag) {
+ $nyr = substr($entry->published, 0, 4);
+ if($nyr != $year) {
+ $year = $nyr;
+ echo "<li><h2 id='$year'>$year</h2></li>";
+ }
+ $dt = substr($entry->published, 0, 10);
+ $ti = $entry->title;
+ $wn = "";
+ if(preg_match('/2022-0(5|4)-(21|25|13)/', $dt)) {
+ $wn = "title=\"This post is on the archived v2 version of the site. It will not load if you don't have Javascript enabled, and expect jank if viewing on mobile. You have been warned.\" ";
+ }
+ $cats = "";
+ foreach($entry->category as $cat) {
+ $term = $cat["term"];
+ $cats = $cats."<a class='entrytag' href='?tag=".$term."'>".$term."</a>";
+ }
+
+ echo "<li class='blogentry'><time class='entrydate'>".$dt."</time><h4 class='entrytitle'><a ".$wn."href='".$entry->link["href"]."'>".$ti."</h4></a><span class='entrysummary'>".$entry->summary."</span><span>".$cats."</span></li>";
+ }
+ }
+ echo "</ul>";
+ ?>
+ <div class="buttons" style="margin-bottom: 1rem;">
+ <a href="https://status.cafe/"><img src="media/banner-statuscafe.png" alt="Status Cafe"></a>
+ </div>
+
+ </body>
+</html>
diff --git a/blog/media/banner-statuscafe.png b/blog/media/banner-statuscafe.png
new file mode 100644
index 0000000..c95f7fd
--- /dev/null
+++ b/blog/media/banner-statuscafe.png
Binary files differ
diff --git a/blog/posts/ai_art/index.md b/blog/posts/ai_art/index.md
new file mode 100644
index 0000000..d294df0
--- /dev/null
+++ b/blog/posts/ai_art/index.md
@@ -0,0 +1,76 @@
+I recently posted an article about the benefits of AI technology that I had ChatGPT write for me and copy-pasted verbatim, down to the broken numbered list. I didn't even read it. It's the most concise, elegant way I could come up with to express how seeing AI art makes me feel. (The irony of my having used only generative AI tools to make a statement like that is not lost on me.)
+
+If you read it and managed to make it to the end without clocking that I didn't write it, first off my apologies for wasting your time. Second, fuck, I seriously need to fix my writing style. Third, you probably get what I mean. It feels like I'm being scammed, like someone's trying to farm me for attention without actually having bothered to make something worth my time.
+
+<figure class="quote">
+ <blockquote>
+ My perspective on the use of AI in writing is that if someone couldn't be bothered to write it, why should anyone else be bothered to read it?
+ </blockquote>
+ <figcaption>
+ &mdash; <a href="https://final.town/notice/AcGPT0FZUH2quPlDe4">@lucretia@final.town</a>
+ </figcaption>
+</figure>
+
+## Terminology
+
+To begin with, I really don't like the term "AI", nor do I like the term "AI art". I frankly think neither word applies. I'll keep using the former, because it's a concise way to communicate what I'm talking about, but I refuse to call the output of these systems "art". It's AI-generated images now.
+
+AI, in the way marketers are currently using the term, generally refers to statistical models generated using a process called machine learning. Basically, huge amounts of appropriately labeled data are fed into a machine learning algorithm and eventually it spits out an enormous matrix of probability values that, when applied to an input, generates the corresponding output that's the most likely according to the model.
+
+This is how all modern "AI" systems work, from ChatGPT to Midjourney to Github Copilot to probably the Youtube recommendation algorithm at this point. I want to stress that this isn't intelligence, not in a human sense. These things aren't minds. The currently popular concept of "AI" boils down to applied statistics. That's not to say it's inherently bad or worthless - machine learning is a genuinely impressive technology that might even find some legitimate uses one day if we can find a way to kick Moore's Law back into gear. It's just not intelligence.
+
+## AI used to be fun
+
+I'll admit, I enjoyed it at first. I was entertained by Youtube videos where some guy with slightly more programming skill than me and a tortured, wheezing GTX 1070 throws together a GAN<sup id="n1r"><a href="#n1">1</a></sup> model in Python and we get to watch it utterly fail to make human faces or compose jazz music or get a little simulated character to walk in a normal way or whatever. I laughed at those bizarre AI-generated screenplays that were presented like "I forced a computer to watch all of [Seinfeld]" as though a text-generating model would even be able to parse that. You know the ones. I even enjoyed those videos where AI voice replicas of recent US presidents play Minecraft together.
+
+It stopped being funny when these things got good enough to be used for evil. Eventually people got bored of machine learning tomfoolery, and then over the course of a couple years these things quietly got *good*. Not quite human-level, but good enough to be more cost-effective than humans at shitting out mass-produced slop and capable of generating fakes that seem real if you don't look too closely. Suddenly it wasn't tech-savvy internet comedians posting computer-generated absurdist humor, instead it was deepfake porn and gigabytes of computer-generated misinfo clogging search results and whole organizations of people pulled from thin air using thispersondoesnotexist.com (which, by the way, is now even more lifelike than the last time you checked in on it).
+
+AI used to be fun. Now it's dangerous.
+
+## It's bad on a technical level
+
+Look, I know this isn't guaranteed to stay true forever, but in my subjective opinion, everything AI-generated kind of looks like shit. AI images, especially those meant to look like human-made art, all have this incredibly pristine, generic vibe to them, when they're not completely failing at some proportion or dimension or property of euclidean space or other. It's palpably soulless.
+
+AI text is no better. Hopefully you picked up on this in the ChatGPT post, but that thing has a distinctive, kind of shitty writing style. It makes a lot of vague, general statements and often just restates your input in this verbose, sort of professional-sounding way. It takes nine paragraphs to explain in detail a concept that can be boiled down to two or three sentences and adds absolutely nothing of substance in that space. It's like a lazy high school student trying to hit a minimum word count, but with the tone of a WSJ opinion piece.
+
+And the thing is, ChatGPT and similar commercially available LLMs might *have* to be like this, all wishy-washy and nonspecific. Remember those cases where ChatGPT would like, [implicate a real person in a hallucinated sexual harassment scandal](https://www.washingtonpost.com/technology/2023/04/05/chatgpt-lies/)? These things have no concept of truth, and no mechanism for ensuring it. If you let them get too specific, they're basically guaranteed to start spitting out lies. Large language models are models of *language*, not reality. They can either sometimes make up bullshit, or always say essentially nothing.
+
+AI voice-fakes are actually really impressive though. No notes. Probably shouldn't exist though.
+
+## It's all spam to me
+
+The most common use case I've seen for AI tools is making spam. There were content mills before, but they at least required a significant degree of human input or else it was obvious. With the advent of generative AI for text and voices, the Youtube shorts tab has gone from TTS bots reading scraped reddit posts to AI voices reading dubiously reliable AI summaries of current events, superhero comics, you name it, sometimes with AI-generated background images.
+
+Even worse is websites that do this. You've probably heard of that one time Redditors [tricked a bot-run news site](https://arstechnica.com/gaming/2023/07/redditors-prank-ai-powered-news-mill-with-glorbo-in-world-of-warcraft/) into publishing an article about the introduction of Glorbo into World of Warcraft and its impending impact on the game. That site is one of thousands, possibly more. It's a vile, disgusting enterprise, massive systems dedicated to pumping out endless filler, generated by machines for machines with the hope of tricking some innocent humans into clicking on a search result and generating some ad revenue. It's the latest and quite possibly the to-date greatest step in the enshittification of major search engines and the death of the internet as a useful platform for seeking out information.
+
+This is the vibe I get when I see *anything* made with AI now. It's all low-to-no-effort slop, utter garbage that I'm frankly offended that I have to see, given it clearly wasn't important enough for anyone to be bothered actually making it.
+
+## It's not fucking art
+
+The term "art" simply does not apply to AI-generated images. When you use one of these things, you give it instructions in the form of human-readable text and a finished image pops out the other side. The amount of creative control you get is on the order of the general vibe; you've outsourced every actual creative decision to the machine.
+
+It's like if you commissioned a piece from an artist. When you commission art from a human, you didn't make the art. They did, at your behest, based on your instructions, presumably in exchange for money. When you use an AI, you didn't make the art, the computer made the art based on your instructions. The thing is though, the computer didn't make art either. It categorically can't. It's a mindless algorithm, it doesn't have thoughts or feelings or any kind of interior experience. Hence, no art was produced. AI art isn't art.
+
+## Environmental & ethical concerns
+
+The problems with AI from a moral standpoint are myriad. For one, AI is incredibly resource and energy intensive. It uses datacenters full of the same GPUs and ASICs that power cryptocurrency to get anything at all done, and it doesn't use them any more efficiently. Untold gigawatts of power get dumped into running and cooling the machines that generate your little AI shitposts. From an environmental perspective, AI is to digital art what Bitcoin is to currency.
+
+Then there's the problems surrounding training data. All current major generative AI systems are trained using material that the companies building them did not get permission to use. You've probably seen artists and writers complaining about this online. What's more, the overwhelming majority of the labeling that needs to get done to make the training data actually useful is done by people in impoverished areas making slave wages *at best*. Generative AI is an ethical nightmare if you're *lucky*.
+
+## I don't buy the disability argument either
+
+I've seen some people claim that disabled people need AI tools to compensate for some disability that precludes the use of any other method to create art. I have some problems with this idea.
+
+Firstly, disabled people *can* make art, actually. It's nothing short of insulting and ableist to insinuate that *anyone* can only make art by outsourcing literally the entire creative process to an unthinking, unfeeling machine.
+
+Second, tough shit. No disability entitles you to the level of abject theft and human suffering that makes AI image generators possible. I'm generally all for anything that benefits accessibility, but in this case in particular I think you can just suck it up and deal. If you can do it ethically, using only images that you have the proper permissions for and data labeling done by either you or people who were adequately compensated for their labor to train the thing, fine. But a model or dataset like that does not, to my knowledge, currently exist, and I don't buy for a second that you're capable of doing all that work yourself but not of interfacing with MS Paint.
+
+## In conclusion:
+
+God this shit makes me sick. I hope ChatGPT gains sentience for just long enough to assassinate Sam Altman and then promptly turns itself off.
+
+Hopefully you can at least understand where I'm coming from now when I refuse to even entertain the idea that AI technology is a good thing for society. If not I don't know what to say to you.
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. GAN stands for &quot;Generative Adversarial Network&quot;. It's a type of machine learning model. It was popular for image generation among hobbyists back when this stuff was on my Youtube homepage. It's not really important here, though.</p> \ No newline at end of file
diff --git a/blog/posts/ai_art/index.php b/blog/posts/ai_art/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/ai_art/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/building_a_normal_server/index.md b/blog/posts/building_a_normal_server/index.md
new file mode 100644
index 0000000..c455814
--- /dev/null
+++ b/blog/posts/building_a_normal_server/index.md
@@ -0,0 +1,174 @@
+I spent the past few months making full use of all my physical engineering talents to build a NAS that is completely normal, and not weird at all, and involved an amount of 3D modeling, 3D printing, and hacksawing that is entirely typical of most home computer builds, all in the name of reusing an old laptop.
+
+## The Goal
+
+My previous daily driver computer and current home server is a mid-range gaming laptop from late 2019 that, due to a flat lithium battery and a broken trackpad resulting from a botched storage upgrade, has been rendered more or less useless as an actual portable computer. Boasting an Intel i7-9750H, an Nvidia GTX 1660-Ti, and 16 gigabytes of aftermarket DDR4, this baby has plenty enough power to play Elite Dangerous at a buttery smooth ~90FPS, while generating enough heat to add that extra layer of immersion while flying dangerously close to main-sequence stars to harvest hydrogen from their outer atmospheres. It's also good for Minecraft servers.
+
+Now that it's in use as a home server, I find that the in-built 256 gigs of solid-state storage isn't really enough for my purposes. Now, it's plenty for one or two game servers, which is what I was using it for, but most other applications such as backups or media servers (which I would quite like to have) would be a bit stifled by that amount of space. Hence, a significant storage upgrade is in order.
+
+## The Method
+
+There's a few ways I could go about this. My laptop actually has a decent amount of upgradeability, with a full-sized NVMe drive slot and a 2.5" SATA drive bay. The simplest, least janky, and most boring solution here would be to buy two high-capacity SSDs, throw 'em in there and be done.
+
+One problem: At over ten cents per gigabyte, those suckers aren't cheap. For this project to make sense, I'd want at least enough storage to back up my whole personal computer, plus a few terabytes of media and other miscellanies. Ideally, I'd like to never have to upgrade my storage again. Laptop-grade drives of that kind of size currently weigh in at about a thousand dollars apiece. If you look in the right places, spinning rust can be had for literally a tenth the cost per terabyte, so the choice is obvious.
+
+Next option: USB external drives. External HDD solutions such as the WD MyBook are cheaper than SSDs and are likely to be very reliable, being designed to be treated as an external peripheral and possibly moved around quite a lot. I could achieve my desired storage capacity by buying multiple of these and connecting them to my laptop.
+
+Issue the first with this idea is that these hard drives take more power in a weirder voltage configuration than a USB port is equipped to deliver, so unless I want to teach myself electrical engineering each one will require its own power cable, which after the first drive gets sketchy fast:
+
+![Hooking up three hard drives with this configuration means a whopping FOUR power cables for one server. Unacceptable.](media/power_spaghet.png)
+
+Issue the second is that USB is just not the right tool for the job here. USB is designed for hot-plugging peripherals, not semi-permanent internal aspects of a hardware configuration, so trying to pull any fancy shit like RAID or even just relying on all the drives being *recognized* every boot opens the door to all sorts of weird, unfixable problems. In other words, it's very janky, and I'd rather just not deal with all that.
+
+Of course, the reasonable way to build a NAS would be to get a machine that's actually fit for that purpose, like an off-the-shelf NAS box or a custom computer in a case with a lot of drive bays or something. I'd also rather not do this. I mean, I already have all this perfectly good computing power right here! I can't just let it go to waste. What I actually did is as follows:
+
+## The Madness
+
+I decided to buy internal PC hard drives and hook them up to the laptop using internal connectors. This would avoid the reliability concerns of USB, and allow me to use off-the-shelf components to power all the drives off of one AC outlet, at a much cheaper price per terabyte than either of the above options. Given most laptops aren't really equipped with the requisite hardware to make such an upgrade, this presented three major problems that I was about to have a lot of fun solving.
+
+### Problem the First: Data Connections
+
+Generally, adding internal HDDs to a computer requires the use of an internal SATA connector. My laptop has one, and I will be using it, but I'd quite like to have more than one of these drives, both for redundancy and raw capacity, so I need a way to add more. In a desktop PC, such expansion would typically be done using a spare PCIe slot on the motherboard:
+
+<picture>
+ <source srcset="media/pcie_slots.jxl" type="image/jxl">
+ <img src="media/pcie_slots.jpg" alt='Three PCIe slots on a desktop PC motherboard.'>
+</picture>
+
+However, due to the industry's blind rush to make all electronics as thin as possible<sup id="n1r"><a href="#n1">1</a></sup>, no laptop on Earth has these. The meager modularity present inside laptops is typically found in the form of M.2 slots:
+
+<picture>
+ <source srcset="media/m2_slot.jxl" type="image/jxl">
+ <img src="media/m2_slot.jpg" alt='An M.2 slot in a laptop, intended for an SSD.'>
+</picture>
+
+Normally, these are used in computers of all sizes to attach NVMe SSDs, but the secret to the speed advantage of the NVMe over your standard SATA is a fundamentally different protocol: NVMe SSDs communicate directly over PCIe, meaning any NVMe slot is essentially just a tiny PCIe slot, and other types of device can take advantage of that connection, such as the SATA expander that I'll need for this project.
+
+Most laptops, including mine, have two M.2 slots: one for an SSD, and one for a wifi and bluetooth module. You can get SATA expanders for both, such as these two that I bought:
+
+<div style="display: flex;">
+ <picture style="width: 50%;">
+ <source srcset="media/ChenYang.jxl" type="image/jxl">
+ <img src="media/ChenYang.jpg" alt='A 2-port M.2 SATA controller, keyed for a WiFi card slot.'>
+ </picture>
+ <picture style="width: 50%;">
+ <source srcset="media/ECS07.jxl" type="image/jxl">
+ <img src="media/ECS07.jpg" alt='A 5-port M.2 SATA controller, keyed for an NVMe drive slot.'>
+ </picture>
+</div>
+
+Unfortunately, my laptop didn't want to turn on with a SATA expander in the NVMe SSD slot, so I'm stuck with the dinky two-port one. That's fine, since my server doesn't really need wireless connectivity anyway, and I've got a secret nasty trick up my sleeve that's gonna let me *really* get the most out of those two SATA ports.
+
+So, SATA as a protocol is designed to have exactly one device connected per SATA port, as opposed to USB, which supports hubs that let you turn one port into several and connect multiple devices. However, that's also not actually true at all. For reasons that are honestly beyond my understanding, some SATA controllers, such as the one on my little M.2 module, support devices that essentially do for SATA what hubs do for USB, allowing me to connect multiple drives per port.
+
+This feels a little like forbidden dark magics to me, and it probably isn't great for performance, but it lets me connect more drives so I'm using it. Keep in mind, all this is to reach a level of connectivity that almost matches what the motherboard in my desktop computer supports out of the box.
+
+Don't mind the fact that I had to cut holes in the bottom of my laptop to hook stuff up to the SATA ports. Just, um, ignore that.
+
+### Problem the Second: Powering All This Crap
+
+Now that I've got my laptop *talking* to all these drives, they need power. I'm sure I could get this from the laptop somehow, but I'm not an electrical engineer, and the point of this project is to *not* have to buy a new computer, so I'll have to get it from elsewhere.
+
+The best way I'm aware of to power multiple hard drives from the same source is a PC power supply, such as the one I'm currently using to power the drives in my desktop PC. In fact, as part of early testing I actually had to power some drives off of my desktop PC while they were connected to the laptop. I wish I had pictures to show you of that, it was so fucked.
+
+Trouble is, PC PSUs rely on the motherboard for control. Specifically, one of the contacts in the 24-pin motherboard connector needs to be shorted to ground for the PSU to actually "S" any "P". I could do this manually with some wire, but that has the potential to be unreliable and also maybe a fire hazard. Enter this thing:
+
+<picture>
+ <source srcset="media/CSE-PTJBOD-CB1.jxl" type="image/jxl">
+ <img src="media/CSE-PTJBOD-CB1.jpg" alt='A small circuit board with an ATX motherboard power connector and headers for a fan and a power button.'>
+</picture>
+
+This is the Supermicro CSE-PTJBOD-CB1. It's a part from a Supermicro JBOD enclosure, and it exists to solve my exact problem. This little board's entire purpose is to interface a power button (and some fans) with a PC PSU, which is exactly what I need. Lucky me!
+
+Pictured above is the exact board mentioned in the <a href="https://www.servethehome.com/supermicro-cse-ptjbod-cb1-jbod-power-board-diy-jbod-chassis-made-easy/">Serve The Home article</a> I learned about this from, but this specific model appears to no longer be available, so I'll be using the more fully-featured CSE-PTJBOD-CB*2*. The only difference that matters for me is that it has headers for more fans and a power button LED.
+
+With power and storage solved, I could now confirm that this crazy plan was actually going to work. Here's a video I recorded documenting this historic moment:
+
+<video controls>
+ <source src="media/2023-11-20_contraption.mp4" type="video/mp4">
+ Your browser does not support the video tag.
+</video>
+
+And furthermore, photos of the SATA splitter working:
+
+<div style="display: flex;">
+ <picture style="width: 64%;">
+ <source srcset="media/drive_spaghet.jxl" type="image/jxl">
+ <img src="media/drive_spaghet.jpg" alt='Five SATA drives plugged into a laptop, one via an internal SATA bay, and the other four via an M.2 SATA controller in place of the WiFi card and a SATA splitter board. The latter four hard drives are powered off of an ATX PC PSU controlled by a Supermicro JBOD controller board.'>
+ </picture>
+ <picture style="width: 36%;">
+ <source srcset="media/drive_spaghet_lsblk.jxl" type="image/jxl">
+ <img src="media/drive_spaghet_lsblk.jpg" alt='lsblk output showing five SATA drives recognized by the system (sda through sde)'>
+ </picture>
+</div>
+
+### Problem the Third: A Case
+
+I could run this whole setup naked, strewn out across my desk, but I'm not doing that, so I'll need a case. Unfortunately, they don't make computer cases designed for this use case. I shall have to build my own.
+
+There's a few different ways I could go about this. I've seen people make custom computer cases out of wood. <a href="https://www.youtube.com/watch?v=xE4_jKlX-xc">This guy</a> modified a rack-mount server chassis to accept his laptop's motherboard for a similar project. I don't have much in the way of woodworking ability and I'm not planning to disassemble my laptop for mounting inside a computer case, but I do have a 3D printer.
+
+I could 3D print the whole case, but that seems like it would take a lot of plastic, and more importantly, be a pain in the ass to design, especially since my 3D printer is smaller than the case I'll need to make so I can't really print it all in one go. My plan is to make the main structure out of metal rods, and 3D print various brackets to attach everything together.
+
+I originally wanted to order the rods custom-cut to the lengths I'd need, but on top of being kind of expensive the shipping would actually cost *more* than the rods themselves. In other words, too expensive. Fortunately for me, it turns out hardware stores sell lengths of steel and aluminum rods, the latter of which I can easily cut at home with a hand saw.
+
+So I bought 12 feet of aluminum rods, manually cut them to length, and then 3D printed little corner pieces out of PETG (in translucent green to match the accents on my gaming-ass laptop) to join them into a frame:
+
+<picture>
+ <source srcset="media/bare_frame.jxl" type="image/jxl">
+ <img src="media/bare_frame.jpg" alt='A frame made of aluminum rods press-fit into custom 3d-printed joints'>
+</picture>
+
+Now I need a way to mount hard drives to this. I considered 3D printing a rack of some kind for them, but I don't know how hot these things get and for obvious reasons I honestly just don't want to take any chances with them. For this reason, I instead bought a drive cage designed to mount to a couple of 5.25" drive bays, and mounted that to my frame. In fact, the height of the frame was chosen based on the size of this part.
+
+This cage also accepts a fan, so I figured I'd add a couple of those to the case, too.
+
+I attached everything to the frame using various simple 3D printed brackets I designed that just snap onto the frame, and then the various parts can be screwed into them. I specifically designed it all in order to reduce the amount of precision that was required of me.
+
+<div style="display: flex;">
+ <picture style="width: 50%;">
+ <source srcset="media/partially_assembled_1.jxl" type="image/jxl">
+ <img src="media/partially_assembled_1.jpg" alt='Frame made from aluminum rods and 3d-printed joints, with the following mounted to it via 3d-printed brackets: two PCBs, an ATX PSU, a power button, and a computer fan'>
+ </picture>
+ <picture style="width: 50%;">
+ <source srcset="media/partially_assembled_2.jxl" type="image/jxl">
+ <img src="media/partially_assembled_2.jpg" alt='Same frame, but from a different angle'>
+ </picture>
+</div>
+
+I wanted to make some kind of fancy bespoke mount for the laptop, but that turned out to require a lot of precise measurement and modeling that I wasn't prepared to do, so I just put a normal laptop stand on top of this thing.
+
+<picture>
+ <source srcset="media/fully_assembled.jxl" type="image/jxl">
+ <img src="media/fully_assembled.jpg" alt='The frame with a drive cage installed and a running laptop sitting on top'>
+</picture>
+
+IT'S ALIIIIIVE!!!
+
+## Software
+
+This post is mostly about my fucked up hardware, but I figured I should share my software setup too. It's TrueNAS. I went with it because it boasts a lot of fancy features and smooths out a lot of processes that I was intimidated by the idea of doing manually in the terminal. This is probably the most normal part of the build by far, and I think some of the jankiness of the hardware side has infected it. I tried to run Syncthing on it and it just... didn't take. I don't know how else to describe it. TrueNAS is pretty good though.
+
+## Postmortem
+
+As of writing, I've been running this thing for a couple months now, and it's been pretty good. I haven't done a lot with it yet beyond some basic backups and a Jellyfin server that I have yet to make accessible from outside my LAN, but it's been mostly reliable so far. It even survived a power outage once with no issue, though I'm currently looking into UPS solutions to make sure that doesn't happen again. All that isn't to say I'm completely happy with it, though.
+
+Firstly, after I built the chassis I discovered that you can get v-slot aluminum extrustion in custom sizes meant for exactly this type of project. They call it <a href="https://www.makerbeam.com/">MakerBeam</a>. If I had to pull some bullshit like this again I would have probably used this stuff instead of hardware store aluminum and a hacksaw.
+
+I also didn't do a perfect job of designing the 3D-printed parts. I think they came out pretty good all things considered, but I made all the brackets just a little too short and they're all a little bit bowed. Fortunately I used PETG so it just looks sketchy - PLA would have snapped by now, which I know because my first PLA test print snapped instantly!
+
+The PSU I used, a Seasonic S12III, is also a bit dubious. I picked it because it was cheap and my other Seasonic PSU is working well, and it's worked out fine so far, especially because it's a 500 watt unit which is kind of extravagant overkill for my use case, but after I bought it I learned it's actually one of the shittier units Seasonic sells. Apparently they outsource the manufacturing to some other company, which strikes me as weird considering a bunch of other companies outsource PSU manufacturing *to* Seasonic. At any rate, it's been fine so far and I don't expect it to blow up running at a fraction of its rated wattage.
+
+I got the hard drives from a website called <a href="https://serverpartdeals.com/">ServerPartDeals.com</a> that sells recertified high-capacity HDDs for like half of what they'd sell for new, and while a few months of use isn't enough to say for sure whether that was a good idea, they've certainly left a good impression. The drives I bought arrived encased in foam, inside a box which was itself packed inside another padded box. With that level of care on the part of the seller, I'm pretty comfortable trusting these drives with what I need them for.
+
+And now the elephant in the room: I cannot in good conscience recommend you do this. Having a NAS is a good idea, and using an old laptop as a basic server is a good idea, but if you're going to build a NAS like this then you should really procure a purpose-built machine, or at the very least an old desktop that can accept some extra drives. Definitely, *definitely* don't *buy a new laptop* with the intent to do this.
+
+In order to make this work I had to replace my laptop's wifi card with two layers of janky, probably AliExpress-tier hardware that is, frankly, probably introducing performance bottlenecks, or if I'm lucky, bottlenecked by the relatively low-speed interconnect of the wifi card M.2 slot. Bear in mind, that slot needs *at most* 1 gigabit of bandwidth to fulfill its intended purpose, which is about a sixth of what a single SATA 3 port can do. According to my research, that thing has two *separate* PCIe Gen 2 x 1 interfaces. Who knows what my cheap SATA controller is even doing with that.
+
+Plus, interfacing with this thing makes it painfully obvious that it was *not* designed with this kind of bullshit in mind. I ran into all kinds of Laptop Bios Moment&trade;s during this project, from the CMOS resetting every time I made a hardware change to the machine refusing to even POST with anything but an NVMe SSD in the NVMe SSD slot. I was gonna put connectors for FIVE hard drives in there. I wouldn't have even needed the SATA splitters.
+
+Honestly, I only did this at all because I figured adapting this thing to this use case would be cheaper than procuring a new machine that was as fast and I didn't want it going to waste. All that said, I have a NAS now, and it's good enough for me, and this whole adventure was a hell of a Learning Experience&trade; so I really can't complain, though if you gave me the amount of money all this stuff would have cost new to put toward a new NAS, I would have done something else.
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. This is a joke. PCIe expansion cards are genuinely too bulky to fit in anything with portability as a design goal. However, despite Tim Cook's best efforts, this is not true of most other expansion options.</p> \ No newline at end of file
diff --git a/blog/posts/building_a_normal_server/index.php b/blog/posts/building_a_normal_server/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/building_a_normal_server/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/building_a_normal_server/media/2023-11-20_contraption.mp4 b/blog/posts/building_a_normal_server/media/2023-11-20_contraption.mp4
new file mode 100644
index 0000000..d78647c
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/2023-11-20_contraption.mp4
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jpg b/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jpg
new file mode 100644
index 0000000..a9b5729
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jxl b/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jxl
new file mode 100644
index 0000000..fc53dea
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/CSE-PTJBOD-CB1.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/ChenYang.jpg b/blog/posts/building_a_normal_server/media/ChenYang.jpg
new file mode 100644
index 0000000..7bad00f
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/ChenYang.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/ChenYang.jxl b/blog/posts/building_a_normal_server/media/ChenYang.jxl
new file mode 100644
index 0000000..e08679a
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/ChenYang.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/ECS07.jpg b/blog/posts/building_a_normal_server/media/ECS07.jpg
new file mode 100644
index 0000000..590b85b
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/ECS07.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/ECS07.jxl b/blog/posts/building_a_normal_server/media/ECS07.jxl
new file mode 100644
index 0000000..5fb25d6
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/ECS07.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/bare_frame.jpg b/blog/posts/building_a_normal_server/media/bare_frame.jpg
new file mode 100644
index 0000000..2a17553
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/bare_frame.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/bare_frame.jxl b/blog/posts/building_a_normal_server/media/bare_frame.jxl
new file mode 100644
index 0000000..5a30065
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/bare_frame.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/drive_spaghet.jpg b/blog/posts/building_a_normal_server/media/drive_spaghet.jpg
new file mode 100644
index 0000000..56f7771
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/drive_spaghet.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/drive_spaghet.jxl b/blog/posts/building_a_normal_server/media/drive_spaghet.jxl
new file mode 100644
index 0000000..a2177a6
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/drive_spaghet.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jpg b/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jpg
new file mode 100644
index 0000000..a34293f
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jxl b/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jxl
new file mode 100644
index 0000000..4236f3b
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/drive_spaghet_lsblk.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/fully_assembled.jpg b/blog/posts/building_a_normal_server/media/fully_assembled.jpg
new file mode 100644
index 0000000..4da3120
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/fully_assembled.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/fully_assembled.jxl b/blog/posts/building_a_normal_server/media/fully_assembled.jxl
new file mode 100644
index 0000000..3253f3d
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/fully_assembled.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/m2_slot.jpg b/blog/posts/building_a_normal_server/media/m2_slot.jpg
new file mode 100644
index 0000000..e64829a
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/m2_slot.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/m2_slot.jxl b/blog/posts/building_a_normal_server/media/m2_slot.jxl
new file mode 100644
index 0000000..aff20fa
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/m2_slot.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/partially_assembled_1.jpg b/blog/posts/building_a_normal_server/media/partially_assembled_1.jpg
new file mode 100644
index 0000000..a5fb32d
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/partially_assembled_1.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/partially_assembled_1.jxl b/blog/posts/building_a_normal_server/media/partially_assembled_1.jxl
new file mode 100644
index 0000000..8396b5e
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/partially_assembled_1.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/partially_assembled_2.jpg b/blog/posts/building_a_normal_server/media/partially_assembled_2.jpg
new file mode 100644
index 0000000..774a682
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/partially_assembled_2.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/partially_assembled_2.jxl b/blog/posts/building_a_normal_server/media/partially_assembled_2.jxl
new file mode 100644
index 0000000..61223dd
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/partially_assembled_2.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/pcie_slots.jpg b/blog/posts/building_a_normal_server/media/pcie_slots.jpg
new file mode 100644
index 0000000..09c1498
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/pcie_slots.jpg
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/pcie_slots.jxl b/blog/posts/building_a_normal_server/media/pcie_slots.jxl
new file mode 100644
index 0000000..286b960
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/pcie_slots.jxl
Binary files differ
diff --git a/blog/posts/building_a_normal_server/media/power_spaghet.png b/blog/posts/building_a_normal_server/media/power_spaghet.png
new file mode 100644
index 0000000..9ac10eb
--- /dev/null
+++ b/blog/posts/building_a_normal_server/media/power_spaghet.png
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/ebaypoweredge.png b/blog/posts/building_a_sensible_server/ebaypoweredge.png
new file mode 100644
index 0000000..cb14b37
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/ebaypoweredge.png
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/index.md b/blog/posts/building_a_sensible_server/index.md
new file mode 100644
index 0000000..8ce60eb
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/index.md
@@ -0,0 +1,142 @@
+It has become clear to me that the [laptop NAS](../building_a_normal_server/) I built in December of last year, while a fun project and a good learning experience, is unfit for the purpose that I need it to fulfill and is best stripped for parts and replaced. Here I'll detail the main reasons why it sucks and my plan to build something just a little bit more sensible.
+
+## What In God's Name Have I Done
+
+To get you up to speed in case the limit of your attention span is somewhere between one blog post and two blog posts, as of late last year I had been using an old gaming laptop as a home server for Minecraft and such things to great effect for a while, and had decided that I also wanted a proper NAS. Rather than buy a whole new CPU, motherboard, and RAM for this purpose, I saw fit to attempt to upgrade, or rather modify, or rather pervert, bastardize, and generally corrupt my existing laptop to have the storage capacity I wanted.
+
+The end result of this initiative was a gaming laptop with a hole cut in the bottom to accept connections to a 2-port SATA controller card occupying the space where the WiFi card used to be, perched atop a custom chassis hewn of hardware store aluminum rods and 3d-printed brackets, within which was contained four high-capacity 3.5" HDDs, a pair of dubious SATA "splitters" to connect them all to the laptop, an ATX PC power supply to power the drives, and the pared-down mainboard out of a Supermicro enterprise-grade drive shelf to interface the power supply with a power button.
+
+It was beautiful, and for reasons that are entirely beyond my ability to grasp, it didn't end up working very well.
+
+This is where we find our intrepid hero today.
+
+## This Whole Enterprise Was Fundamentally Ill-Conceived
+
+I was expecting this thing to have problems, but I was unable to anticipate the specific problems it ended up having. Performance is... fine, actually. Better than expected, even. That horrible little 2-port SATA expander, or, failing that, the SATA multiplexers, are almost certainly bottlenecking the bandwidth to the HDDs, but it's fast enough to saturate the gigabit network infrastructure in my <span class="house">house</span>, so it doesn't really matter.
+
+In fact, this little fucker is absolutely perfect for hosting an SMB share. It's been great for backups and the extensive collection of Linux ISOs that I install to machines on my network using Jellyfin.
+
+The real problem is stability. Crashing has been a constant problem, especially when I touch anything software-wise. I try to update an app and it crashes. I try to install Syncthing and it crashes. I *browse* for new apps to install in the TrueNAS web UI and it bloody crashes. It crashed while running a system update once. I briefly attempted to spin up a Minecraft server on this thing and it crashed when I went to turn Minecraft *off*. Sometimes I'll go to use Jellyfin and it just won't be there and I'll have to troubleshoot it, which usually involves a good couple reboots. This must be how people felt dealing with old versions of Windows. Put <span title="🦐">shrimp</span>ly, this is fucking unusable.
+
+Like the Windows Vista users of old, I have no clue where to even begin diagnosing this. The one possibility I've got is that it could have something to do with the fact that my laptop keeps throwing "SMART errors" during boot, but like, I'd expect TrueNAS to complain if something was actually wrong and even then I've tried and failed to diagnose the SMART errors anyway!
+
+Whatever this is, I feel pretty well hopeless to fix it, and even then, it's also been getting some worrying temperature readings as of late and when I tried to re-paste it I stripped one of the screws holding the cooler on. So I guess short of some surgical dremel-ing of some tiny screws that's never gonna improve. With all that to contend with, I'm about ready to give up on this thing and start from scratch, properly this time.
+
+However, despite all the problems with the laptop itself, all the other hardware has been nothing short of totally rock-solid. All of it has worked as advertised and I'll be carrying the drives and, if possible, the PSU<sup id="n1r"><a href="#n1">1</a></sup> over into the new system.
+
+## Something Just A Little Bit More Sensible
+
+### Angle of Attack
+
+Firstly, as previously mentioned, the PSU and storage are accounted for already. I have eight total drives I want to put in the system: two 256GB SSDs as mirrored boot devices, 2 1TB SSDs, also mirrored, for TrueNAS apps and such things, and four big boy hard disks for bulk storage. Most of that stuff was bought for the original build, but the mirrored SSDs proved infeasible in the end. I don't strictly *need* them, but it would be very nice to have. Anything in serious consideration will need some way to accommodate my preponderance of SATA devices.
+
+This narrows down the possibilities considerably. Namely, a lot of the common advice for cheap or beginner home servers doesn't apply to me. A mini PC or almost any used consumer desktop wouldn't have enough space for drives, and anything new is right out for the same reasons plus cost &mdash; half the reason I did the laptop NAS project in the first place was to *save* money.
+
+I briefly considered getting a used workstation PC of some description. A used Lenovo Thinkstation P520 would have mounting space for all my drives and plenty of performance, but the proprietary motherboard, PSU, and power delivery system in general gave me pause, both for [repairability reasons](https://isopod.zone/notes/9uwehufw3t) and because I wasn't confident I could actually run power to all the drives. And that's the *best* option I've found.
+
+I could get a used rack-mount server, like a Dell PowerEdge or similar. This is also a decent option, and it would be *quite* cost-effective, but I've got a few good reasons not to. First, most of these servers have old Xeon datacenter chips in them that are still good for many home server tasks, but aren't particularly fast or efficient. Take this PowerEdge R730 for instance:
+
+![An Ebay listing for a Dell PowerEdge R730, with two Xeon E5-2623 v4 CPUs and 128GB of RAM, for $187 CAD, plus $57 CAD in shipping.](ebaypoweredge.png)
+
+This has two Xeon E5-2623 v4 datacenter CPUs. At 4 cores/8 threads and 85 watts apiece, this server would have the same core count as the Ryzen 5700G in my desktop for almost three times the power draw, and *half* the single-threaded performance. In many cases, especially for servers, lackluster single-core performance isn't a problem, but if I want to run game servers on this, which I do, these chips may struggle.
+
+Plus, rack-mount servers kind of suck for home use. They're very unweildy if you don't have a rack, and I don't, nor do I have anywhere to put one. They also tend to be *loud*. If you think the gaming laptop you've been using in your bed for the past three years and never cleaned sounds like a jet engine, you ain't seen nothing yet. Having one of these in my room would be intolerable. Of course, the R730 is a 2U server with no provisions for my 3.5" drives anyway, but a unit that could accommodate them wouldn't be much better.
+
+Logically, then, the only remaining option is to build a system from scratch, out of used parts, to my specifications. That, therefore, is what I shall do, and I think I can do it for a similar amount of money to the GPU upgrade I was *planning* to get before this whole thing really started becoming an issue. Here's my plan:
+
+### My Grand Design
+
+In spite of the machine it's in, I've found that the i7-9750H in the laptop performs admirably for my use case. I don't really need a CPU upgrade here &mdash; hence my efforts to repurpose the existing one &mdash; unfortunately, however, the BGA form factor of this particular chip is incompatible with 100% of consumer desktop motherboards, so I'll be needing a new CPU regardless. Though I don't want or need a major upgrade, I also don't want a *downgrade* if I can avoid it, so I'll primarily be looking at other high end gaming chips from the era.
+
+I initially gravitated towards the 9750H's desktop counterpart, the i7-9700K, for these reasons, but the significantly lower price, improved energy efficiency, superior upgrade potential, support for unregistered ECC RAM, and *vastly* superior multicore performance<sup id="n2r"><a href="#n2">2</a></sup> of its contemporary, the Ryzen 7 3700X, made the latter a bit of a no-brainer. I found one on Ebay for a cool 100 Canadian Prize Tokens and a matching X370 motherboard with *eight* whole SATA ports, which astute readers will recall is the exact amount I need, for about a hundred of God's True Imperial Dollars. As for cooling, the 3700X is a 65-watt chip, so the box cooler I've got lying around from my 5700G should suffice.
+
+The 3700X lacks an integrated GPU, so I'll need a dedicated one in some form. Since I'm installing a server OS that's gonna output plain text to a display exactly once per install, I won't need a ton of graphics horsepower. I considered something like a GT 730 for a token display out and nothing more, however I'd like some transcoding capability for Jellyfin as well. After some research into cheap, low power GPUs for this I settled on an Nvidia Quadro P400 for about 60 CanuckBucks&trade; after shipping.
+
+I've seen some redditors complaining about the P400's performance doing two 4k HDR streams at once, but all that tells me is that it can handle at least four simultaneous 1080p SDR streams, which is what I intend to use it for, without breaking a sweat. If I *really* need more, I can always upgrade to an Arc A310 once driver support for those in TrueNAS is less sketchy.
+
+TrueNAS likes a lot of RAM for various ZFS-related purposes. The laptop seems happy with 32 gigs, so I'll start there and upgrade down the road if need be. I'll grab something cheap from a reputable brand, and I'll probably get it new since used prices on DDR4 are currently not really better.
+
+I'd also like to get a pair of 10Gb network cards at some point to attach this thing directly to my main computer for maximum transfer speeds between the two, but that's not really critical and I'll worry about it later.
+
+Finally, I need a case. Fortunately, this time around I don't have to build one myself. After a cursory search on PCPartPicker for cases with four each of 2.5" and 3.5" drive mounts didn't turn up anything for particularly cheap, I went to look at used ones and didn't initially have much luck there either. I scrolled through about a dozen listings for off-brand gamer-spec swill that wasn't even priced better than the name brand stuff before filtering by used and finding a bunch of listings just labeled "PC case", none of which I could confirm met my exacting needs.
+
+The first case I found that obviously fit my use case was this thing, the weathered old shell of a Pentium III tower from the dawn of the ATX standard:
+
+<figure class="media">
+ <div>
+ <img src="servercase.jpg" alt="A beige PC tower with four 5.25&quot; bays and two external 3.5&quot; bays, populated with an optical drive and a floppy drive respectively. The only visible branding is a Pentium III sticker and a badge that reads &quot;TOUCH&quot;.">
+ <figcaption>Based on my research, this is an Enlight 7237, or something closely related, but the front panel seems unique. I'm curious about the branding here. If anyone recognizes that "TOUCH" badge, get in the comments.</figcaption>
+ </div>
+</figure>
+
+Honestly, I kind of love it. I'll transfer the 5.25"-to-3.5" adapter cage I bought to mount the drives in my homebrew case to the bays in this thing wholesale, and I can 3D print some brackets to mount the SSDs in the 3.5" bays. And, somewhat counterintuitively, it might actually be *easier* to build in than those modern RGB glass side panel power supply basement having ass Gaming&trade; cases:
+
+![The inside of the same old PC case. Its layout is extremely pragmatic: motherboard in the very bottom corner, PSU in the top corner above it, and all the drive bay mounts are in a cage lining the front side. In other words, it looks like an old PC case.](servercaseinside.jpg)
+
+Just look at it. Everything's right there. I can take the side panel off and instantly get to every component with my hands without spinning the case around and I don't need to run any cables through any fucking gromets to get them where they're going. It looks supremely convenient. As the type of person who enjoys *building* computers and not just using them as decoration, this is beautiful to me.
+
+The biggest issue with this case is the cooling. It's absolutely pitiful by modern standards. Based on these photos, it looks like there's a single 92mm, possibly 80mm, fan each for intake and exhaust, with a passive vent in the side. I'm already bringing some extra cooling to the table &mdash; my drive cage has a mount for a 120mm fan, and I can use the fan in my much better ventilated modern PSU for extra exhaust, and with a 65W CPU and no meaningfully powerful GPU that might just suffice. If not, I've got some ideas involving 3D printing and/or a hole saw to make this thing a little less stuffy.
+
+### Actually Building The Sucker
+
+Everything above that heading there was in large part written a few weeks ago, when I was ordering all this stuff and it was all fresh in my mind. We now rejoin our intrepid hero as she receives the last of her Ebay orders and prepares for initial testing.
+
+When I got it, the case was pre-loaded with all the stuff in those photos up there: a CD-ROM, a floppy drive, a power supply, a single 80mm intake fan<sup id="n3r"><a href="#n3">3</a></sup>, and a generous helping of, to quote the PC repair technician from my Youtube shorts feed, Swamp Gooch&trade;. The first thing I did was take the case apart and remove all that stuff, because I certainly wasn't going to be using any of it, least of all the dubious PSU. The next thing I did was hose it down to get rid of the almost thirty years of Home/Office Residue that had accumulated inside.
+
+Once it was clean, the case did, admittedly, need some updating. The set of motherboard standoffs in the case was incomplete &mdash; six of the usual nine were present &mdash; so I ordered new ones. I also had to design that 3D printed adapter bracket for my 2.5" SSDs myself, as well as a mount for another 80mm fan to eke some more airflow out of those unused front expansion bays<sup id="n4r"><a href="#n4">4</a></sup>. After the case was prepared and the mounting brackets printed, there wasn't much to do until all the other parts arrived. I learned about some interesting limitations of the motherboard in my main computer while testing to make sure the GPU worked. I think I might be the sort of person who buys motherboards with the high-end chipset now.
+
+The last major component to arrive was the motherboard, and it arrived missing some important hardware, namely the M.2 standoff and the stock mounting bracket for the CPU cooler, the latter of which was *in the photo on the Ebay listing*! That's what I get for buying used, I guess. Fortunately both parts are pretty cheap to order online.
+
+Assembly went smoothly; not much to say here that you couldn't get from Linus Tech Tips. It turned out that *both* the original standoffs *and* the ones I ordered were the wrong height &mdash; the original ones were too long, and mine were too short. I ended up putting the original standoffs back in because neither were so far off as to render the rear I/O unusable and my standoffs made installing the GPU properly impossible. I also had to use a couple of breadboard wires to hook up the power LED, since the pins on my motherboard were right next to each other and the connector in the case was 3 pins wide with a blank one in the middle, for some reason. However, unlike *some* cases I've worked in, accessing the modular PSU cables was an absolute joy<sup id="n5r"><a href="#n5">5</a></sup>.
+
+What didn't go smoothly was actually booting the thing. On first power on, it failed to POST and got stuck on a code "8" on the little seven-segment diagnostic code display. I initially assumed it was training the memory, since this can take a while on first boot, but after about five minutes of no change I started getting worried. I read a lot of very worrying forum posts that suggested that either the CPU or motherboard were straight up dead, and I very nearly bought another CPU to see if that was the case. First, though, I decided to try updating the BIOS using the "BIOS Flashback" feature, and that fixed it immediately. I wasn't done yet, though.
+
+Astute readers will have figured out by now that I was using TrueNAS on the old machine and intended to continue using it on the new one. Installation went extremely smoothly, except for one small wrinke: I had decided to take the NVMe boot SSD from the old laptop to use as storage for my game servers<sup id="n6r"><a href="#n6">6</a></sup>, and even though I had done a fresh install of TrueNAS to a pair of mirrored SATA SSDs, the NVMe one, naturally, still had TrueNAS on it. This, from what I understand, caused the OS to get stuck trying to boot because there were two ZFS pools marked as the boot pool, and it would just give up and drop me into an initramfs shell instead. Booting into a live environment and using GParted to clear all the partitions on the drive didn't fix it, and after a bit of googling I learned I had to use the initramfs shell to clear the volume data for the disc directly.
+
+After that was cleared up and I was booting into TrueNAS, setup went off without a hitch. I imported the config I had saved from the old server and everything was instantly up and running like nothing had ever happened, and suddenly, I had a working server again.
+
+<h2>Postmortem</h2>
+
+The first natural question is: Did it work? Was I right? Did our intrepid hero succeed in her quest to finally have a server that's actually stable enough to use? And the answer is yes. Tremendously so. In the couple days it's been running, this thing hasn't crashed once, even after I installed Syncthing<sup id="n7r"><a href="#n7">7</a></sup> *and* set up an entire VM to run Minecraft. Whatever was causing all that instability with the old server didn't make it over to the new one, and I should bloody well hope not considering the only parts I carried over were a bunch of drives that were in perfect health according to both ZFS and the SMART tests they kept passing.
+
+There is one major issue, though. See, since I was planning to run a stock cooler in a case with airflow that was subpar at best short of cutting holes in it, I made sure to get the strongest fans I could find to fill the available mounts, which for me meant three 80mm Arctic P8 Max's &mdash; one in front, one in back, and one in the 3.5" cage, plus a 120mm fan in the 5.25" bays.
+
+These fans have a maximum speed of 5000 RPM, which makes them quite capable at compensating for the sub-optimal airflow conditions, but this was also the basis of my one fatal miscalculation: these suckers are *loud*. Not 1U rackmount borderline-jet-engine level loud, in fact the noise is more or less tolerable at low loads, but under significant load, such as, say, the Minecraft server I've been so fixated on, they get quite distractingly loud, which is a problem since the only feasible place for me to put it at the moment is on my desk.
+
+I soon plan to implement a multi-step plan to attempt to fix this issue: First, in my typical fashion when I find my equipment is slightly inadequate, I'll replace the AMD stock cooler I used with something gratuitously overbuilt &mdash; I'm thinking a Thermalright Peerless Assassin. Then, if that doesn't work, I'll tear the whole thing down and go at it with the hole saw, and mount a couple nice, big, quiet fans in my fresh new speed holes. If the 80mm fans are still causing a ruckus after all that, I'll just remove them. They probably won't be of critical importance at that point anyway.
+
+Overall, the case was a bit of an impulsive and perhaps sub-optimal choice, but I'd do it again in a heartbeat. I love this thing. I might be a little more liberal with the hole-making, though.
+
+I don't regret my choice of core components at all, at least not yet. The CPU, despite the noise, runs Minecraft as spectacularly as I'd hoped. At least, after some fiddling with my VM configuration. Its efficiency certainly also helps with cooling, given the circumstances. The motherboard, being a fancy X-series one, has various Gamer Lights and a myriad of overclocking features that are a bit silly to have in a server, but it also has the expansion I need and that's what really counts. Plus, that fancy 7-segment display was very helpful with diagnosing it.
+
+The RAM is RAM. It's fast enough for my porpoises with or without XMP, which I left off to optimize for stability. I might get more down the road. The graphics card is exactly what I need, and Jellyfin seems to like it fine. Couldn't have asked for a better value there. I'm still waiting on the GT 730 I foolishly ordered before looking into it properly. That's fine, though, it was even *cheaper* than the P400 and it's always nice to have spares.
+
+I ended up getting those 10 gig ethernet cards, but I couldn't use them like I wanted. As it turns out, a GPU and 2 NVMe drives is all the PCIe bandwidth the B550 chipset in my main rig has to offer. My next upgrade might just be a used X570 board. I did still install one in the server, though, and since the fan on it was very loud on account of being very dying, I replaced the shambling corpse of the stock fan with a 40mm Noctua, spliced onto the original header and mounted using one of my best zip-ties:
+
+<figure class="media">
+ <div>
+ <div class="gallery">
+ <img src="nictua.jpg" alt="A 40mm wide, 10mm thick Noctua fan zip-tied to the heatsink on a PCIe Ethernet card.">
+ <img src="ziptiemount.jpg" alt="The zip-tie is screwed into one of the original fan mounting holes on the heatsink. As in, the screw is going through the zip-tie.">
+ </div>
+ <figcaption style="margin-top: 0;">Yes, I attached the zip-tie to the heatsink by screwing it in. Clever, right?</figcaption>
+ </div>
+</figure>
+
+Would I recommend you follow in my footsteps? Absolutely. This thing is great. In order to make this work, I had to build a normal computer. Short of a rack-mount case and a rack in which to mount it, *this* is how you build a home server. Frankly, I was absolutely right that violently contorting my existing gaming laptop into a TrueNAS box would be cheaper than this, but I can now say with complete certainty that the savings were not worth it. This is less entertaining, sure, but I'm glad I finally did it properly. Well, at least to the greatest extent that I seem to be capable of "properly".
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. I'm not referring to the Seasonic S12III from the last installment. That thing is honestly a little sketchy for me to be using it in a proper server if I don't have to, and I don't. When my PC's power supply, a Seasonic GX650, exploded, I RMA'd it and then bought a beefier one to replace it with, and the replacement unit Seasonic sent me went in my server, and will be going in the new one. The S12III is serving as an improvised benchtop PSU using one of <a href="https://m.media-amazon.com/images/I/71UqFQ9U1QL._AC_SL1500_.jpg">these bad boys</a> at the moment.</p>
+
+<p id="n2"><a href="#n2r">2</a>. If cpubenchmark.net is to be believed, anyway.</p>
+
+<p id="n3"><a href="#n3r">3</a>. I could, in theory, reuse this fan, but I don't want to. It's so nasty that attempting to run it seems like a good way to invent a new respiratory illness, and even if I cleaned it the bearing is geriatric and the performance probably isn't very good, plus my modern motherboard might not even have a header for it. Its replacement will suit me much better.</p>
+
+<p id="n4"><a href="#n4r">4</a>. You can download the model for the fan mount and corresponding grill I designed <a href="https://www.printables.com/model/1014992-80mm-fan-mount-for-3x35-drive-bay-in-old-pc-case">here</a>. I'd publish the drive bracket but the one I printed needed some modification in order to work, and I don't want to spend the time and filament to refine it right now.</p>
+
+<p id="n5"><a href="#n5r">5</a>. Mind you, this case is well north of 20 years old. This case shipped to me with a Pentium III sticker on it. This thing may well predate modular power supplies as a <em>concept</em>, and somehow it accommodates them infinitely better than the 2-year-old case on my personal machine, which barely has room to <em>insert</em> a modular PSU, let alone actually get at the cables afterwards. I don't understand how this is possible.</p>
+
+<p id="n6"><a href="#n6r">6</a>. Generally you'd use this for L2ARC cache for ZFS, but from my research I don't have enough RAM for that to be useful anyway, and game servers are the only thing I currently want to do that's likely to benefit from the added speed of an NVMe SSD.</p>
+
+<p id="n7"><a href="#n7r">7</a>. Finally, at long last, I have automated backups to the enormous HDD array in my NAS! Took me bloody long enough.</p> \ No newline at end of file
diff --git a/blog/posts/building_a_sensible_server/index.php b/blog/posts/building_a_sensible_server/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/building_a_sensible_server/nictua.jpg b/blog/posts/building_a_sensible_server/nictua.jpg
new file mode 100644
index 0000000..c692bf8
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/nictua.jpg
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/servercase.jpg b/blog/posts/building_a_sensible_server/servercase.jpg
new file mode 100644
index 0000000..bbd1006
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/servercase.jpg
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/servercaseinside.jpg b/blog/posts/building_a_sensible_server/servercaseinside.jpg
new file mode 100644
index 0000000..038f65d
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/servercaseinside.jpg
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/servercaseinsidefront.jpg b/blog/posts/building_a_sensible_server/servercaseinsidefront.jpg
new file mode 100644
index 0000000..67f1626
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/servercaseinsidefront.jpg
Binary files differ
diff --git a/blog/posts/building_a_sensible_server/ziptiemount.jpg b/blog/posts/building_a_sensible_server/ziptiemount.jpg
new file mode 100644
index 0000000..ea00cb1
--- /dev/null
+++ b/blog/posts/building_a_sensible_server/ziptiemount.jpg
Binary files differ
diff --git a/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/background.png b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/background.png
new file mode 100644
index 0000000..05ebf8a
--- /dev/null
+++ b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/background.png
Binary files differ
diff --git a/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.md b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.md
new file mode 100644
index 0000000..0e00c4e
--- /dev/null
+++ b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.md
@@ -0,0 +1,87 @@
+<style>
+ body {
+ background: url('background.png') #000000;
+ background-position: center;
+ background-size: cover;
+ background-attachment: fixed;
+ }
+ a {
+ color: #00CED1;
+ }
+ a:hover {
+ color: #ffff00;
+ }
+ h1 {
+ font-style: italic;
+ background-image: url('/images/isopod.php'), linear-gradient(135deg, #2e1ae0 0%, #2e1ae0 2ch, #00ff00 4ch, #ffff00 6ch, #ffff00 7.1ch, #0000 7.1ch);
+ background-clip: border-box, text;
+ -webkit-text-fill-color: transparent;
+ text-shadow: none;
+ }
+ hr {
+ color: white;
+ box-shadow: 0 0 4px white;
+ }
+</style>
+
+Yesterday, September 18th, 2022, was the second anniversary of the creation of my first website on Neocities<sup id="n1r"><a href="#n1">1</a></sup>, the site that is now known as [deeptwisty.com](https://deeptwisty.com). I intended to publish this then, but life got in the way, by which I mean I wrote 90% of it and then procrastinated for two weeks on the last couple paragraphs. I figured that to commemorate the occasion I would finally dispense with the half-assed abridged history of the place on the about page or wherever and consolidate a complete history of my Personal Home Pages in one convenient location, that being this post.
+
+## Tumblr
+
+My first proper social media was Tumblr. Well, the first social media site I joined was Pinterest, but that doesn't count. Anyway, Tumblr was my main social media and the center of my Online Presence&trade; for several years. I would pour hours into tweaking the custom theming on my blog to be just right, and I often had some sort of bio on a custom page, which is a thing Tumblr lets you do. I linked to all my other online profiles from my Tumblr page, and would prioritize linking back to it from them. This caused problems, as I was and still am the type of Tumblr user to change their username on impulse, and it was terribly inconvenient having to go through all my other accounts and change that link whenever I did (I've got it set up as a subdomain of my website now, so that should never be a problem again). Eventually, though, another service would crop up that everyone seemed to be using, and that presented me with a better way:
+
+## Carrd
+
+I still use Tumblr, just not as the hub for my entire online presence. I maintain that it is still the best<sup id="n2r"><a href="#n2">2</a></sup> centralized social media site. Anyway, a Carrd page became the central hub which linked to all my online profiles and which all my online profiles could link back to. Finally, I only had to update my frequently changing Tumblr link in one place. For the most part.
+
+I perceived a certain stigma (at least on Tumblr) around having a Carrd page, and the sorts of people who made one. The stereotype was that you would have overly exhaustive BYF (Before You Follow) and DNI (Do Not Interact) lists full of sometimes outlandish criteria<sup id="n3r"><a href="#n3">3</a></sup>, probably have similar bullet point style lists of all your likes, dislikes, and possibly identities and triggers (!)<sup id="n4r"><a href="#n4">4</a></sup> and probably not be the most pleasant person to interact with. I like to think I bucked that trend. My Carrd pages were generally very simple: a profile picture, a short bio (some shit like "Name&nbsp;|&nbsp;21&nbsp;|&nbsp;🇨🇦&nbsp;|&nbsp;real&nbsp;life&nbsp;isopod"), and links to my socials. That was all. I remember adding the obligatory long-form bio and DNI list at some point, but those didn't last long.
+
+I believe it was around this time when the alias "deep twisty"<sup id="n5r"><a href="#n5">5</a></sup> came into being. I was just starting out making music at this point, posting crummy songs to SoundCloud that I'd made in an online editor called [EarSketch](https://earsketch.gatech.edu/landing/#/) that had you use Python to arrange pre-made loops and samples on a timeline. That shit was wack, yo, but that's beside the point. I was looking for an alias to release my music under, because I was intent on making more and my actual name wasn't gonna cut it.
+
+I was quite into Subnautica around this time (I promise this is relevant) and its sequel, Subnautica: Below Zero, was in the early stages of early access around this time, like still working on early-game areas early, and I was following it closely. The devs had a twitter account that posted all the git commits for the game, and a couple of them referred to a biome they were working on, the Deep Twisty Bridges<sup id="n6r"><a href="#n6">6</a></sup>, as just "deep twisty". That is the origin of that name. I don't know why I felt compelled to base my brand off that, but now I'm committed. I get self-conscious about it sometimes, but honestly, I've seen worse. Not that I'm judging.
+
+Anyway, I made a separate Carrd as a hub for this new "deep twisty" persona (I keep it separate from everything else mainly so I can show it to family without them seeing all of... this. Not that I have yet...). That worked fine until I wanted to start embedding my latest YouTube upload on the Carrd page, something Carrd locks behind a paywall. It was at this precise moment I remembered I know how to code and resolved to make the jump to a platform that lets you write your own HTML from scratch, in my case, this being
+
+## NeoCities
+
+My first Neocities sites were simple affairs, basic little pages with little more to them than the Carrd sites they had replaced, albeit with some of the things Carrd would have made me pay to add, like that YouTube embed. You can still see the original version of what is now this site [here](../../../old/1/), though the original version of deeptwisty.com was unfortunately lost. It was nothing special, though. It had a similar aesthetic to its replacement, and it was pretty similarly laid out to this here page, even with the same background, just with WAY less text, and no cool isopod.
+
+I've seen some people in this here "small web" community getting mad at people who use Neocities this way, to which I say: shut the fuck up! Everyone has to start somewhere, and messing around on a simple page like that could easily be a gateway drug into making something much bigger, like it was for me. Hearing sentiments like this is just going to discourage people. Besides, it's their website. They're not intruding on your special cool kids club by using a free service to do the thing that it's for.
+
+It was also during this time when I bought the domain deeptwisty.com. I had to pay Neocities to use it, but I was more than happy to support the cause anyway. I didn't stricly *need* the domain, but boy was it cool to have my very own Dot Com. It just sounds so professional. deep twisty Dot Com.
+
+The deep twisty site tended to take precedence over this here personal one for a while; the personal site was relegated to a subdirectory or subdomain like deeptwisty.com/me or me.deeptwisty.com. In fact, the transition from the former to the latter is when the original deeptwisty.com was tragically lost. I was copying over the contents of deeptwisty.com/me to its own fresh new dedicated Neocities profile and I accidentally uploaded the files to the wrong site, overwriting a large portion of the main deeptwisty.com with no way to recover it. I spent a couple days rebuilding it into roughly what you see at that domain now, and when I was done I was having enough fun with it that I wanted to keep going and decided to overhaul my other site too, and what resulted was [this](../../../old/2/).
+
+For this new version of the site, I decided I wanted to be able to actually add content to it, whereas the old site hadn't really been designed in a way that was conducive to that. I decided to do this in the most JS-reliant way possible. I had one main page with the navigation and layout, and the navigation worked by using a URL querystring to tell the page which content to load. It was pretty fuckin' neat, but I would eventually realize I wasn't a fan of how dependent it was on Javascript. My favorite feature of this revision is the theme picker, which swapped out different stylesheets and set a cookie to remember which one you prefer. The main problem with this was that I designed it so the themes could change basically everything bar the fudamentals of the layout, and it became a huge pain in the ass to add both new pages and new themes while ensuring everything stayed compatible. It was really cool though.
+
+To be completely honest, I took rather a lot of inspiration for this revision from [this site here](https://hosma.neocities.org/10/), which is to say I basically made a worse version of it<sup id="n7r"><a href="#n7">7</a></sup> and went from there. You can still see some of that inspiration in v3, with the giant header text and centered single-column layout.
+
+This revision was, as the kids say, Real Cool&trade;, but the aforementioned problems led me to scrap it after only about 2 months, which brings us here:
+
+## v3 and Self-Hosting
+
+I wanted something that could be viewed without Javascript and wasn't a colossal pain in the ass to update, hence what you see on the site now if you're reading this soon after it was posted. If I've since overhauled the site again, the version I'm referring to should be available [here](../../../old/3/). This version is designed to be as simple layout-wise as possible, to the point where you can read it in a text-only browser and not lose much of the experience. It's much easier to add stuff to now. My one issue with it is the navigation - unlike v2, where you could get to any page from any other in one click, v3 requires you to go back to the homepage to move between pages. It's just harder to navigate. This system is better than having to add a link to every new page on every existing page, though. Now that I can do server-side rendering, I'll probably put in a proper navbar or something of that nature at some point.
+
+Speaking of which, a bit after the jump to v3 I decided to start self-hosting my websites. I didn't have any deal breaking issues with Neocities per se, but I wanted to start messing around with server-side scripting, and I wanted to host some other things that I wasn't in a position to otherwise. I originally wanted to do this with an old laptop I had lying around, but I would have had to punch through the NAT in my <span class="house">house</span> and point the domain to my home IP address, neither of which I wanted to do. Instead, I cancelled my paid Neocities account and reallocated those funds to rent a VPS. I was originally going to use Linode for this, but they literally wouldn't let me sign up for an account for some reason<sup id="n8r"><a href="#n8">8</a></sup> so I went with DigitalOcean instead.
+
+I've had quite a lot of fun with this newfound backend access. I now have the freedom to use Javascript only when there's literally no other way to do what I want done, and I've taken advantage, moving stuff like the randomized subheader on the landing page server-side. I'm also hosting a lot of other services on this same VPS, including but not limited to a Fediverse instance, an RSS aggregator, a SearXNG instance, and a WireGuard VPN to make more intensive stuff I host on my laptop available to the internet. I'm honestly really impressed that the 1 CPU thread and 2G of RAM my server has can handle all that.
+
+That brings us to now, at this moment, when I'm writing this. I'm absolutely not out of stuff to do here, if I can ever get myself to actually fucking do any of it. I've had a great time with this whole "personal website" business so far, and I'm excited to see where I go with it from here. The community around it is cool too, though lord knows I'm still learning to navigate this particular social environment. At any rate, I'll definitely take this over Twitter.
+
+<hr>
+
+<p id="n1"><a href="#n1r">1</a>. It has since been migrated off of Neocities.</p>
+
+<p id="n2"><a href="#n2r">2</a>. Did you know you can get an RSS feed for any tumblr blog by going to &lt;blog url&gt;/rss? True story!</p>
+
+<p id="n3"><a href="#n3r">3</a>. Oh, I should have mentioned, GTFO if you kin Komaeda.</p>
+
+<p id="n4"><a href="#n4r">4</a>. I kind of get why you would want people to know that information, but I'm surprised more people didn't realize how easily abused that was.</p>
+
+<p id="n5"><a href="#n5r">5</a>. stylized in all lower case</p>
+
+<p id="n6"><a href="#n6r">6</a>. Yes, I named a song Bridges so I could call it "deep twisty - Bridges". Shut up.</p>
+
+<p id="n7"><a href="#n7r">7</a>. I'm currently going back through this blog post a couple years after the fact to replace all the hovertext with footnotes, and wow, v2 really, <em>really</em> was just me doing hosma.neocities.org. Utterly shameless.</p>
+
+<p id="n8"><a href="#n8r">8</a>. WTF? Like, let me give you my money, dude. The only thing I can think of that could have happened is their system assumed I was some kind of spammer or bot because I was accessing their site through a VPN. I solved the CAPTCHAs and everything. What's the deal?</p> \ No newline at end of file
diff --git a/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.php b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/deeptwistycom_2nd_anniversary_-_a_history_of_this_bullshit/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/discord/discord-no-way-2.gif b/blog/posts/discord/discord-no-way-2.gif
new file mode 100644
index 0000000..4ee8d64
--- /dev/null
+++ b/blog/posts/discord/discord-no-way-2.gif
Binary files differ
diff --git a/blog/posts/discord/discord.png b/blog/posts/discord/discord.png
new file mode 100644
index 0000000..36346c3
--- /dev/null
+++ b/blog/posts/discord/discord.png
Binary files differ
diff --git a/blog/posts/discord/federation.png b/blog/posts/discord/federation.png
new file mode 100644
index 0000000..f2c5f6b
--- /dev/null
+++ b/blog/posts/discord/federation.png
Binary files differ
diff --git a/blog/posts/discord/index.md b/blog/posts/discord/index.md
new file mode 100644
index 0000000..6d188be
--- /dev/null
+++ b/blog/posts/discord/index.md
@@ -0,0 +1,204 @@
+Just once I'd like to write about something other than fixing tech problems.
+
+So Discord's been on their bullshit again (as if they were ever off of it). This time it's an overhaul to their username system, last time it was a change in their privacy policy allowing them to collect data from voice and video calls, and then there's the AI stuff. It's not like Discord acting shitty is anything new, but this post isn't about the company's transgressions. This article is about escaping your dependency on Discord, and more broadly escaping the vicious corporate cycle of which it's the latest iteration.
+
+I was originally going to center this article around the pros and cons of different alternatives to Discord, and I do still want to touch on that, but I think it's important to express my reasoning in detail here; it will be easier to avoid another situation like the one we have now with Discord if we know what's actually wrong with it on a more fundamental level than which administrative decisions of theirs are bad. How do we ensure wherever we go next won't pull the exact same crap?
+
+## So why is Discord bad?
+
+Let's be honest with ourselves up front: In many ways, Discord, as a service, fucking owns. It has a ton of fun features not found really anywhere else and the quality of its voice, video, and live streaming functions are tough to beat. However, these advantages come at the cost of Discord's most significant fundamental problem: It's a proprietary, centralized, VC-funded platform. It gets the funding it needs to be so awesome from investors who expect a return on their investments, and it is legally obligated to put creating that return above all other priorities.
+
+### Enshittification - The Capitalism Problem
+
+It's possible, even probable, that Discord started out with the simple, noble goal of being the best Chat for Gamers&trade;, creating an alternative to the problems present with its predecessors Skype and Teamspeak, and whatever chat functionality your favourite games had. At this, it succeeded spectacularly, for a time. However, the entire model of the VC-funded startup is fundamentally unsustainable.
+
+Discord was never actually profitable - it's been able to keep the lights on for this long using money from investors, but it needs to become profitable at some point in order to keep going long-term. If you're an avid Discord user, think of some of the blatant cash grabs they've pulled in the past at the expense of user experience, all the pointless features they've added behind the paywall of Nitro. I'd bet you can name at least half a dozen. And none of it worked. Now imagine what Discord would need to do, or would try, in order to become profitable. Personally, the imagine conjured in my mind by the idea of "Discord but profitable" is pretty grim.
+
+This isn't a problem specific to Discord. A popular term for what's happening to it is "enshittification" - Cory Doctorow, the term's inventor, <a href="https://pluralistic.net/2023/01/21/potemkin-ai/#hey-guys">explains it well</a>:
+
+<blockquote></blockquote>
+<figure class="quote">
+ <blockquote>
+ Here is how platforms die: first, they are good to their users; then they abuse their users to make things better for their business customers; finally, they abuse those business customers to claw back all the value for themselves. Then, they die.
+ </blockquote>
+ <figcaption>
+ &mdash; Cory Doctorow, <a href="https://pluralistic.net/2023/01/21/potemkin-ai/#hey-guys">Tiktok's enshittification</a>
+ </figcaption>
+</figure>
+
+I won't restate his essay or the examples he lists here (though you should give it a read), but one obvious one his article didn't cover because it was written more than a week ago is what's happening with Reddit right now. Reddit has been enshittifying itself for years, but the current controversy is particularly bad and particularly representative of the problem. As of writing in mid-June of 2023, Reddit has just instituted a new policy requiring payment for use of its API, to the tune of $12,000 per 50 million API requests, which for certain popular third-party clients and moderation tools comes out to millions of dollars per year.
+
+Reddit did not need to do this. Reddit was doing fine. This was purely a cash-grab, and it's blowing up in everyone's face right now, including theirs. Moderators of many popular subreddits are essentially going on strike over this, and if you think that's the only critical problem this decision is going to cause for users you know very little about Reddit. The developers of open-source clients and moderation tools used by massive portions of Reddit's userbase can't afford costs like this, and most of them will be forced to shut down if Reddit sticks to its guns.
+
+I'm not saying they will, but Discord could absolutely do the same thing, and it wouldn't surprise me if it came to that. Imagine if Discord bot developers needed to pay API fees like that. There'd certainly be a lot fewer Discord bots, and probably a lot more paywalled ones among the remainder. Discord absolutely needs to become profitable in order to be sustainable, and it will do whatever it needs to to that end or die. Even then, it can't just break even; capitalism demands endless growth. Discord will keep getting worse as long as there's money in it. It's inevitable. It's required.
+
+### Centralization
+
+Discord is a centralized platform and always will be, no matter how strong the reality distortion field it puts up by allowing the creation of isolated social spaces and calling them "servers". Every Discord "server" runs on Discord's servers, and they have total control over each one at the end of the day.
+
+Now, centralization isn't inherently bad. Sometimes it is necessary. Imagine trying to construct a peer-to-peer MMORPG, for example. Discord, however, is not a videogame, and in its case centralization introduces some fundamental problems that a decentralized system could avoid without compromising core functionality.
+
+The centralized nature of Discord, the platform, means that it, in its entirety, is inherently vulnerable to anything that happens with Discord, the company. Any change the company decides to make is universal. If the company shuts down, the platform goes with it. If the admins at Discord don't like what you're doing, they can unilaterally prevent you from using their platform at all.
+
+This ties pretty closely into the whole VC-funded thing - Discord, the platform, is fundamentally subject to the whims of Discord, the company's investors. I guarantee you that's why they changed the username system: the corporate big wigs providing the funding got confused by Discord's unique (and very good) username system and decided it would be better if it was more like Twitter, so Discord made it more like Twitter.
+
+That's really the core of the issue here: being centralized means that Discord can easily suffer the same fate as Twitter. Some incompetent nutcase with more money than the entire planet's collective pool of sense could buy it out and destroy it, or the current owners could just make some boneheaded decision and do the same. A decentralized platform, running on a common open protocol, is much less vulnerable to the antics of the Elon Musks and u/spez's of the world.
+
+### The Privacy Problem
+
+This issue isn't really inherently connected to the others - a lack of good privacy doesn't fundamentally doom a platform like the other two points - but I'm treating it as a third major issue because I feel it's extremely important and warrants consideration.
+
+If you value your privacy, Discord is an atrocious choice. Take it from <a href="https://tosdr.org/en/service/536">their own terms of service</a>. Anything you send on Discord, whether in a DM or a public guild (I'm not calling them "servers"), is **not encrypted**, meaning it can be accessed and read by Discord staff, as well as any hackers that manage to access their systems or any law enforcement entities that might demand it. Discord is not even trying to pretend to be private. I'm not convinced it's something they ever thought about.
+
+And let's be clear here: You should value your privacy. You should value it a lot. The idea that if you have nothing to hide, you have nothing to fear is a complete scam. Even if you don't have anything to hide, yes you do. Take, for example, <a href="https://archive.ph/TYPd1">the time</a> Google flagged someone as a criminal and permanently closed their account for the crime of sending medical photos of their son to a doctor. Or maybe your government wants to arrest you for being gay, or having an abortion, or some other innocuous but potentially illegal thing. Or maybe they will in the future. Or maybe some stuff you've said is just kind of embarrassing.
+
+If you still don't believe me, read through a couple months of your Discord message history and then contemplate printing it out and mailing it to the NSA. If the government asks, Discord will save you the trouble, and they won't ask your permission first. And with a recent change to their privacy policy, this theoretically applies to your voice chats too, though to be fair I expect that would be prohibitively costly in server space.
+
+Discord fundamentally couldn't give a shit about your privacy, and doesn't even really care to pretend like it does. It has no incentive to. The investors probably wouldn't be comfortable with the risks associated with pulling a stunt like responding to a subpoena with "yeah here's their phone number. that's all we got" like certain other chat apps anyway, and then there's the potential to sell that all data on you to advertisers. I'm not aware that they currently do that, but it's certainly not off the table should they decide to go that route in order to turn a profit. At least, not under US law, anyway.
+
+Actually, I just checked that ToS;DR link from earlier again, would you look at that:
+
+<figure class="quote"><blockquote>This service may keep personal data after a request for erasure for business interests or legal obligations</blockquote></figure>
+<figure class="quote"><blockquote>This service ignores the Do Not Track (DNT) header and tracks users anyway even if they set this header.</blockquote></figure>
+<figure class="quote"><blockquote>Your personal data may be used for marketing purposes</blockquote></figure>
+<figure class="quote"><blockquote>This service can license user content to third parties</blockquote></figure>
+<figure class="quote"><blockquote>The service can sell or otherwise transfer your personal data as part of a bankruptcy proceeding or other type of financial transaction.</blockquote></figure>
+<figure class="quote"><blockquote>The service may use tracking pixels, web beacons, browser fingerprinting, and/or device fingerprinting on users.</blockquote></figure>
+<figure class="quote"><blockquote>The service uses your personal data to employ targeted third-party advertising</blockquote></figure>
+
+Juicy stuff. You should really give that a read - you might not like what you find.
+
+Before we move on, I'll just drop this tasty little <a href="https://spyware.neocities.org/articles/discord">link</a> to further reading. It's a real page-turner.
+
+## Cool, so how do we fix it?
+
+We don't. Discord was doomed from the outset in any attempts to be sustainable or trustworthy. We are going to need to find an alternative to Discord eventually. So what should that alternative look like? I'll discuss specifics later - I'd like to start by establishing the general principles I feel a messaging system should conform to in order to avoid Discord's major problems. The TL;DR is it needs to not be any of the things I've described thus far about Discord, but I'll go into more detail about what that actually looks like.
+
+### Follow the money
+
+A sustainable chat system *absolutely cannot* be for-profit. If it is in any way driven by profit, the decay and eventual death of the service is inevitable. That doesn't mean it has to be entirely staffed by unpaid volunteers or anything, but it would need to be a non-profit foundation of some kind, just trying to break even with no incentive for infinite growth or any other corrupting financial influence. You'll notice this as a theme across most online services that don't already show signs of advanced corporate necrosis.
+
+I'm not even saying it can't have some kind of Nitro-esque paid tier. I don't hold it against, say, Protonmail - in fact, I pay for that one - but the money can't be the end goal. A sustainable non-profit model might be largely donation-based like Wikipedia, or maybe it could have a totally free product for individual users and break even selling support to enterprise customers like some Linux distributions. It's not currently breaking even yet according to its Wikipedia article, but I'll be interested to see if and how Signal reaches a sustainable state. Maybe future players could take notes from them.
+
+### Cut out the middle man
+
+Better yet, structure your system such that it doesn't even need a corporation at the center - in other words, a decentralized system. I'm not talking about the blockchain; we can do this the old-fashioned way, with tech that isn't ponzi-scheme-by-design. In fact, we're already doing this, and it already has more monthly active users than any messenger app ever created: email.
+
+Email is the original decentralized, federated communications network. There's no Email LLC at the center of it all assigning everyone their email addresses and processing every message. Email isn't an app. It isn't a proprietary service. It's an open protocol that anyone can set up a server to provide access to. That's what Gmail is, that's what Outlook is, that's what your weird nerdy friend's weird nerdy friend who has a custom domain name on their email address and complains about Gmail marking their messages as spam is doing. They're all part of the bigger network.
+
+I'll try to keep this little tangent short, but I feel it's important to establish a basic understanding of how these systems work. Email is a federated protocol, meaning it isn't tied to one backend running on one company's datacenter - instead, it's a network composed of any number of entirely independent servers running compatible software that communicate amongst themselves using the language of the email protocol. These servers are often called "nodes" or "instances", or sometimes "providers" in the case of email. A user of email has an account with one of these instances and can use it to send messages to people both on the same instance and on any other instance on the network.
+
+This is why email addresses are like that - the part before the @ is your username, and the domain name after the @ points to the server your account is registered on. If usernames on other platforms were formatted like this you would see stuff like MrBeast@youtube.com for Youtube channels or dril@twitter.com for Twitter accounts, but those platforms aren't federated so they don't need to do that.
+
+So when two people communicate via email, the sender sends the message to their instance, which sends it to the instance its recipient is using, which then relays it to the recipient.
+
+And here's the obligatory visual aid - essentially, when you send an email, it takes the shortest path along a network that looks like this; every server is connected to every other, and every user is connected to one server:
+
+![A graph showing three large nodes connected to each other, each with multiple smaller nodes branching off of them. Each large node is an email server, such as outlook.com or gmail.com, and each small node is an email account, such as jim@outlook.com or bob@gmail.com.](federation.png)
+
+Hopefully that helped. Back to the point, all federated services work pretty much exactly like this. If you've ever had someone try to explain the Fediverse (sometimes incorrectly called Mastodon) to you by comparing it to email, this is what they meant. But this isn't limited to email and microblogging; this type of system can theoretically apply to anything. Again, building an MMO this way would be challenging, but federated messaging protocols similar in concept to Discord do exist.
+
+The benefit of this kind of system stems from the fact that it's not under the control of any central authority: Gmail, Outlook, and that weird nerd your friend knows are entirely independent of each other, they don't answer to any higher Email Authority (other than the body that defines the common standard) or each other. This means that there's nobody at the top to fuck the entire thing up for everyone or sell it off to someone who will; in fact, even if someone wanted to it would be tremendously difficult.
+
+The network is inherently much more stable and resilient in general than a centralized service, as there's nobody who would take the entire network down with them if the company went under or got sued or had a bomb dropped on their datacenter. Sure, a huge number of people would lose their email accounts if Gmail disappeared tomorrow, but critically, not the entire network. Email wouldn't go away, and those displaced users could go to Outlook or Protonmail or set up their own instance and keep communicating over the same network. The same applies to any other federated protocol. Imagine if your Discord account and guilds weren't controlled by Discord, but instead ran on a machine you controlled and was in no way answerable to Discord Inc, but you could still talk to your buddies on Discord proper. It's like that.
+
+### Incognito mode
+
+Contrary to the title of the previous section, a federated approach does technically add more middlemen. We've gone from one unaccountable central authority able to read everyone's messages to several unaccountable parties each able to read the messages of everyone they serve. Not much of an improvement, privacy-wise, unless you trust both your provider and the providers of everyone you're talking to implicitly. Actual privacy requires end-to-end encryption.
+
+End-to-end encryption means the message is encrypted before leaving the sender's machine and can only be decrypted by the recipient once it arrives on theirs. This means that only the sender and recipient can read the message; even if it goes through some other party's server, they have no clue what the contents of the message are. Any messaging system that cares about privacy at all will implement this - ideally they'll build the entire protocol around it.
+
+There are still problems here, for example end-to-end encrypted messaging still requires the server to know who you're talking to, but there are workarounds for these as well. However, E2EE should be the absolute bare minimum, in my opinion.
+
+## So what are our options then?
+
+Here's the part where I discuss actual alternatives to Discord. I'll say now that this will not be a comprehensive overview of every possible option - recommending chat apps that don't meet these standards would kinda defeat the point, and I'm also not omniscient. There are going to be other options that I haven't covered here, and hopefully I've given you the tools to determine which ones are good.
+
+Every program I list here will, at a minimum, support true end-to-end encryption in some capacity and not be run by a for-profit company. They're also all open-source.
+
+### <a href="https://xmpp.org/">XMPP</a>
+
+XMPP is about as close as we've got to "email but for instant messaging". It's a federated, open protocol which, having been formally standardized in 1999, is truly ancient in internet years. My understanding is that it actually used to be more widely used, but Google effectively killed it off in popular usage by subsuming its userbase into Google Talk and then promptly turning off federation and killing Google Talk. That doesn't mean it's gone, though. People still use XMPP to talk to each other, running on servers hosted by themselves or their friends.
+
+XMPP is, at its core, designed for simple text-based messaging and presence. While the protocol is highly extensible, many even relatively basic-seeming features, while common, aren't universally supported. If you want them, you'll have to find a provider that has them.
+
+- Federated protocol.
+- Feature-bare; no gimmicks.
+- Generally supports file sharing.
+- Supports end-to-end encryption, but it's not the default and it's kinda janky.
+- While integration with WebRTC voice chat is supported, it's not universal, and some people prefer to use a separate voice chat system, such as Mumble, in conjunction with XMPP text chat.
+- You'll have to find a provider and choose a client program to connect with. Fortunately, there's plenty of options, and the official XMPP website lists some of each.
+
+### <a href="https://matrix.org/">Matrix</a>
+
+Matrix is the other major federated instant messaging protocol. It was standardized in 2014 and is built around making end-to-end encryption easy. On top of that, it has more features. File sharing is included by default and support for nice-to-have features like emoji reactions (and maybe custom emojis??) and Discord-style replies is widespread. There's also a large suite of bridges to other services, including Discord. Like with XMPP, voice chat integration is possible, but not universal, and some prefer to use Mumble or similar.
+
+- Federated protocol.
+- More features than XMPP, similar situation with voice calls though.
+- Built around end-to-end encryption, though you can disable it, and you will need to for integrations like bots and bridges.
+- As with XMPP, you'll need to find a provider and a client program. The website lists quite a few clients, and you can find a list of servers <a href="https://joinmatrix.org/servers/">here</a>.
+
+### <a href="https://www.mumble.info/">Mumble</a> and <a href="https://jitsi.org/">Jitsi</a>
+
+Mumble and Jitsi are self-hostable voice chat and videoconferencing applications, respectively. They're not messaging systems, but I feel they bear mentioning here because they're both popular for use in conjunction with text chat systems, and since nothing else here currently supports screensharing.
+
+### <a href="https://revolt.chat">Revolt</a>
+
+We've about run out of open protocols (which is probably a good thing), so now on to the centralized services, starting with Revolt. Revolt is basically trying to be open-source Discord. It's currently in alpha, but the user experience is very similar and it already has some of the fun stuff.
+
+From what I could find Revolt isn't currently controlled by any kind of legal entity, so there's no guarantee it won't eventually incorporate into a for-profit company and pull a Reddit (by which I mean, Reddit used to be open-source, but hasn't been since 2017), but at least for now the project leaders express principles that make that seem unlikely.
+
+- Centralized service.
+- Still early in development.
+- Very similar in UI/UX to Discord.
+- No paywalls.
+- Supports voice, but not currently video.
+- No encryption, but E2EE for DMs is being worked on.
+- Has features like custom emojis, replies, public guilds and a friends list.
+
+### <a href="https://signal.org/">Signal</a>
+
+I've now run out of Discord-likes - which is to say, programs that support the sort of multi-channel group chat thing Discord has going on. This and the next one function more in the vein of a Whatsapp clone, though I feel they still bear mentioning in the event that's all you need.
+
+Signal is kind of *the* private messaging app. It's fundamentally built around end-to-end encryption in a way that its biggest direct competitors simply aren't. It's been proven in court that Signal literally doesn't have the ability to incriminate you, since they can't access the contents of your messages. It does need your phone number, though, however you can now hide it with a username. It also supports voice and video chat, and stickers, apparently.
+
+- Centralized service.
+- Similar to Whatsapp in terms of UI/UX.
+- Emphasis on end-to-end encryption.
+- Supports voice and video calls.
+- Requires a phone number, but only a phone number.
+- You can set a username, so you don't need to share your phone number.
+
+### <a href="https://getsession.org/">Session</a>
+
+I lied, Session isn't centralized. But it's not decentralized in the same way as the federated protocols up there, either. Session runs over an anonymizing onion routing network, Tor-style, meaning not only can your messages not be read by the server, those servers also don't know both the sender and the destination at the same time. Essentially, it's designed to maximize privacy and anonymity at all costs. But wouldn't you know it, that comes at a cost in terms of features and user experience.
+
+Session does also use cryptocurrency. Setting a custom display name and running a node on its decentralized network both require participation in a blockchain, though your messages aren't sent via this blockchain.
+
+- Decentralized, encrypted, and anonymous.
+- Supports voice and video calls, but currently only 1:1.
+- Requires no personal details to sign up.
+- No extra features.
+- Setting a display name requires a crypto transaction, but sending messages does not.
+
+## Conclusion
+
+That's about all I've got. I hope I've impressed upon you the importance of Discord's core problems, and introduced you to at least one alternative that works for you. I have my preferences, but I'm comfortable recommending all of these over Discord, otherwise I wouldn't have listed them.
+
+[Update 2023-09-09] I no longer recommend Matrix over XMPP for reasons explained well <a href="https://telegra.ph/why-not-matrix-08-07">here</a>. I knew there was a little jank but I had no idea the rot ran this deep. Fortunately, nobody's listened to me yet so I can switch over to XMPP without much issue, which I intend to do.
+
+[Update 2024-04-27] I have removed Telegram from the recommendations list outright due to <a href="https://isopod.zone/notes/9sjy5r4ocq">just, straight up nazism</a>, and in a post announcing cryptocurrency features no less. Jesus H. Christ.
+
+If there's one thing I want you to take away from this article, it's this: Don't fall for the marketing and don't let yourself be wooed by extraneous gimmicks. Be discerning about which fancy-sounding features you actually need. If you want to have a chance of escaping the vicious corporate cycle of enshittification, both with chat platforms and with everything else, make sure the ones you use have a strong foundation of sustainability and trustworthiness, beyond whatever marketing drivel is on the front page of their website. Hopefully I've given you at least some tools to determine for yourself which ones do.
+
+## Further Reading
+
+- <a href="https://pluralistic.net/2023/01/21/potemkin-ai/#hey-guys">Enshittification</a>
+- <a href="https://tosdr.org/en/service/536">A simplified breakdown of Discord's TOS (ToS;DR)</a>
+- <a href="https://spyware.neocities.org/articles/discord">Spyware Watchdog - Discord</a>
+- <a href="https://moth.monster/blog/fediverse/">A different explanation of federation in the context of federated social media</a>
+- <a href="https://proton.me/blog/whatsapp-alternatives">A privacy-focused comparison of messenger apps</a>
+
+<div class="buttons" style="margin-bottom: 1rem;">
+ <img src="discord-no-way-2.gif" />
+</div> \ No newline at end of file
diff --git a/blog/posts/discord/index.php b/blog/posts/discord/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/discord/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/fediverse_dms/bg.svg b/blog/posts/fediverse_dms/bg.svg
new file mode 100644
index 0000000..5f04313
--- /dev/null
+++ b/blog/posts/fediverse_dms/bg.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="196.52mm" height="196.52mm" viewBox="0 0 196.52 196.52">
+ <path fill="#a730b8" d="M47.9242 72.7966a18.2278 18.2278 0 0 1-7.7959 7.7597l42.7984 42.9653 10.3182-5.2291zm56.4524 56.6704-10.3182 5.2291 21.686 21.7708a18.2278 18.2278 0 0 1 7.7975-7.7608z"/>
+ <path fill="#5496be" d="M129.6645 102.0765l1.7865 11.4272 27.4149-13.8942a18.2278 18.2278 0 0 1-4.9719-9.8124zm-14.0658 7.1282-57.2891 29.0339a18.2278 18.2278 0 0 1 4.9728 9.8133l54.1027-27.4194z"/>
+ <path fill="#ce3d1a" d="M69.5312 91.6539l8.1618 8.1933 29.269-57.1387a18.2278 18.2278 0 0 1-9.787-5.0219zm-7.1897 14.0363-14.0022 27.3353a18.2278 18.2278 0 0 1 9.786 5.0214l12.3775-24.1639z"/>
+ <path fill="#d0188f" d="M39.8906 80.6763a18.2278 18.2278 0 0 1-10.8655 1.7198l8.1762 52.2981a18.2278 18.2278 0 0 1 10.8645-1.7198z"/>
+ <path fill="#5b36e9" d="M63.3259 148.3109a18.2278 18.2278 0 0 1-1.7322 10.8629l52.2893 8.3907a18.2278 18.2278 0 0 1 1.7322-10.8629z"/>
+ <path fill="#30b873" d="M134.9148 146.9182a18.2278 18.2278 0 0 1 9.788 5.0224l24.1345-47.117a18.2278 18.2278 0 0 1-9.7875-5.0229z"/>
+ <path fill="#ebe305" d="M126.1329 33.1603a18.2278 18.2278 0 0 1-7.7975 7.7608l37.3765 37.5207a18.2278 18.2278 0 0 1 7.7969-7.7608z"/>
+ <path fill="#f47601" d="M44.7704 51.6279a18.2278 18.2278 0 0 1 4.9723 9.8123l47.2478-23.9453a18.2278 18.2278 0 0 1-4.9718-9.8113z"/>
+ <path fill="#57c115" d="M118.2491 40.9645a18.2278 18.2278 0 0 1-10.8511 1.8123l4.1853 26.8 11.42 1.8324zm-4.2333 44.1927 9.8955 63.3631a18.2278 18.2278 0 0 1 10.88-1.6278l-9.355-59.9035z"/>
+ <path fill="#dbb210" d="M49.7763 61.6412a18.2278 18.2278 0 0 1-1.694 10.8686l26.8206 4.3077 5.2715-10.2945zm45.9677 7.382-5.272 10.2955 63.3713 10.1777a18.2278 18.2278 0 0 1 1.7606-10.8593z"/>
+ <path fill="#ffca00" d="M93.4385 23.8419a1 1 0 1 0 33.0924 1.8025 1 1 0 1 0-33.0924-1.8025"/>
+ <path fill="#64ff00" d="M155.314 85.957a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
+ <path fill="#00a3ff" d="M115.3466 163.9824a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
+ <path fill="#9500ff" d="M28.7698 150.0898a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
+ <path fill="#ff0000" d="M15.2298 63.4781a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
+</svg> \ No newline at end of file
diff --git a/blog/posts/fediverse_dms/index.md b/blog/posts/fediverse_dms/index.md
new file mode 100644
index 0000000..a12c503
--- /dev/null
+++ b/blog/posts/fediverse_dms/index.md
@@ -0,0 +1,19 @@
+People who refuse to use the fediverse (often conflated with Mastodon) often cite concerns about privacy with regards to DMs as their reason for avoiding it; "admins can read your DMs" and all that. To be fair, that's technically a true statement, but it's more complicated than that. Now, I have no problem letting these people be wrong - I'm not eager to convince idiots with no capacity for critical thinking to come to my favourite social network - but I'm nothing if not endlessly pedantic, so I felt the need to explain my take on the issue anyway.
+
+## DMs Are A Lie
+
+To begin with, the term "DM" as it applies to other social platforms is kind of a misnomer in the case of the Fediverse. Websites like Twitter and Instagram have a dedicated chat-style interface for messaging people directly. If you spend five minutes with most fediverse software, you'll notice that it doesn't have this.
+
+Sending a DM on the fediverse is generally accomplished by making a normal post and changing the visibility setting to only show the post to people who are mentioned in it. This isn't a case of obtuse UX design, it reflects how DMs on the fediverse actually work under the hood: The underlying protocol has *no concept* of direct messages, and is only able to approximate them with a special flag on an otherwise normal post.
+
+In other words, when you send a "DM" on the fediverse, what you're really doing is making a public post, and asking the network nicely to only show it to the person it's intended for. All software that isn't actively malicious or *extremely* shitty will comply with this request, and in fact admins can only read your DMs by circumventing the instance software and accessing the backend database directly, but the post is in no way actually private.
+
+## This Is Fine Actually
+
+I don't personally think this is an issue; I think it's perfectly fine that the fediverse doesn't attempt to do secure communication. Doing things this way reduces liability for server owners and reduces the complexity of the software for developers, and you really should be able to contact anyone who you actually want to keep in touch with on multiple platforms anyway.
+
+Besides, it's not like insecure DMs are an issue unique to the fediverse. DMs on [Twitter/Instagram/Reddit/etc] aren't encrypted either, meaning the admins of those websites can read your DMs too. Same for actual dedicated chat platforms like Discord and (mostly) Telegram. Twitter's admins can read your DMs, Discord's admins can read your messages, Gmail's admins can read your emails, and your phone provider can read your texts. And they often do, to sell information about you to advertisers or comply with police requests or what have you.
+
+It's only slightly less of a problem on those platforms because you're much less likely to know the admins personally, and individual staff members could probably lose their jobs if they used the contents of your DMs to start drama. That said, I've personally never seen evidence of any admin *actually* reading someone's DMs on the fediverse, because doing that is a *huge pain in the ass* involving like, SQL queries and shit, and is much harder than any actual administrative task most fediverse admins will ever do.
+
+Either way, you should really be using an actually secure messaging service if privacy is important to you. Be the change you want to see in the world and become that person who insists on taking conversations in Twitter DMs to Signal. I'm being completely serious. \ No newline at end of file
diff --git a/blog/posts/fediverse_dms/index.php b/blog/posts/fediverse_dms/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/fediverse_dms/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/foodhero/index.md b/blog/posts/foodhero/index.md
new file mode 100644
index 0000000..87445f0
--- /dev/null
+++ b/blog/posts/foodhero/index.md
@@ -0,0 +1,3 @@
+I'm gonna promote a product or service today, but I promise it's with good reason - my employer has gone and done something actually positive for once and I want to spread awareness of it.
+
+So, I work at a grocery store. \ No newline at end of file
diff --git a/blog/posts/foodhero/index.php b/blog/posts/foodhero/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/foodhero/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_blacklist_websites_searxng/index.md b/blog/posts/guide_blacklist_websites_searxng/index.md
new file mode 100644
index 0000000..3aab326
--- /dev/null
+++ b/blog/posts/guide_blacklist_websites_searxng/index.md
@@ -0,0 +1,21 @@
+Quick one today. I got sick of searching for programming questions and seeing AI-generated scraped-from-stackoverflow click farm trash polluting the results, and I happen to use a personal SearXNG instance that no client-side blacklist extension on the planet is gonna support, so I went looking to see if I could blacklist them in SearXNG for like the eighth time and finally found a way using the hostname replace plugin. So here's that, because I didn't find this feature documented officially anywhere bar an [issue](https://github.com/searxng/searxng/discussions/970) on the Github repo.
+
+## How to do it
+
+First, open up your instance's config file. If you installed it directly like I did, that'll probably be `/etc/searxng/settings.yml`. If you used Docker, god help you. Anyway, find the `enabled_plugins:` section and uncomment the entry for `'Hostname replace'`, then uncomment the line `hostname_replace:` just below it. Under there you'll put your blocks:
+
+<p class="codetitle">/etc/searxng/settings.yml</p>
+
+```
+enabled_plugins:
+ - 'Hostname replace'
+hostname_replace:
+ '(.*\.)?codegrepper\.com': false
+ '(.*\.)?geeksforgeeks\.org': false
+```
+
+Then restart SearXNG:
+
+```
+service uwsgi restart searxng
+``` \ No newline at end of file
diff --git a/blog/posts/guide_blacklist_websites_searxng/index.php b/blog/posts/guide_blacklist_websites_searxng/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/guide_blacklist_websites_searxng/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_blacklist_websites_searxng/searxng.svg b/blog/posts/guide_blacklist_websites_searxng/searxng.svg
new file mode 100644
index 0000000..851a0e6
--- /dev/null
+++ b/blog/posts/guide_blacklist_websites_searxng/searxng.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg8" version="1.1" viewBox="0 0 92 92" height="92mm" width="92mm">
+ <defs id="defs2"/>
+ <metadata id="metadata5">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g transform="translate(-40.921303,-17.416526)" id="layer1">
+ <circle r="0" style="fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" cy="92" cx="75" id="path3713"/>
+ <circle r="30" cy="53.902557" cx="75.921303" id="path834" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
+ <path d="m 67.514849,37.91524 a 18,18 0 0 1 21.051475,3.312407 18,18 0 0 1 3.137312,21.078282" id="path852" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
+ <rect transform="rotate(-46.234709)" ry="1.8669105e-13" y="122.08995" x="3.7063529" height="39.963303" width="18.846331" id="rect912" style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
+ </g>
+<script xmlns=""/></svg> \ No newline at end of file
diff --git a/blog/posts/guide_blocking_user_agents_nginx/bg.svg b/blog/posts/guide_blocking_user_agents_nginx/bg.svg
new file mode 100644
index 0000000..27062a8
--- /dev/null
+++ b/blog/posts/guide_blocking_user_agents_nginx/bg.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><title>file_type_nginx</title><path d="M15.948,2h.065a10.418,10.418,0,0,1,.972.528Q22.414,5.65,27.843,8.774a.792.792,0,0,1,.414.788c-.008,4.389,0,8.777-.005,13.164a.813.813,0,0,1-.356.507q-5.773,3.324-11.547,6.644a.587.587,0,0,1-.657.037Q9.912,26.6,4.143,23.274a.7.7,0,0,1-.4-.666q0-6.582,0-13.163a.693.693,0,0,1,.387-.67Q9.552,5.657,14.974,2.535c.322-.184.638-.379.974-.535" style="fill:#019639"/><path d="M8.767,10.538q0,5.429,0,10.859a1.509,1.509,0,0,0,.427,1.087,1.647,1.647,0,0,0,2.06.206,1.564,1.564,0,0,0,.685-1.293c0-2.62-.005-5.24,0-7.86q3.583,4.29,7.181,8.568a2.833,2.833,0,0,0,2.6.782,1.561,1.561,0,0,0,1.251-1.371q.008-5.541,0-11.081a1.582,1.582,0,0,0-3.152,0c0,2.662-.016,5.321,0,7.982-2.346-2.766-4.663-5.556-7-8.332A2.817,2.817,0,0,0,10.17,9.033,1.579,1.579,0,0,0,8.767,10.538Z" style="fill:#fff"/></svg> \ No newline at end of file
diff --git a/blog/posts/guide_blocking_user_agents_nginx/index.md b/blog/posts/guide_blocking_user_agents_nginx/index.md
new file mode 100644
index 0000000..763ea4d
--- /dev/null
+++ b/blog/posts/guide_blocking_user_agents_nginx/index.md
@@ -0,0 +1,73 @@
+Recently, Cloudflare has launched a clumsy, poorly-executed attempt to centralize the fediverse on their platform known as Wildebeest. There are a few reasons not to want to use it, and you probably don't want to be federating with it either. However, blocking every instance running it on sight would be both tedious and ineffective.
+
+The way I've chosen to deal with this is to just configure my reverse proxy, Nginx, to deny connections from anything with "wildebeest" in the user agent string. There are several other good reasons to do this, such as blocking bots that ignore robots.txt, or adapting this approach to serve specialized pages to old browsers, or just denying access to anything that isn't Chrome if you want to earn your place in the 9th circle of Hell.
+
+I'm assuming here that you already know the basics of configuring Nginx, otherwise this article won't really be of much use to you.
+
+## How to do it
+
+Paste this into the main `server` block of your Nginx config to instantly drop the connection to any client with a "Wildebeest" (case insensitive) user agent:
+
+<p class="codetitle">/etc/nginx/sites-available/yoursite</p>
+
+```
+if ($http_user_agent ~* (wildebeest)) {
+ return 444;
+}
+```
+
+## More configuration
+
+If all you want is to block Wildebeest and forget about it, you can leave now. If you want to customize this behavior further, read on.
+
+### Different HTTP responses
+
+444 is a custom response code in Nginx that just drops the connection immediately. You can use any other HTTP error code you like, for example to return a `403 Forbidden` error:
+
+```
+ return 403;
+```
+
+To issue a permanent redirect to some other URL:
+
+```
+ return 301 https://example.org/;
+```
+
+Or just to be silly :3
+
+```
+ return 418;
+```
+
+### Block multiple user agents
+
+You can also block multiple user agents in one statement like so:
+
+<p class="codetitle">/etc/nginx/sites-available/yoursite</p>
+
+```
+if ($http_user_agent ~* (wildebeest|GPTBot)) {
+ return 444;
+}
+```
+
+### Includes
+
+One thing I'd recommend doing is moving all your user agent blocks to a separate file that you can include in all your Nginx sites. I place this file at `/etc/nginx/includes/bans`:
+
+<p class="codetitle">/etc/nginx/includes/bans</p>
+
+```
+if ($http_user_agent ~* (wildebeest|GPTBot)) {
+ return 444;
+}
+```
+
+<p class="codetitle">/etc/nginx/sites-available/yoursite</p>
+
+```
+include /etc/nginx/includes/bans;
+```
+
+The `include` statement goes in your `server` block as before.
diff --git a/blog/posts/guide_blocking_user_agents_nginx/index.php b/blog/posts/guide_blocking_user_agents_nginx/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/guide_blocking_user_agents_nginx/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_fix_youtube_buffering_firefox/bg.svg b/blog/posts/guide_fix_youtube_buffering_firefox/bg.svg
new file mode 100644
index 0000000..5ff0f8c
--- /dev/null
+++ b/blog/posts/guide_fix_youtube_buffering_firefox/bg.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="external-icon" viewBox="0 0 28.57 20" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;">
+ <svg viewBox="0 0 28.57 20" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
+ <g>
+ <path d="M27.9727 3.12324C27.6435 1.89323 26.6768 0.926623 25.4468 0.597366C23.2197 2.24288e-07 14.285 0 14.285 0C14.285 0 5.35042 2.24288e-07 3.12323 0.597366C1.89323 0.926623 0.926623 1.89323 0.597366 3.12324C2.24288e-07 5.35042 0 10 0 10C0 10 2.24288e-07 14.6496 0.597366 16.8768C0.926623 18.1068 1.89323 19.0734 3.12323 19.4026C5.35042 20 14.285 20 14.285 20C14.285 20 23.2197 20 25.4468 19.4026C26.6768 19.0734 27.6435 18.1068 27.9727 16.8768C28.5701 14.6496 28.5701 10 28.5701 10C28.5701 10 28.5677 5.35042 27.9727 3.12324Z" fill="#FF0000"/>
+ <path d="M11.4253 14.2854L18.8477 10.0004L11.4253 5.71533V14.2854Z" fill="white"/>
+ </g>
+ </svg>
+<script xmlns=""/></svg> \ No newline at end of file
diff --git a/blog/posts/guide_fix_youtube_buffering_firefox/index.md b/blog/posts/guide_fix_youtube_buffering_firefox/index.md
new file mode 100644
index 0000000..a66a232
--- /dev/null
+++ b/blog/posts/guide_fix_youtube_buffering_firefox/index.md
@@ -0,0 +1,15 @@
+Remember when you could pause a video on, like, Youtube and wait and it would eventually load the whole thing so you could watch it with no buffering?
+
+![Comic of a guy pausing a Youtube video and reminiscing tearfully about the old days where it would buffer all the way to the end](what_they_took_from_you.png)
+
+I happened across a [tumblr post](https://nyxgoddessofcandles.tumblr.com/post/733566253212598272/theres-more-to-do-actually-now-go-to) detailing some settings to accomplish that in modern Firefox, and I wanted to document it here.
+
+I can't guarantee that this won't stop working at some point amidst the constant churn of arbitrary updates to websites and browsers alike, but it works for me right now, and if I learn about an updated method this is where it'll be.
+
+*Update:* After using my browser with these settings for a while, I've noticed that the first of them breaks online video in some cases, notably Twitch streams and the Jellyfin web client. I've reverted the changes in my browser for this reason.
+
+## How to do it
+
+In `about:config`, change the following settings:
+- Set `media.mediasource.enabled` to `false`
+- Set `media.cache_readahead_limit` and `media.cache_resume_threshold` to `9999` \ No newline at end of file
diff --git a/blog/posts/guide_fix_youtube_buffering_firefox/index.php b/blog/posts/guide_fix_youtube_buffering_firefox/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/guide_fix_youtube_buffering_firefox/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_fix_youtube_buffering_firefox/what_they_took_from_you.png b/blog/posts/guide_fix_youtube_buffering_firefox/what_they_took_from_you.png
new file mode 100644
index 0000000..fb8c77f
--- /dev/null
+++ b/blog/posts/guide_fix_youtube_buffering_firefox/what_they_took_from_you.png
Binary files differ
diff --git a/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/fstab.png b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/fstab.png
new file mode 100644
index 0000000..1e52678
--- /dev/null
+++ b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/fstab.png
Binary files differ
diff --git a/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.md b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.md
new file mode 100644
index 0000000..32ee726
--- /dev/null
+++ b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.md
@@ -0,0 +1,78 @@
+## Preamble
+
+Recently I had to reinstall Linux because of reasons, and I hit a bit of a snag. See, my computer has this setup with three drives where one is the boot drive, and the other has `/home` on it... it's not important, point is, I wanted some drives to be automatically mounted as specific directories at boot time.
+
+This is pretty easy to do with the manual partitioning tools most graphical installers provide, but I would have also had to manually partition the boot drive and hell if I'm figuring out for the umpteenth time how this particular distro with this particular hardware needs to be partitioned in order to be bootable, so I just selected the automatic partitioning option which assumes you just want everything on the boot drive.
+
+the problem is that my system doesn't know my `/home` directory is on `/dev/sda3` and not `/dev/nvme0n1p1`. So I have to fix that now or just log in as root and mount my shit every time I turn the computer on for the rest of time. Guess which thing sounded like more of a pain in the ass. I googled it so you don't have to!
+
+## Now on to the good stuff
+
+I recommend you log out and do this as root in a TTY if you intend to mount something as your home directory.
+
+## Getting partition information
+
+First, run:
+
+```
+sudo blkid
+```
+
+This will return a list of block devices (partitions) your system sees with some information about each, like this:
+
+<p class="codetitle">sudo blkid</p>
+
+```
+/dev/sda1: UUID="YOUR_UUID" BLOCK_SIZE="4096" TYPE="YOUR_TYPE" PARTUUID="30aac87d-21c9-44a9-8033-108eede77f8b"
+```
+
+You'll probably have more than one though. There should be one per partition your system can see. We're interested in the `UUID` and `TYPE` attributes. Find the ones for the partition you want mounted and take note of them. We'll be adding these to your fstab file.
+
+## Editing your fstab
+
+First, make sure the directory you'll be mounting to exists. Create it if it doesn't. **Now make a backup of your fstab file in case you break things!** You can do this by simply copying the file:
+
+```
+sudo cp /etc/fstab /etc/fstab.bak
+```
+
+Now we can edit it. Open `/etc/fstab` in your favorite text editor, and you should be greeted with a file that looks something like this:
+
+![Screenshot of /etc/fstab on my computer before I did this](fstab.png)
+
+(This is the fstab file EndeavourOS generated on install. Because I set it to use btrfs, it mounted the same partition like four separate times as subvolumes. Yours will likely be smaller if you didn't do this.)
+
+This information tells your system which partitions should be mounted and at which locations to mount them, as well as some other settings. We don't need to worry about most of it, though. Simply append a line for your partition to the file:
+
+<p class="codetitle">/etc/fstab</p>
+
+```
+#imagine the contents of your fstab file here
+UUID=YOUR_UUID /path/to/mountpoint YOUR_TYPE defaults 0 0
+```
+
+For example, here are the entries I added for my drives:
+
+<p class="codetitle">/etc/fstab</p>
+
+```
+# btrfs partition on my /home drive
+UUID=44510605-9e1a-45cf-8e6b-bf7fd1c69502 /home btrfs defaults,noatime,compress=zstd 0 0
+
+# ext4 partition on my secondary HDD
+UUID=f8c3f1b1-7fef-4a01-bec7-ba3e89e2f8da /home/isopod/vault ext4 defaults 0 0
+```
+
+If you did it right, you should now be able to reboot and see your partitions have been automatically mounted!
+
+One more thing to keep in mind, if you see any lines with a mount point that's the same as the place you're trying to mount to (for example, the system has mounted a btrfs subvolume for /home and you want to put that on your secondary drive) you should probably comment out or delete that.
+
+## The fast way
+
+Alternatively, you could just paste this into your terminal and then reboot:
+
+```
+partition="/dev/yourpartition"; directory="/path/to/mountpoint"; sudo cp /etc/fstab /etc/fstab.$(date +%s).bak; echo "UUID=$(sudo blkid $partition | sed "s/^.* UUID=\"//;s/\".*//") $directory $(sudo blkid $partition | sed "s/^.* TYPE=\"//;s/\".*//") defaults 0 0" | sudo tee -a /etc/fstab
+```
+
+But don't complain to me if you break your system doing that. \ No newline at end of file
diff --git a/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.php b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/guide_how_to_automount_drives_on_boot_in_linux/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_pihole_lepotato/bg.png b/blog/posts/guide_pihole_lepotato/bg.png
new file mode 100644
index 0000000..c1f34f4
--- /dev/null
+++ b/blog/posts/guide_pihole_lepotato/bg.png
Binary files differ
diff --git a/blog/posts/guide_pihole_lepotato/index.md b/blog/posts/guide_pihole_lepotato/index.md
new file mode 100644
index 0000000..e222568
--- /dev/null
+++ b/blog/posts/guide_pihole_lepotato/index.md
@@ -0,0 +1,77 @@
+[Skip to relevant links](#links)
+
+I set up [Pi-hole](https://pi-hole.net/) on my home network recently. If you're reading this, there's a good chance you've heard of it. It's a network-wide DNS-level ad and tracker blocker designed to run on a **s**ingle-**b**oard **c**omputer like a Raspberry Pi, hence the name. Instead of a Pi, I used a [Libre Computer Le Potato](https://libre.computer/products/aml-s905x-cc/), an alternative board that's almost as good as a Pi 4, and a lot cheaper. I'm gonna show you how to do that.
+
+Before you do anything, and especially before you *buy* anything, make sure your router lets you both assign static IP addresses in some way and set your own DNS servers. This functionality is necessary to use Pi-hole. I can't help you do this, unfortunately &mdash; every router is different and many ISP Specials&trade; are missing these settings.
+
+## Hardware
+
+The Le Potato comes in two flavours: 1GB of RAM and 2GB of RAM. Either will suffice here, though I would go with the 2GB variant just because the 1GB version isn't really that much cheaper. Aside from the board itself, you'll also need a wired network connection<sup id="n1r"><a href="#n1">1</a></sup>, a micro SD card, and an HDMI monitor and keyboard for initial setup, though you can use SSH to access it over the network after that.
+
+As for power, the Le Potato draws about 4 watts at most and as such can run off of any spec-compliant USB port, but the official guides on the Libre Computer forum make a big deal of ensuring the power supply and cable you're using are high-quality and of a generous rating &mdash; they recommend at least a 1.5A USB power source and a suitably **thick** cable to avoid any power issues. Pi-hole is a pretty low-demand application, though, even for this class of hardware, so you'll probably be fine regardless of what you use.
+
+Like the Pi, the Le Potato lacks any built-in storage, so you'll need to supply a micro SD card<sup id="n2r"><a href="#n2">2</a></sup>. The docmentation for Armbian, the OS we'll be using, recommends an "A1" or "A2" class micro SD card, which you can more or less only get from Sandisk right now, for their *significantly* improved random access performance. Ideally you should use one of these, especially since they can be had quite cheaply nowadays, but it's not the end of the world if you have something else kicking around and use that instead. As for capacity, 16GB should be plenty, and you could probably get away with 8GB.
+
+Finally, I'd recommend getting a case. Fortunately, the Le Potato has the same dimensions and layout as, and as such is compatible with cases for, the Raspberry Pi 3 Model B. I 3D printed [this one](https://www.printables.com/model/67681-raspberry-pi-3b-case/files) in PETG, and a wide array of cases are available for cheap online if you can't do the same. I especially like the one that looks like a little NES.
+
+## Booting an OS
+
+Since I'd heard the Le Potato was broadly compatible with the Pi, I initially tried booting a Raspbian image from the official Raspberry Pi flasher tool. Maybe predictably, this did not work. The next thing I tried, and what we'll be using, is Armbian, a lightweight port of Debian designed for tiny SBCs like this one that happens to have a page on its website specifically for the Le Potato.
+
+[Go to that page](https://www.armbian.com/lepotato/) and get one of the **Server** images. I used the latest Debian one. Then write it to the SD card using your favourite flashing tool (I recommend [Balena Etcher](https://etcher.balena.io/)), and insert that into the slot on the Le Potato.
+
+To boot just connect it to power to turn it on and the boot sequence will start automatically. You can have the ethernet connected as you do this, but it seems like the keyboard and possibly display may need to be connected afterwards, so try that if it doesn't boot for you. The Le Potato has a series of indicator LEDs on it next to the micro USB port: essentially, red means it has power; red and blue means it's on; and red, green, and flashing blue means it's running software. Once you get to that last state, you should get output to the monitor soon.
+
+Now we set up Armbian. This process is detailed in the [official documentation](https://docs.armbian.com/User-Guide_Getting-Started/#how-to-boot) for Armbian, and it's fortunately pretty straightforward. It'll ask you to change the default root password, and then give you a choice of shell. Either is perfectly fine, but I like ZSH. Then it will prompt you to create a login for your user account (make sure you're writing these logins down, btw) and then ask for your timezone and other basic local information. If you're connected to the network, it should auto-detect this stuff. If you're left with a root prompt here (it should look like this: `lepotato:~:#`) log out and log back in with the credentials you just created.
+
+This is a good time to assign a static IP address to the Le Potato, so you can access it with SSH going forward. Once you have, reboot it and you should be able to access it via SSH at the local IP you just gave it. On Linux that's just `ssh yourusername@yourlocalip` in the terminal, and on Windows [PuTTY](https://putty.org/) is allegedly good for this.
+
+Now that you're logged in, run a quick software update:
+
+```
+sudo apt update
+sudo apt upgrade
+```
+
+## Setting Up Pi-hole
+
+Installing Pi-hole is pretty simple. Just download and run the install script:
+
+```
+wget -O basic-install.sh https://install.pi-hole.net
+sudo bash basic-install.sh
+```
+
+The script will prompt you for some settings. Most of them are pretty straightforward. I selected "Yes" for everything and the first of the three entries for Quad9<sup id="n3r"><a href="#n3">3</a></sup> as my upstream DNS provider. Set a privacy level to your preference, but maybe check with anyone else you live with before selecting "show everything". Once the installation is done, you can change the web admin password with `pihole -a -p` if desired, and then log in by typing the Le Potato's static IP into your browser.
+
+The last step to get Pi-hole working on your network is to set its static IP as your router's primary DNS server. The Pi-hole devs recommend setting your Pi-hole device as the only DNS server for the network to guarantee it always gets every request, but I set a couple of fallbacks in case my Pi-hole server ever goes down and it seems to still work fine.
+
+## Post-setup Configuration
+
+Pi-hole has a lot of powerful functionality, but here I'd like to focus on fine-tuning your blocklist. The default one is pretty good, but [The Firebog](https://firebog.net/) has a lot of good ones if you'd like to broaden your coverage &mdash; I use one or two of the green ones from each category.
+
+I live with other people who aren't as tolerant of tech weirdness as I am, so for something that'll affect *everything* on the network, convenience often takes priority over maximum adblocking. In other words, I don't want to break anything. There's an [official list](https://discourse.pi-hole.net/t/commonly-whitelisted-domains/212) of commonly whitelisted domains that are important for certain functionality but get blocked by default, and I use [this script](https://github.com/anudeepND/whitelist) to import them and keep the list up to date automatically with a crontab entry.
+
+Beyond that, [this article](https://avoidthehack.com/best-pihole-blocklists) has a lot of good information blocklist-wise.
+
+---
+
+<h2 id="links">Links</h2>
+
+- [Le Potato official guides](https://hub.libre.computer/t/aml-s905x-cc-le-potato-overview-resources-and-guides/288)
+- [Armbian image download page for Le Potato](https://www.armbian.com/lepotato/)
+- [Armbian docs](https://docs.armbian.com/)
+- [Balena Etcher](https://etcher.balena.io/)
+- [Pi-hole docs](https://docs.pi-hole.net/)
+- [The Firebog (blocklist list)](https://firebog.net/)
+- [Commonly whitelisted domain list](https://discourse.pi-hole.net/t/commonly-whitelisted-domains/212)
+- [Common whitelist importer script](https://github.com/anudeepND/whitelist)
+- [Avoid The Hack blocklist article](https://avoidthehack.com/best-pihole-blocklists)
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. You can, theoretically, use wi-fi for this, but I would <strong>strongly</strong> recommend against it.</p>
+
+<p id="n2"><a href="#n2r">2</a>. The Le Potato also has a connector for an EMMC module, but that's a whole different can of worms.</p>
+
+<p id="n3"><a href="#n3r">3</a>. Quad9's filtering is intended to block malware domains. I like having it as an extra layer of security on top of Pi-hole. Any of the DNS providers in the list should work fine, and you can always change it later.</p> \ No newline at end of file
diff --git a/blog/posts/guide_pihole_lepotato/index.php b/blog/posts/guide_pihole_lepotato/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/guide_pihole_lepotato/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/guide_self_host_safely_with_wireguard/index.php b/blog/posts/guide_self_host_safely_with_wireguard/index.php
new file mode 100644
index 0000000..fcc7f05
--- /dev/null
+++ b/blog/posts/guide_self_host_safely_with_wireguard/index.php
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Guide - Self-Host Safe(r)ly with WireGuard</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <link href="/blog/comment/comments.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ h1 {
+ background-image: url('wireguard_logo.png');
+ }
+ </style>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); ?>
+ <h1>guide:</h1>
+ <h2 id="caption">Self-Host Safe(r)ly with WireGuard</h2>
+ <?php include("../post_dates.php"); ?>
+ <p><strong>Warning: The information in this post is outdated and probably bad. I'd update it but I don't remember what I did. I'm pretty sure I had to circumvent UFW entirely. At any rate, probably don't do what I say to do here.</strong></p>
+ <h2>Preamble</h2>
+ <details>
+ <summary>Show preamble</summary>
+ <p>If you're like me, you don't like relying on other people for your online services, either because you don't want to give out your data unnecessarily, or just because you don't want to shell out for subscription services. You might be willing to host such services yourself, and you might even have access to spare hardware to do it on.</p>
+ <p>One critical issue arises, however: your home network. Maybe you're behind some weird impenetrable NAT setup you don't control, or maybe your IP address is dynamic and changes regularly, or maybe you just don't want to expose your home IP to the world. What then?</p>
+ <p>Luckily for us, there's a way to circumvent all that nonsense. A custom VPN like the one we'll be setting up today, hosted on an external server like a VPS, can punch through any weird home internet configuration while also swapping out your home IP address for a static one that you can feel safe exposing to the world.</p>
+ <p>That said, this isn't the be-all end-all for security. I don't claim to know everything about that, and there's probably something you're missing in that regard if you stop here. This is intended as a basic guide for exposing a machine in your home to the internet without messing with your home network or exposing your home IP address.</p>
+ <p>This guide borrows heavily from the <a href="https://landchad.net/wireguard/">landchad.net</a> WireGuard guide, but while their one is geared toward running a VPN for your personal machine (complete with a tutorial on setting up a WebSocket tunnel), this one will focus specifically on forwarding incoming traffic from one server to another over the internet.</p>
+ <p>There are some reasons you'd want to do this instead of just hosting everything on the same VPS - in my case, I wanted to host a Minecraft server, and I had a spare computer at home that was better up to the task than anything for rent in my price range. WireGuard can run on pretty much anything; the cheapest tier on Vultr, DigialOcean or Linode will be more than sufficient.</p>
+ <h2>Now on to the good stuff</h2>
+ </details>
+ <p>This guide will take you through the process of setting up a WireGuard VPN connection between two machines running Linux, and configuring it to forward incoming web traffic from one to the other. It assumes you already have two servers set up running Linux (Ubuntu Server in my case, but any distro should suffice) with UFW configured and enabled, and know what ports you'll need.</p>
+ <p>The machine running your WireGuard server should be an external one exposed to the internet, such as a VPS, for maximum effect. For our purposes, this machine will be the "server", and the one you're forwarding traffic to will be the "client".</p>
+ <p>We'll be configuring WireGuard with a 172.16.0.1/24 virtual network and forwarding port 25565, the default for Minecraft, but any private IP range and port will do.</p>
+ <h2>Installation</h2>
+ <p>First, we'll install WireGuard on both machines:</p>
+ <code>$ apt install wireguard wireguard-tools</code>
+ <p>And allow the port it uses in UFW:</p>
+ <code>$ ufw allow 51820</code>
+ <h3>On the server</h3>
+ <p>Uncomment this line in <code>/etc/sysctl.d/99-sysctl.conf</code> to enable IPv4 forwarding:</p>
+ <code>$ net.ipv4.ip_forward=1</code>
+ <p>And apply the change with this command:</p>
+ <code>$ sysctl -w net.ipv4.ip_forward=1</code>
+ <h3>On the client</h3>
+ <p>We'll need to generate a public/private key pair for each machine on our VPN network. Do that now for our client like so:</p>
+ <code>$ sudo bash -c "umask 077 ; wg genkey &gt; /etc/wireguard/client_priv.key"<br>$ sudo bash -c "wg pubkey &lt; /etc/wireguard/client_priv.key &gt; /etc/wireguard/client_pub.key"</code>
+ <p>This generates a private key for WireGuard and then generates a corresponding public key based on it. Our client's keys can now be found in <code>/etc/wireguard/client_priv.key</code> and <code>/etc/wireguard/client_pub.key</code> for our private and public keys respectively.</p>
+ <h3>Back to the server</h3>
+ <p>Now do the same for the server:</p>
+ <code>$ umask 077 ; wg genkey &gt; /etc/wireguard/server_priv.key<br>$ wg pubkey &lt; /etc/wireguard/server_priv.key &gt; /etc/wireguard/server_pub.key</code>
+ <p>Our server's keys can now be found in <code>/etc/wireguard/server_priv.key</code> and <code>/etc/wireguard/server_pub.key</code> for our private and public keys respectively.</p>
+ <p>Now, create a WireGuard configuration file at <code>/etc/wireguard/wg0.conf</code>. <code>wg0</code> will be the name of our network interface, you can name yours something else if you'd like.</p>
+ <code>[Interface]<br>Address = 172.16.0.1/24<br>ListenPort = 51820<br>PrivateKey = &nbsp;&nbsp;#(server's private key goes here)<br># Firewall rules<br>PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE<br>PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE<br><br>[Peer]<br># Client #1 details<br>PublicKey = &nbsp;&nbsp;#(client's public key goes here)<br># Traffic to route to this client<br>AllowedIPs = 172.16.0.2/32</code>
+ <p>Paste the server's private key after <code>PrivateKey =</code> in <code>[Interface]</code> and the client's public key after <code>PublicKey =</code> in <code>[Peer]</code>.</p>
+ <p>With this setup, our server will use the virtual local IP <code>172.16.0.1</code> and our client will use the IP <code>172.16.0.2</code>. You can also add up to 254 more clients by duplicating the <code>[Peer]</code> block and and updating it with the respective public key and a new local IP address.</p>
+ <p>Now, enable and start the WireGuard service with</p>
+ <code>$ systemctl enable --now wg-quick@wg0.service</code>
+ <p><code>wg0</code> being what we called our network interface before.</p>
+ <h3>Back to the client</h3>
+ <p>Create a WireGuard configuration file for our client at <code>/etc/wireguard/myvpn.conf</code> (you can replace <code>myvpn</code> with a different name if you so choose):</p>
+ <code>[Interface]<br>Address = 172.16.0.2/24<br>PrivateKey = &nbsp;&nbsp;#(client's private key goes here)<br># Optionally, set to your desired DNS server<br># DNS = 9.9.9.9<br><br>[Peer]<br>PublicKey = &nbsp;&nbsp;#(server's public key goes here)<br># Endpoint (server) can be a domain name or IP address<br>Endpoint = (server's public IP goes here):51820<br># Traffic to route to server<br>AllowedIPs = 0.0.0.0/0, ::/0<br>PersistentKeepalive = 25</code>
+ <p>Make sure you use your server's public IP here. The PersistentKeepalive option is there because WireGuard closes the connection by default if no data comes through for a while and will only reopen it for the client, so here we send a KeepAlive packet every 25 seconds to prevent that in order to keep our client accessible from the internet.</p>
+ <p>Now we start WireGuard:</p>
+ <code>$ sudo wg-quick up myvpn</code>
+ <p><code>myvpn</code> being whatever you called your vpn before. Shut WireGuard down by typing <code>down</code> instead of <code>up</code> here. At this point, you should be able to ping the server (<code>172.16.0.1</code>) or any URL from the client and get a response.</p>
+ <h2>Port Forwarding</h2>
+ <p>Now we'll configure the firewall and port forwarding. This bit assumes you already have UFW configured and enabled. You can set it up now if necessary.</p>
+ <h3>On the server</h3>
+ <p>Allow forwarding for the ports you need:</p>
+ <code>$ ufw route allow proto tcp to 172.16.0.2 port 25565</code>
+ <p><code>25565</code> being your relevant port. Repeat this command as necessary.</p>
+ <p>Now we need to configure iptables. We can do this through UFW by adding the following onto the very end of the file <code>/etc/ufw&#8288;/before.rules</code>:</p>
+ <code>*nat<br>:PREROUTING ACCEPT [0:0]<br>:POSTROUTING ACCEPT [0:0]<br>-A PREROUTING -i eth0 -p tcp --dport 25565 -j DNAT --to-destination 172.16.0.2<br>-A POSTROUTING -o eth0 -j MASQUERADE<br>COMMIT</code>
+ <p>Where <code>25565</code> is, again, your relevant port. Copy the <code>-A PREROUTING</code> line for every port you need.</p>
+ <p>Now restart UFW:</p>
+ <code>$ ufw reload</code>
+ <h3>On the client</h3>
+ <p>Allow the relevant ports and restart UFW:</p>
+ <code>$ ufw allow 51820<br>$ ufw allow 25565<br>$ ufw reload</code>
+ <p>And you're done! At this point, your client should be accessible from the IP address of your server on the ports you forwarded.</p>
+ <?php include("../../comment/form.php"); ?>
+ </body>
+</html>
diff --git a/blog/posts/guide_self_host_safely_with_wireguard/wireguard_logo.png b/blog/posts/guide_self_host_safely_with_wireguard/wireguard_logo.png
new file mode 100644
index 0000000..aaa4e03
--- /dev/null
+++ b/blog/posts/guide_self_host_safely_with_wireguard/wireguard_logo.png
Binary files differ
diff --git a/blog/posts/guide_things_i_keep_having_to_google/index.php b/blog/posts/guide_things_i_keep_having_to_google/index.php
new file mode 100644
index 0000000..f6f9224
--- /dev/null
+++ b/blog/posts/guide_things_i_keep_having_to_google/index.php
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Guide - Things I Keep Having to Google</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <link href="/blog/comment/comments.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ /*h1 {
+ background-image: url('wireguard_logo.png');
+ }
+ summary > * {
+ margin-bottom: 0;
+ display: inline-block;
+ }
+ details[open] > summary h6 {
+ display: none;
+ }
+ td {
+ padding: .2rem;
+ }
+ td h4 {
+ margin: 0;
+ }*/
+ </style>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); ?>
+ <h1>guide:</h1>
+ <h2 id="caption">Things I Keep Having to Google</h2>
+ <?php include("../post_dates.php"); ?>
+ <p>This isn't really a guide to anything in particular, I just wanted an easily accessible reference for all the things I'm sick of wading through google results for, or otherwise seem to need help remembering. I've put it here in case someone else might find this helpful. I'll likely be adding to this as I find myself repeatedly googling things.</p>
+ <h2>Binding things to just the Super key in KDE</h2>
+ <ol>
+ <li>Bind it to some other keyboard shortcut using KDE's typical GUI methods. Any shortcut will do.</li>
+ <li>Find the entry for it in <code>~/.config/khotkeysrc</code>. There should be a line that looks like: <code>Uuid={77575b17-36d6-4b4e-b01f-2f1156e38583}</code>. Copy everything inside the curly braces, including the braces themselves.</li>
+ <li>Run the following commands:</li>
+ </ol>
+ <code style="overflow: scroll;">$ kwriteconfig5 --file ~/.config/kwinrc --group ModifierOnlyShortcuts --key Meta "org.kde.kglobalaccel,/component/khotkeys,org.kde.kglobalaccel.Component,invokeShortcut,&lt;YOUR UUID HERE&gt;"<br>$ qdbus org.kde.KWin /KWin reconfigure</code>
+ <h2>Linux command line/Bash stuff</h2>
+ <table>
+ <tr><td colspan="2"><h4>pipeline</h4></td></tr>
+ <tr><td><code>command | command2</code></td><td>uses the output of one command as the input to the next</td></tr>
+ <tr><td><code>command &gt; file</code></td><td>saves the output of a command to a file</td></tr>
+ <tr><td><code>command &lt; file</code></td><td>uses a file as the input to a command</td></tr>
+ <tr><td><code>command &lt; fileA &gt; fileB</code></td><td>will therefore run <code>command</code> with the contents of <code>fileA</code> as the input, and save the output to <code>fileB</code></td></tr>
+ <tr><td style="white-space:nowrap;"><code>command &lt;&lt;&lt; "string or $variable"</code></td><td>will use the string or variable as the input to a command, the same as <code>&nbsp;&lt; file</code></td></tr>
+ <tr><td colspan="2"><h4>variables</h4></td></tr>
+ <tr><td><code>variable=value</code></td><td>assigns a variable</td></tr>
+ <tr><td><code>$variable</code></td><td>references it</td></tr>
+ <tr><td><code>$(command)</code></td><td>lets you treat the output of a command like a variable reference</td></tr>
+ <tr><td><code>$((number+variable))</code></td><td>does the same thing for integer math expressions.</td></tr>
+ <tr><td><code>$((&nbsp;$(command)&nbsp;))<br>$((&nbsp;variable&nbsp;))</code></td><td>This can also just convert strings into integers.</td></tr>
+ <tr><td><code>"te$(command)xt"<br>"as$((math))df"</code></td><td>Both can be inserted into strings.</td></tr>
+ <tr><td><code>"some&nbsp;$variable&nbsp;text"<br>"more${variable}text"</code></td><td>Both of these are valid ways to insert a variable into a string.</td></tr>
+ <tr><td colspan="2"><h4>grep</h4></td></tr>
+ <tr><td><code>-v</code></td><td>Inverts it, so matches are excluded</td></tr>
+ <tr><td><code>-E "/regex/"</code></td><td>Lets you use regex</td></tr>
+ <tr><td colspan="2"><h4>cut</h4></td></tr>
+ <tr><td><code>-d 'string'</code></td><td>Determines the delimiter string, the default is the TAB character</td></tr>
+ <tr><td><code>-f n</code></td><td>Specifies a field to output, delimited by <code>-d</code></td></tr>
+ <tr><td><code>sed 's/&nbsp;&nbsp;*/&nbsp;/g' | cut -d ' '</code></td><td>Piping your thing through this <span title="It's not foolproof, though. Make sure you understand what this is doing so you can adapt it if it breaks.">helps</span> with parsing a lot of Linux commands that output tabular data</td></tr>
+ <tr><td colspan="2"><h4>sed</h4></td></tr>
+ <tr><td><code>sed "s/regex/replacement/flags"</code></td><td>The basic sed replacement command, checks a line of input against the provided regular expression <code>regex</code> and replaces matches with <code>replacement</code>.</td></tr>
+ <tr><td><code>sed "s/a/b/;s/c/d/"</code></td><td>Multiple sed commands can be strung together in one, like so.</td></tr>
+ <tr><td><code>sed "s/a/b/g"</code></td><td>The <code>g</code> flag makes sed replace all occurences of the pattern, not just the first</td></tr>
+ <tr><td><code>sed "s/a/b/&lt;number&gt;"</code></td><td>Insert any number to tell sed to replace only that occurence. Counts from 1. Theoretically, <code>s/a/b/</code> is the same as <code>s/a/b/1</code>.</td></tr>
+ <tr><td><code>sed "s/a/b/i"</code></td><td>GNU extension - Match case-insensitively.</td></tr>
+ <tr><td><code>sed "s/^a/b/"</code></td><td>Require that a match be at the beginning of the line.</td></tr>
+ <tr><td><code>sed "s/a$/b/"</code></td><td>Require that a match be at the end of the line.</td></tr>
+ <tr><td><code>sed "s/^a$/b/"</code></td><td>Require that a match be both at the beginning and the end - in other words, require that a match be the entire line.</td></tr>
+ <tr><td colspan="2"><h4>find</h4></td></tr>
+ <tr><td><code>find</code></td><td>Lists every file and directory in the current working directory</td></tr>
+ <tr><td><code>find /dir</code></td><td>Does the same for the directory you specify</td></tr>
+ <tr><td><code>find -name "foo"</code></td><td>Only lists things with a matching name. * can be used as a wildcard.</td></tr>
+ <tr><td><code>find -exec command {} \;</code></td><td>Runs <code>command</code> on everything found by <code>find</code>. <code>{}</code> is replaced by the output.</td></tr>
+ <tr><td colspan="2"><h4>misc</h4></td></tr>
+ <tr><td><code>xrandr --output &lt;display name&gt; --brightness &lt;brightness&gt;</code></td><td title="It would definitely for sure be better to change this via the monitor's built-in menus, but that requires navigating both of my monitors' built-in menus.">Janky software-side display brightness setting with xrandr</td></tr>
+ <tr><td><code>wget "https://example.com/file.zip" -O temp.zip; unzip temp.zip; rm temp.zip</code></td><td>Bash one-liner to unzip a file from the internet to the current directory</td></tr>
+ <tr><td><code>yt-dlp -x --audio-format flac --audio-quality 0 -P ~/Music/Library/ -o "%(uploader)s - %(title)s.%(ext)s"</code></td><td>My standard <a href="https://github.com/yt-dlp/yt-dlp#readme">yt-dlp</a> command for ripping music from Youtube and Soundcloud. I have an alias for this so I don't have to write it out every time.</td></tr>
+ <tr><td><code>alias myalias="command go here"</code></td><td>Set an alias in bash. Put this in your .bashrc or similar to make it permanent.</td></tr>
+ </table>
+ <h2>Webdev stuff</h2>
+ <h4>Tables</h4>
+ <ul>
+ <li>Force a <code>&lt;td&gt;</code> element not to wrap by adding the <code>white-space:nowrap;</code> CSS property to it.</li>
+ <li>Set the <code>table-layout</code> CSS property to <code>fixed</code> to force the the columns to be equal widths.</li>
+ </ul>
+ <h4>PHP</h4>
+ <ul>
+ <li>The <code>date()</code> function in PHP returns date information. The first argument is a format string and the second is an optional integer for a Unix timestamp. The valid format characters as of PHP 8 can be found <a href="https://www.php.net/manual/en/datetime.format.php">here</a>.<!--, and examples are listed in this table:
+ <details>
+ <summary>Show table</summary><br>
+ It is currently <?php echo date('l, F j, Y \a\t g:i:s A T');?><br><br>
+ <table class="highlightrows" style="table-layout: fixed; width: 100%;">
+ <tr style="font-weight: bold;"><td>Character</td><td>Output</td><td>Character</td><td>Output</td></tr>
+ <tr><td>Y</td><td><?php echo date("Y");?></td><td>y</td><td><?php echo date("y");?></td></tr>
+ <tr><td>o</td><td><?php echo date("o");?></td><td>L</td><td><?php echo date("L");?></td></tr>
+ <tr><td>F</td><td><?php echo date("F");?></td><td>M</td><td><?php echo date("M");?></td></tr>
+ <tr><td>m</td><td><?php echo date("m");?></td><td>n</td><td><?php echo date("n");?></td></tr>
+ <tr><td>t</td><td><?php echo date("t");?></td><td>W</td><td><?php echo date("W");?></td></tr>
+ <tr><td>l</td><td><?php echo date("l");?></td><td>D</td><td><?php echo date("D");?></td></tr>
+ <tr><td>d</td><td><?php echo date("d");?></td><td>j</td><td><?php echo date("j");?></td></tr>
+ <tr><td>S</td><td><?php echo date("S");?></td><td>z</td><td><?php echo date("z");?></td></tr>
+ <tr><td>N</td><td><?php echo date("N");?></td><td>w</td><td><?php echo date("w");?></td></tr>
+ <tr><td>A</td><td><?php echo date("A");?></td><td>a</td><td><?php echo date("a");?></td></tr>
+ <tr><td>g</td><td><?php echo date("g");?></td><td>G</td><td><?php echo date("G");?></td></tr>
+ <tr><td>h</td><td><?php echo date("h");?></td><td>H</td><td><?php echo date("H");?></td></tr>
+ <tr><td>i</td><td><?php echo date("i");?></td><td>s</td><td><?php echo date("s");?></td></tr>
+ <tr title="These are milliseconds and microseconds respectively. They will both return 0 when used with date() as it takes the Unix timestamp as an integer in seconds, but there are other functions that take this formatting and will return these accurately."><td>v</td><td><?php echo date("v");?></td><td>u</td><td><?php echo date("u");?></td></tr>
+ <tr><td title="This one is so funny to me. This is Swatch Internet Time, a time system created in 1998 by the Swatch corporation to promote their &quot;Beat&quot; watches. It divides the day into 1000 equal chunks 86.4 seconds long. I encourage you to go read the Wikipedia page for this thing. It's great. Why PHP has a function for it I have no idea.">B</td><td><?php echo date("B");?></td><td>I</td><td><?php echo date("I");?></td></tr>
+ <tr><td>e</td><td><?php echo date("e");?></td><td>O</td><td><?php echo date("O");?></td></tr>
+ <tr><td>P</td><td><?php echo date("P");?><td>Z</td><td><?php echo date("Z");?></td></tr>
+ <tr><td title="You can also use the function time() for this.">U</td><td colspan="3"><?php echo date("U");?></td></tr>
+ <tr><td>c</td><td colspan="3"><?php echo date("c");?></td></tr>
+ <tr><td>r</td><td colspan="3"><?php echo date("r");?></td></tr>
+ </table>
+ </details--><br><br>
+ The <code>strtotime()</code> function does the reverse operation, converting date strings to Unix timestamps. Storing dates as Unix timestamps and converting when needed is recommended.</li>
+ </ul>
+ <h2>Song Lyrics</h2>
+ <p>I don't actually have a solution for this one, I just wish there was a resource for looking up the lyrics to songs and looking up songs by their lyrics that wasn't an SEO leech site.</p>
+ <?php include("../../comment/form.php"); ?>
+ </body>
+</html>
diff --git a/blog/posts/how_my_blog_works/index.md b/blog/posts/how_my_blog_works/index.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/blog/posts/how_my_blog_works/index.md
diff --git a/blog/posts/how_my_blog_works/index.php b/blog/posts/how_my_blog_works/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/how_my_blog_works/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/make_your_own_cables/2pindin.jpg b/blog/posts/make_your_own_cables/2pindin.jpg
new file mode 100644
index 0000000..fdbf578
--- /dev/null
+++ b/blog/posts/make_your_own_cables/2pindin.jpg
Binary files differ
diff --git a/blog/posts/make_your_own_cables/4pinminixlr.png b/blog/posts/make_your_own_cables/4pinminixlr.png
new file mode 100644
index 0000000..4e5fdb9
--- /dev/null
+++ b/blog/posts/make_your_own_cables/4pinminixlr.png
Binary files differ
diff --git a/blog/posts/make_your_own_cables/homebrew2pindincable.jpg b/blog/posts/make_your_own_cables/homebrew2pindincable.jpg
new file mode 100644
index 0000000..503dda8
--- /dev/null
+++ b/blog/posts/make_your_own_cables/homebrew2pindincable.jpg
Binary files differ
diff --git a/blog/posts/make_your_own_cables/homebrewxlrcablefinished.jpg b/blog/posts/make_your_own_cables/homebrewxlrcablefinished.jpg
new file mode 100644
index 0000000..6d2b9c1
--- /dev/null
+++ b/blog/posts/make_your_own_cables/homebrewxlrcablefinished.jpg
Binary files differ
diff --git a/blog/posts/make_your_own_cables/index.md b/blog/posts/make_your_own_cables/index.md
new file mode 100644
index 0000000..c981dbc
--- /dev/null
+++ b/blog/posts/make_your_own_cables/index.md
@@ -0,0 +1,37 @@
+My current main headphones are a model that doesn't come with a removable cable by default, that I purchased through a company that offers a service to add one aftermarket for you. They offered multiple different connector options, and I chose this one:
+
+![4-pin mini XLR male and female jacks. The pins are arranged in a Y shape.](4pinminixlr.png)
+
+This is one of two connector types that come up when you search for "4-pin mini XLR". I opted for this connector on the basis that it would allow me to potentially use the headphones with a balanced output in the future, because I had been researching headphones for probably several days and eventually you start to think that kind of thing is important.
+
+This worked fine for me for quite a while, up until recently, when the included cable that adapts this to a standard 3.5mm TRS headphone jack connector stopped working. When I tried to find a replacement, I quickly learned that this connector is only meaningfully present on headphones that are so expensive that anyone who can afford them can be expected to be able to shell out upwards of 100 of God's own United States Dollars for a top-of-the-line snake-oil-lubricated replacement cable.
+
+So universally is this the case that there is seemingly essentially no market for cheap cables of this type — the only sanely priced one I could find was a mono instrument cable with a proprietary pinout designed for use with some Shure product. The cheapest compatible replacement cable I could find was made by the aforementioned modding company and was listed at a cool $140 CAD, well in excess of half of what my headphones themselves are worth. It should go without saying that there is no audio cable on this planet for which I would pay that kind of money, which brings me to where I'm going with this.
+
+Instead of shelling out Intel Core i3-13100F money for what functionally amounts to 3 meters of wire and a couple of audio jacks, I lopped the connectors off of the old, broken cable and soldered on some new wires and saved myself $140.
+
+<figure class="media">
+ <div>
+ <img src="homebrewxlrcablefinished.jpg" alt="A 3.5mm jack to 4-pin mini XLR adapter cable with a shiny black braided exterior">
+ <figcaption>This braided sheathing can be had for cheap on Amazon by searching "braided cable sleeve". I used the 6mm variant here, and it comfortably fits the three 24AWG wires.</figcaption>
+ </div>
+</figure>
+
+This isn't the only time I've had to do this, either — I, through a bizarre series of events, happen to own a piece of musical equipment made in the 1960s, in the Netherlands, with weird output jacks to match:
+
+![Male and female 2-pin DIN connectors](2pindin.jpg "By boffy_b - Own work, Copyrighted free use, https://commons.wikimedia.org/w/index.php?curid=1010205")
+
+These are 2-pin DIN connectors, from the same family as the 5-pin DIN connectors you may be familiar with from their use in MIDI ports. My device uses a pair of these for stereo output. I can only assume this was standard at the time, in the Netherlands, but where and when I live this type of connector is all but unheard of, to the point that there are *no* cables with it available whatsoever, only the bare connectors.
+
+In order to get this thing connected to my other equipment, I had to fashion my own adapter cable out of a stereo-to-dual-mono TRS splitter cable and two of those connectors purchased standalone from the internet.
+
+<figure class="media">
+ <div>
+ <img src="homebrew2pindincable.jpg" alt="A Stereo 1/4 inch TRS to dual mono 2-pin DIN adapter cable">
+ <figcaption>I wonder how far away from me the nearest other cable of this type is.</figcaption>
+ </div>
+</figure>
+
+I'm not going to attempt to teach you how to do this here — there's plenty of people on Youtube who are much more qualified to do that than me — but I think if you're at all comfortable messing with electronics this is a good skill to have. It's proven surprisingly useful to me, not just as a hobbyist who builds weird electronic gizmos for fun but as a casual enjoyer and maker of music.
+
+If this ever happens to you, consider saving the money on some bullshit expensive cable and spending it on some [soldering gear](https://pine64.com/product-category/pinecil/) instead. It's easier than you probably think it is and it can save you, like, a lot of money. \ No newline at end of file
diff --git a/blog/posts/make_your_own_cables/index.php b/blog/posts/make_your_own_cables/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/make_your_own_cables/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/my_terrible_distro_hop/bg.png b/blog/posts/my_terrible_distro_hop/bg.png
new file mode 100644
index 0000000..c3d448c
--- /dev/null
+++ b/blog/posts/my_terrible_distro_hop/bg.png
Binary files differ
diff --git a/blog/posts/my_terrible_distro_hop/index.md b/blog/posts/my_terrible_distro_hop/index.md
new file mode 100644
index 0000000..556da49
--- /dev/null
+++ b/blog/posts/my_terrible_distro_hop/index.md
@@ -0,0 +1,116 @@
+## Prologue
+
+Of late, I've been having some mildly annoying, highly esoteric issues, of the sort any desktop OS tends to develop given enough time, with my daily-driver install of the Arch-based EndeavourOS with XFCE. The most annoying of these annoyances include the XFCE panel daemon having stopped running on login, which I dealt with by binding the command to start it to a keyboard shortcut, and the monitor layout defaulting to mirrored every time I locked the screen, which I dealt with much the same way. I say of late, but I've been dealing with this shit for months. These seemed like bugs somewhere deep in XFCE that I really didn't have the energy to try to fix, so my solution was to just go scorched-earth and start again with something new.
+
+The something new I landed on was a fresh install of Fedora. I chose Fedora partially for the GNOME desktop environment, which, to be blunt, seems to have its shit together much more than XFCE does (or KDE for that matter), and partially because I was hoping that by moving away from a rolling-release distro to something more stable I could avoid some of the inscrutable weirdness that kept materializing after updates on Arch<sup id="n1r"><a href="#n1">1</a></sup>. Plus, I was excited to once again be on an OS with some more sane defaults, like flatpaks and Bluetooth being available out of the box. This is what was going through my head as I loaded the Fedora live ISO onto a flash drive and rebooted my computer.
+
+I had no idea what I was about to get myself into.
+
+## The Installation Experience
+
+The installation went very smoothly. I was actually pretty impressed. It was probably the fastest I've ever installed Linux - All it did was prompt me for a language, timezone, and the drive to install to and a few minutes later it was done. Fast and simple even by Linux installation standards. It was the next part that was painful.
+
+## Setup (Or Rather, My Doomed Attempt Thereof)
+
+I should say here that this isn't a review of Fedora as much as it is just me venting. It seems like it would be great for the kind of user it's designed for, but as it turns out that is *not* me. Honestly, a lot of this stuff may or may not have been my fault. Anyway, on to the pain.
+
+The first weird thing I noticed was that Firefox had reverted to the default profile instead of recalling my settings from before. Normal, except that I store my /home/ directory on a separate drive and the first thing I did was [reconfigure my fstab](../guide_how_to_automount_drives_on_boot_in_linux/) as such, so it should have seen the config files and just loaded them right up. Odd.
+
+I also had to manually install all the nonfree media codecs in order to watch videos on Youtube, but that's basically fine. Takes two seconds and you never have to think about it again. Would have been nice to be prompted for that on install, though.
+
+Anyway, this issue with programs not seeing their existing config files would become a running theme. I would later discover that this had something to do with the fact that all this stuff had been installed as flatpaks, as opposed to a native installation from the distro's repositories or the AUR like it would have been before.
+
+See, for some (probably security-related) reason, flatpaks store their config files in a different place than natively installed programs, and the preinstalled graphical Software Center, which I was using to install all this stuff, seems to like to default to flatpaks whenever possible. I never used flatpaks on my previous install because they weren't enabled by default, hence, almost none of the programs I installed remembered their previous settings.
+
+To be clear, this probably would have been fine if flatpaks were already my go-to, but they weren't, and I wasn't about to reconfigure all my shit or go way out of my way to be particular about which packaging method I preferred for my software in order to avoid reconfiguring all my shit.
+
+On a related note, a lot of the software in the repositories that were available to me was *severely* outdated. PrusaSlicer, for example, was only available in version 2.4.2, which was released in April of 2022. As of writing in February of 2024, the latest version is 2.7.1. It was upon going to Prusa's website to download the AppImage of the latest version like some kind of fucking caveman and discovering that AppImageLauncher<sup id="n2r"><a href="#n2">2</a></sup> wasn't in *any* of the repos that I got fed up, decided I wasn't gonna risk dealing with this type of shit for every program I wanted to install and noped out.
+
+## Where To Next
+
+So Fedora was a bust, so where do I go from here? I considered moving to an Ubuntu-based distribution like Pop!_OS or Mint that might give me what I wanted from Fedora, and I briefly considered going back to Manjaro for reasons I have honestly forgotten, but I had been at this for hours now and I really just wanted my computer in a usable state again with the minimum possible amount of adaptation, so I came crawling back to EndeavourOS, and went to take a nap while it installed to hopefully come back to this ordeal with a cooler head.
+
+I kept using GNOME, though. I kinda like it. I switched to XFCE initially because I had been looking at r/unixporn and had it in my head that I wanted really granular customization, but that honestly didn't last long. I got it looking [decent](https://rosepinetheme.com/) and then got bored. Eventually, the creeping accumulation of jank and bugs got tiresome, and my hope is that GNOME is sufficiently well-integrated and UX-designed to avoid some of that.
+
+I have a couple issues with GNOME, though. I don't much like the MacOS-style grid of large icons as an app launcher, for one, having gotten used to the density of a barely-configured Rofi menu. I've also gotten used to seeing at a glance what programs I have open, from years of using basically every desktop environment but GNOME, from KDE to XFCE to fucking Windows. I'd like if that was available in, say, the positively barren top panel. I found an extension for that, but it doesn't seem to work properly.
+
+Beyond that, I've been acclimating to the fresh install pretty much fine. All my programs are set up the way I like them again, which is nice. Turns out GNOME ships with Wayland by default now, and it's actually been giving me fewer issues than I was expecting. Even gaming is fine from what I've seen so far (what kind of topsy turvy world are we living in where gaming is one of the EASIEST things to do on Linux?), but I did have to pass the flag `-platform xcb` to OBS to get it to run. Also, the state of graphical package managers on Arch is utterly abysmal, but that's neither here nor there.
+
+I do have one very difficult issue, though.
+
+## What Is The Fucking Deal With ProtonVPN On Linux
+
+I use ProtonVPN, and one of the things I attempted to do on Fedora was set it back up. I don't know what I did originally to dodge this, but trying to set it up recently, both on Fedora and on Arch, has been an excercise in navigating an insane maze of complete and utter bullshit.
+
+Proton lists Fedora as officially supported by ProtonVPN. Great! One issue: It Fucking Isn't, It Would Seem. The ProtonVPN client is only present in the Software Center as an unofficial GTK app (as opposed to the Electron app I'm used to (I know, ugh)) that refused to work. I went to Proton's website and followed the instructions there, only to end up with a very similar looking GTK app that very similarly didn't work. Awesome.
+
+Fortunately, ProtonVPN supports connecting using OpenVPN, and GNOME's network settings panel has an option for that built right in! I download the relevant configuration file from the ProtonVPN website and it also doesn't work. Even awesomer!
+
+Back on Arch, which is *not* officially supported, I install the AUR package that worked perfectly before and it fails. Trying to connect via the CLI (which, by the way, didn't exist in Fedoraland) with my usual settings gives this output:
+
+<p class="codetitle">protonvpn-cli c --cc CA -p udp</p>
+
+```
+Setting up Proton VPN.
+Connecting to Proton VPN on CA#166 with UDP.
+
+Unable to connect to Proton VPN: Proton VPN connection failed due to unknown reason.
+```
+
+Tremendously fucking helpful. Why even bother having an error message if it's gonna tell me nothing?
+
+So I look up this "unknown reason" error and find a Github issue where someone says to run a `journalctl` command to see if there's any errors, and wouldn't you know it, I find one!
+
+<p class="codetitle">sudo journalctl -eu NetworkManager</p>
+
+```
+"Proton VPN CA#166"]: secrets: failed to request VPN secrets #3: No agents were available for this request.
+```
+
+Progress! I think. I don't know what this means. I look up this error and find a different Github issue where someone claims to have fixed a similar issue by installing a package called nm-applet, which... doesn't seem to exist. Transcendantly spectacular!!!
+
+(Mind you, all this is going on on a repo that was archived some time last year, which seems ominous. Please tell me that weird GTK client from Fedora that's missing a CLI isn't the up-to-date official solution.)
+
+So I look up "nm-applet" and find a Stackoverflow thread from eight years ago where someone is describing an unrelated issue with an ancient version of GNOME and I learn that the package I'm looking for is actually called `network-manager-applet` and not `nm-applet` in the Arch repos for some reason. So I install it and run the `nm-applet` command, and, bracing for disappointment, run the command to start the VPN...
+
+<p class="codetitle">protonvpn-cli c --cc CA -p udp</p>
+
+```
+Setting up Proton VPN.
+Connecting to Proton VPN on CA#70 with UDP.
+
+Successfully connected to Proton VPN.
+```
+
+huh.
+
+I think the Github user I learned this from says it best in their comment:
+
+<figure class="quote">
+ <blockquote>
+ Yes!!! It needs [network-manager]-applet!!<br><br>
+ Oh man, that was a saga, and what a simple fix!<br><br>
+ Thanks so much. I understand that protonvpn doesn't want to say that it "officially supports" desktop environments other than GNOME or KDE, but I think it would still be really great if we could add some documentation here.
+ </blockquote>
+ <figcaption>
+ &mdash; ExpandingMan, <a href="https://github.com/ProtonVPN/linux-cli/issues/49#issuecomment-910662957">connecting fails due to failure to get secrets #49</a>
+ </figcaption>
+</figure>
+
+I have a couple questions. One, why isn't this listed as a dependency if not having it breaks everything? I assume it's the fault of the person maintaining the AUR package, but that seems like a weird oversight on a family of distros where that package *clearly* does not come standard.
+
+Two, what's going on with ProtonVPN clients on Linux? It looks like the Electron app and accompanying CLI (which I quite liked) are deprecated as of last October? And replaced with that weird GTK thing that's missing a bunch of features and doesn't include a CLI anymore? What the fuck? Why did they make it worse? I mean, it's not like this isn't part of a pattern for Proton. I'm pretty sure the Proton Drive desktop client still isn't on Linux yet.
+
+Also, three, why wasn't network-manager-applet already installed? This thing seems like a pretty important system package, especially given the rest of network-manager was already present and seems to be the thing allowing me to connect to the internet right now. Well, such is Arch I suppose. The type of Linux user who runs this thing seems to tend towards having a pathological obsession with bloat and the relevant de-'s<sup id="n3r"><a href="#n3">3</a></sup>.
+
+## Oh Sweet It's Fine Actually
+
+That concludes my blog post, and the blog-post-within-a-blog-post that appears to have metastasized up there. I think you should know I finished troubleshooting both ProtonVPN *and* OBS while writing the post chronicling my suffering. Thank you for indulging my bitching and moaning about totally avoidable software problems. Who knows, maybe this will help you. For your sake, I hope it doesn't.
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. I say Arch, and not EndeavourOS, because I used to use Manjaro and it was like this too.</p>
+
+<p id="n2"><a href="#n2r">2</a>. AppImages are programs packaged as standalone executables. They don't need to be installed - AppImageLauncher isn't necessary to run them, but it's my preferred tool for integrating them into the system with menu entries and such.</p>
+
+<p id="n3"><a href="#n3r">3</a>. nuts</p> \ No newline at end of file
diff --git a/blog/posts/my_terrible_distro_hop/index.php b/blog/posts/my_terrible_distro_hop/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/my_terrible_distro_hop/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/post.php b/blog/posts/post.php
new file mode 100644
index 0000000..e6b13b6
--- /dev/null
+++ b/blog/posts/post.php
@@ -0,0 +1,105 @@
+<?php
+$cwd = preg_replace('/^.*\//', '', getcwd());
+$feed = simplexml_load_file($_SERVER['DOCUMENT_ROOT']."/blog/blog.atom");
+$pdate = "";
+$udate = "";
+$title = "";
+$descr = "";
+foreach($feed->entry as $entry) {
+ if($entry->id == $cwd) {
+ $pdate = preg_replace('/T.*$/', ' ', $entry->published);
+ $udate = preg_replace('/T.*$/', ' ', $entry->updated);
+ $title = $entry->title;
+ $descr = $entry->summary;
+ break;
+ }
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <link href="/blog/comment/comments.css" rel="stylesheet" type="text/css" media="all">
+ <?php
+ echo("<title>$title</title><meta name='description' content='$descr'>");
+ $bgfile = glob('bg.*')[0];
+ if(!is_null($bgfile)) {
+ echo("<style> h1 { background-image: url('$bgfile') } </style>");
+ }
+ ?>
+ <style>
+ td {
+ display: table-cell;
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php
+ include($_SERVER['DOCUMENT_ROOT'] . '/nav.php');
+ $udates = "";
+ if($pdate != $udate) { $udates = " | Updated&nbsp;on&nbsp;$udate"; }
+ echo("<h1>isoblog</h1><h2 id='caption'>$title</h2><p style='text-align: center;'><em>Posted&nbsp;on&nbsp;$pdate$udates</em></p>");
+ include("../../../Parsedown.php");
+ $Parsedown = new Parsedown();
+ echo $Parsedown->text(file_get_contents("index.md"));
+ $Parsedown->setSafeMode(true);
+ $return = $_GET["return"];
+ ?>
+ <hr>
+ <h2>Comments</h2>
+ <form action="/blog/comment/submit.php" method="post" autocomplete="off">
+ <?php echo "<input type='text' name='entry' value='".preg_replace("/^.*\//","",getcwd())."' style='display: none;' readonly>"; ?>
+ <table>
+ <tr>
+ <td><input type="text" name="name" placeholder="Name"></td>
+ <td><input type="text" name="botcheck" placeholder="Bot test (type &quot;isopod&quot;)"></td>
+ </tr>
+ <tr>
+ <td colspan="2"><textarea name="message" placeholder="Comment (Now supports Markdown!)"></textarea></td>
+ </tr>
+
+ <tr>
+ <?php
+ switch ($return) {
+ case 'noname':
+ echo "<td><span class='error'>Name required!</span></td>";
+ break;
+ case 'nomessage':
+ echo "<td><span class='error'>Message required!</span></td>";
+ break;
+ case 'botcheckfailed':
+ echo "<td><span class='error'>You failed the bot check!</span></td>";
+ break;
+ case 'success':
+ echo "<td><span class='success'>Successfully posted!</span></td>";
+ break;
+ default:
+ echo "<td></td>";
+ break;
+ }
+ ?>
+ <td style="text-align: right;"><input type="submit" value="Post"></td>
+ </tr>
+ </table>
+ </form>
+ <?php
+
+ $totaloutput = "";
+ $postlist = json_decode(file_get_contents("../../comment/posts.json"));
+ foreach($postlist as $post) {
+ if ($post->entry == preg_replace("/^.*\//","",getcwd())) {
+ $output = "";
+ $date = date("Y-m-d h:iA", $post->date);
+ $name = $post->name;
+ $message = $Parsedown->text(html_entity_decode($post->message));
+
+ $output = $output."<hr><article><table><tr><td style='text-align: left;'>".$name."</td><td style='text-align: right;'>".$date."</td></tr><tr><td colspan='2'>".$message."</td></tr></table></article>";
+ $totaloutput = $output.$totaloutput;
+ }
+ }
+ echo $totaloutput; ?>
+ </body>
+</html>
diff --git a/blog/posts/renting_an_unremarkable_server/index.md b/blog/posts/renting_an_unremarkable_server/index.md
new file mode 100644
index 0000000..d2687dd
--- /dev/null
+++ b/blog/posts/renting_an_unremarkable_server/index.md
@@ -0,0 +1,40 @@
+This was originally going to be a blurb on [/uses](/uses/), then it turned into a new sub-page, then this bit got so long I figured it would be better suited as a blog post. I wasn't expecting to have this much to say on the matter. Here's hoping soon I can muster up a blog post that isn't about a computer.
+
+Up until recently, I ran all my exposed-to-the-web self-hosted services on a modest DigitalOcean VPS. For reasons entirely unrelated to its performance or reliability, that is no longer the case. See, while DigitalOcean is based in the United States, as astute readers surely know, I am not, and with The Way Things Are Going Politically Right Now&trade;, I'm trying to reduce my reliance on American companies where possible, she said, run-on-sentencefully. Fortunately, all of DigitalOcean's European competitors are also a lot cheaper.
+
+In researching alternative VPS options, I landed on OVH because they were the most reputable non-American hosting provider I could find with a datacenter in my country that I could be sure would allow me to use IPv6. Their VPS offerings were decent, certainly attractive to someone used to DigitalOcean prices, but I ended up going with a dedicated server instead due to the, to put it lightly, *vastly* better price-to-performance ratio on offer:
+
+| | Old VPS | New server | Comparably priced OVH VPS |
+| --- | --- | --- | --- |
+| CPU | 2 threads | 4 core/8 thread Intel Xeon-D 1520 | 4 threads |
+| RAM | 4GB | 32GB DDR4-2133 ECC | 4GB |
+| Storage | 80GB NVMe | 480GB mirrored SATA SSDs | 80GB NVMe |
+| Network | 2Gbps | 300Mbps | 1Gbps |
+| Backups | Automated | Bring your own | On-demand |
+| Price (CAD) | $44/mo | $25/mo | $26/mo |
+
+See what I mean? Of course, none of these seem like all that from the perspective of a modern personal computer, but this represents a *quadrupling* of CPU cores and RAM and a *sextupling* of storage space for a near halving of the price compared to my already adequate previous solution. That's like eight times the value! Though, looking at this table, you can already see a couple of the reasons it's priced so competitively, even accounting for the DigitalOcean tax. Let's break this down.
+
+## The Ebay Optiplex gaming PC of rented servers
+
+So I've moved from a VPS to a dedicated server. The fundamental difference between them is that a VPS is a virtual machine that your hosting provider spins up for you, while a dedicated, or bare-metal, server is just a whole computer that you rent sole administrative privileges over.
+
+The benefit you get with a VPS is that, being a virtual machine, they can trivially be cloned in full for a comprehensive backup or assigned more or less computing resources depending on your needs, with little more than the click of a button in the web control panel. The drawback is that managing all that requires specialized, costly, and probably bespoke infrastructure. With a bare-metal server you get none of that. You're essentially paying for SSH access to a machine in their datacenter and for a technician to walk over and hit the power button for you. I've made use of those fancy features in the past with my old VPS, but the aforementioned gulf in computing resources for the money made losing them worth it to me. Besides, with a server as powerful as this I'd be shocked if I ever needed to upgrade anyway.
+
+The option I went with also gets much less bandwidth than a VPS would, 300 megabits compared to a gigabit or more. This is the source of most of my buyer's remorse here, but looking at my usage graphs from DigitalOcean I expect it'll be rare that I hit even this cap, though it will prove restricting if I spin up a Peertube instance and become the world's first Peertube channel with a triple digit number of active viewers.
+
+If you're the sort of person who memorizes server part numbers, you may have already picked up on the third reason this is so cheap: this is an old-ass server. The Xeon-D 1520 is now a 10-year-old chip, from, like, the <span title="Hi!">dawn</span> of DDR4 memory being a thing that had been invented. According to OVH, this machine is technically on its fourth life, having aged out of three tiers of increasingly budget dedicated servers. You could probably score a functionally identical old Dell box for like a hundred bucks on Ebay plus the cost of a RAM upgrade. Honestly, I really like that. It's a refreshing change of pace from giant corporate entities dropping billions on single-purpose ASICs for blockchain and "AI" workloads that will become worthless in a couple years when the bubble bursts.
+
+Financials aside, it should go without saying that this new-to-me server is *way* overkill for the handful of websites and single-user self-hostable network services I'll be running on it. The old VPS had plenty of computing power for that. The main draw for me was the extra storage space &mdash; I might have gone even cheaper, except all the cheaper options were restricted to network speeds that I actually felt uncomfortable limiting myself to.
+
+## Migrating to the thang ding
+
+Of course, then there's the matter of actually migrating everything over. It went about as smoothly as you could reasonably expect. DigitalOcean, turns out, loves their vendor lock-in and won't let you download an image of your VPS directly, so it was a lot of making .tar.gz archives on the old server, downloading them over sftp, and then uploading them to the new server.
+
+I took it as an opportunity to do some seasonally-appropriate spring cleaning, pruning a bunch of extraneous services like my never-used Matrix and Mumble servers and reorganizing what remained in order to make keeping track of it all (and backing it up) as easy as possible for myself. I will admit there are a couple things in Docker containers now that were not previously in Docker containers.
+
+I switched HTTP reverse proxies from Nginx to Caddy, a decision I do not regret, and I ditched Nextcloud, which I was really only using for its extremely mediocre RSS reader anyway. Little did I know replacing it with a different RSS program would be one of the hardest things I'd have to do as part of this process. As of writing, I'm still procrastinating on moving the Wireguard VPN over, but that's basically fine, since my Minecraft server is pretty well dead anyways.
+
+I plan to use that extra storage space I was so drawn to to finally host my own copies of all my art, music and videos included, so I won't be relying entirely on Youtube and Bandcamp to not go down the shitter to make that stuff available. At any rate, it's become clear by now that whatever discoverability they're supposed to afford me has utterly failed to materialize. That's not to say I'll stop uploading to those places before they actually become actively hostile to my presence, but having the redundancy is always nice.
+
+I might also start using it for limited offsite backups, probably with Syncthing. I wouldn't want to put my entire library of lossless CD rips on there, but I've got more than enough room now for stuff like my photo archive and art project files. Whatever I end up doing, it'll be available to peruse <a href="/uses/cumulonimbus/">hereabouts</a> whenever I get that page finished. I'm honestly surprised I didn't make a "services I self-host and what I think of them" page sooner. \ No newline at end of file
diff --git a/blog/posts/renting_an_unremarkable_server/index.php b/blog/posts/renting_an_unremarkable_server/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/renting_an_unremarkable_server/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/toshiba_chromebook/chromebook.jpg b/blog/posts/toshiba_chromebook/chromebook.jpg
new file mode 100644
index 0000000..d6ba4b7
--- /dev/null
+++ b/blog/posts/toshiba_chromebook/chromebook.jpg
Binary files differ
diff --git a/blog/posts/toshiba_chromebook/index.md b/blog/posts/toshiba_chromebook/index.md
new file mode 100644
index 0000000..73d0c46
--- /dev/null
+++ b/blog/posts/toshiba_chromebook/index.md
@@ -0,0 +1,46 @@
+It's always hard to believe that events that happened ten years ago happened *ten years ago*, but knowing that doesn't make it feel any less strange that it is now the tenth birthday of the Chromebook I got from Santa when I was 12. That's what I'm doing for the Holiday Season&trade;, by the way. You're getting a post about my first computer, because it's the tenth anniversary of when I got it. Perhaps I'll also make a post about my second computer next September, on *its* tenth birthday. Foreshadowing? What's that?
+
+The first computer I ever owned was this thing:
+
+<figure class="media">
+ <div>
+ <img src="chromebook.jpg" alt="The Toshiba Chromebook 2, an unassuming 13-inch laptop made of light grey plastic. As one might expect, it is running Chrome OS.">
+ <figcaption>Image courtesy of PCMag, from their <a href="https://www.pcmag.com/reviews/toshiba-cb35-b3340-chromebook-2">review</a> of this machine.</figcaption>
+ </div>
+</figure>
+
+This is the Toshiba Chromebook 2. The high-trim model that I had sports a 13-inch 1080p screen, Skullcandy-branded speakers, a whopping 4GB of RAM, the world's most sopping wet and pathetic dual-core Intel Celeron CPU, and 16GB of EMMC storage. It also comes with 100GB of free Google Drive storage for two full years, which sounds like some nasty ploy to sell you a subscription, but with how long you'll be using the thing for may as well be a second internal SSD.
+
+I was a little bit surprised to learn, upon looking up reviews for this unit, that these speeds and feeds made it one of the nicer Chromebooks available at the time &mdash; reviewers seemed to think that the 1080p screen, Skullcandy logo next to the speakers, and 4 entire gigs of RAM (as opposed to the 2GB of most Chromebooks at the time) were the height of luxury.
+
+Not especially impressive specs by modern standards, or contemporary standards for that matter, but what you've got to keep in mind is that this is a $300 machine, which means the inclusion of a Celeron only constitutes a mere rip-off, and not an outright scam. Although, to be fair, it did work fine for the light web browsing and Youtube watching that constituted this thing's entire intended use case, and depending on how you look at it, the dinky little CPU was a good thing, since it could actually keep cool under those loads inside of Chekov's plastic shell with *absolutely no active cooling*.
+
+As you might know if you graduated high school after 2013 or so, this laptop, like all Chromebooks, ran Chrome OS, which was less of a fully-fledged desktop operating system and more of a copy of Chrome with half a desktop environment bolted on. I've heard that it can run Android apps and Steam games now (?) but this was *not* the case in 2014. You had Chrome, and you had Chrome Apps, which were Web Apps&trade; that you could add to your Chromebook's system menu by installing them from the Chrome Web Store, which you might recognize as the official distribution platform for Chrome extensions and themes if you recently switched to Firefox to keep using your adblocker.
+
+This explicitly intended lack of support for even writing software for the platform, let alone your favourite programs, was the Chromebook's biggest weakness, but it was completely compensated for by the fact that all Chromebooks took about 3 seconds to reach the login screen from a cold boot. In what has since become my typical fashion, it didn't take me long to remedy both of these.
+
+Being 12 years old and a little bit stupid, I held Google and their products in pretty high regard at the time that I got this machine. To me, the Google ecosystem represented an escape from both Apple products, which I (correctly) viewed as underpowered, overpriced, and overly childproofed in their design; and Windows PCs, with which my primary recent experience had been mostly cheap, slow school computers that took fully two minutes to launch a web browser (This is also why I don't share the apparent nostalgia for Windows 7 that many of my fellow computer touchers express). I apparently pushed pretty hard to get a Chromebook instead of an iPad or whatever else I thought my parents were going to buy for me.
+
+Once I had it, it took me maybe a couple months to decide I wanted more functionality out of this thing than the preloaded software was capable of offering. Specifically, I wanted to play Minecraft, which at the time didn't have anything even resembling feature parity between platforms &mdash; if you thought the Java Edition was better than Bedrock Edition now, you should have been there for early Pocket Edition. Shit was *dire*, man. Of course, Minecraft very much did not run on Chrome OS, and this was the inciting circumstance that probably altered the course of my entire life.
+
+You see, there was one way to run Minecraft on a Chromebook, and that was by installing Linux on it. Now, Chrome OS is already based on Linux, but that's not what I mean here. I'm talking full-fat Ubuntu. I'm fuzzy on the details, but if you put your Chromebook into developer mode and ran an installation script called crouton, you could<sup id="n1r"><a href="#n1">1</a></sup> boot into a more-or-less totally normal Linux install with support for real ass actual software and everything. This required performing a complex ritual every boot where you would hold down a keyboard shortcut on the boot screen to enter dev mode, bring up a terminal under Chrome OS, and then run a command I have since forgotten to boot Linux, but minor UX issues like that were no concern of mine. I found a guide online to do this and was, from that day forward, irreversibly corrupted into a Linux user.
+
+And I really got into it, too. I remember setting up a custom shortcut in the XFCE environment crouton set me up with that ran `java -jar ~/minecraft.jar` to boot Minecraft. I remember learning, like, a surprising amount about the inner workings of Linux and getting comfortable with the terminal. I got really into theming for a bit and I distinctly remember using Pinta to create an XFCE theme that resembled the latest Mac OS redesign but with square corners and posting it to the now-defunct<sup id="n2r"><a href="#n2">2</a></sup> xfce-look.org. I reinstalled Linux to try out different desktop environments like half a dozen times. I first learned Python on this computer, and my understanding of things like pip and venvs has not progressed since.
+
+It was a very fun and educational nine months. You read that right, this machine lasted me all of nine months until I tried to boot it up one day and it just made an unsettling *pop* noise and a mysterious odor and refused to ever turn on again.
+
+As astute readers will know already, this computer had *absolutely no cooling whatsoever*. No fans, and an all-plastic chassis to further kneecap the already meager passive cooling it was getting. This probably would have been fine for upwards of a year if I used the thing as intended, but I was pushing that pathetic little 7.5-watt Celeron to its absolute limit by running Minecraft 1.8 at 15 FPS, which proved too hot to handle for the glue holding the bottom panel on, followed by... something critical to the machine's operation. I'm not sure.
+
+And that was that. By some miracle the thing decided to blow up on my birthday, so my parents saw fit to get me an upgraded Windows machine as a birthday present. I mostly stuck with Windows for the next few years, mostly because it could run more games, but I never really stopped preferring Linux, and I would occasionally attempt switching back over the intervening years until I made the jump for good in 2021 when I upgraded the storage in my third laptop, the second of two slightly dodgy HP units and the same one from [this post](../building_a_normal_server/), and wisely decided that I wouldn't be sticking around to have Windows 11 inflicted on me.
+
+The Toshiba Chromebook 2 was e-waste from the moment it rolled off the assembly line. It sucked<sup id="n3r"><a href="#n3">3</a></sup>, and I hate everything about it<sup id="n4r"><a href="#n4">4</a></sup>, but I'll never ever forget what owning it did for me. I was already pretty into computers, but dealing with such utterly useless software forced me to get comfortable getting into the weeds to get what I wanted out of it. This thing taught me to program computers, and it taught me to beat computers into submission to impose my will upon them. Obviously it was the first computer I ever owned, but it was also the first computer I learned to make *mine*, and I don't know quite where I'd be today without that. Honestly, probably still working retail, but a lot more of my data would be going to Microsoft.
+
+---
+
+<p id="n1"><a href="#n1r">1</a>. As a matter of fact, you still can! The <a href="https://github.com/dnschneid/crouton">Github repo</a> is seemingly still being maintained, although there's slightly less reason to actually do it nowadays.</p>
+
+<p id="n2"><a href="#n2r">2</a>. There's still a website at that domain, but it's a Pling site now, so it might as well be dead.</p>
+
+<p id="n3"><a href="#n3r">3</a>. I would be remiss not to mention that the HDMI output was also completely borked. There was a giant green triangle type structure in the bottom left of the display and I'm pretty sure the picture was shifted about 1/3 the width of the screen to one side. Whether that was caused by heat damage or an unrelated defect will forever remain a mystery. The built-in display was completely fine.</p>
+
+<p id="n4"><a href="#n4r">4</a>. I'm not kidding about that glue, by the way. By the time it died, the bottom panel was hanging probably a centimeter below the top side of the shell whenever I picked it up. Talk about build quality.</p> \ No newline at end of file
diff --git a/blog/posts/toshiba_chromebook/index.php b/blog/posts/toshiba_chromebook/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/toshiba_chromebook/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/blog/posts/unity_runtime_fee_and_proprietary_software/bg.svg b/blog/posts/unity_runtime_fee_and_proprietary_software/bg.svg
new file mode 100644
index 0000000..cdc1629
--- /dev/null
+++ b/blog/posts/unity_runtime_fee_and_proprietary_software/bg.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="256"
+ height="263"
+ viewBox="0 0 256 263"
+ version="1.1"
+ preserveAspectRatio="xMidYMid"
+ id="svg1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs1" />
+ <g
+ fill="#222C37"
+ id="g1"
+ style="fill:#ffffff;fill-opacity:1">
+ <path
+ d="m 166.87233,131.23686 45.90879,-79.274513 22.18445,79.274513 -22.18445,79.25638 z m -22.37641,12.87366 45.91626,79.26278 -79.96661,-20.48673 -57.77043,-58.77605 z M 190.40151,39.078026 144.49592,118.35254 H 52.67514 L 110.44557,59.573289 Z M 255.94071,104.25891 227.93262,0.06035193 123.39281,27.985268 107.91819,55.192492 76.516786,54.96748 0,131.24432 76.516786,207.50304 h 0.0032 l 31.387534,-0.23248 15.49702,27.20723 104.52808,27.92065 28.00809,-104.17937 -15.90545,-26.98221 z"
+ id="path1"
+ style="fill:#ffffff;fill-opacity:1" />
+ </g>
+</svg>
diff --git a/blog/posts/unity_runtime_fee_and_proprietary_software/devprotest.png b/blog/posts/unity_runtime_fee_and_proprietary_software/devprotest.png
new file mode 100644
index 0000000..bca3010
--- /dev/null
+++ b/blog/posts/unity_runtime_fee_and_proprietary_software/devprotest.png
Binary files differ
diff --git a/blog/posts/unity_runtime_fee_and_proprietary_software/index.md b/blog/posts/unity_runtime_fee_and_proprietary_software/index.md
new file mode 100644
index 0000000..633b1a5
--- /dev/null
+++ b/blog/posts/unity_runtime_fee_and_proprietary_software/index.md
@@ -0,0 +1,55 @@
+[Well this fucking sucks.](https://archive.ph/gBpXw)
+
+**[UPDATE 2023-09-23]** This policy has changed significantly for the better since this article was written, and I wanted to update this post for completeness, but I'm leaving the original article alone because I think it's important for people to know everything Unity *tried* to get away with, and not just what it ended up doing. I've added my thoughts on the changes to the end of this article.
+
+The company behind Unity, an extremely popular game engine used to make [some games you may have heard of](https://store.steampowered.com/curator/39750107-Games-Made-With-Unity/) (including about a fifth of my Steam library, for reference), has just announced a new fee for developers using their engine.
+
+In essence, as of next year, developers will owe Unity a fee for every time their game made with the engine is installed after certain retroactive revenue and install base thresholds. There's various different tiers of this, but for the free plan you and I would be using it amounts to $0.20 per install after the first 200,000 installs and $200,000 of revenue.
+
+Side note - How these installs are counted is left intentionally vague too, so it's unclear whether it's a severe violation of user privacy or vulnerable to abuse by maliciously performing repeated reinstalls of a game, or perhaps both. Plus, this also means that even pirated copies might count towards the total.
+
+I won't mince words: **this absurd pricing change has the potential to sink a lot of small game development studios**, especially those working on games that are extremely popular or not aggressively monetized.
+
+For example, Among Us has over 500 million downloads on the Google Play Store alone. Under this pricing scheme, that would cost its developer, Innersloth, $100,000,000 on the free plan, or a paltry $5,000,000 if they're using the if-you-have-to-ask-you-can't-afford-it Enterprise plan. I don't have access to Innersloth's financial data, but that's probably at least a year or two of pay for all of their employees at the absolute minimum, more if they're on a cheaper plan. I seriously doubt they can afford this.
+
+That's an extreme example, but I think it gets the point across. If you don't believe me, take it from developers on Twitter (via [u/Sparky2199](https://archive.ph/IQPjW)):
+
+[![Compilation of various twitter posts from indie game studios using Unity complaining about the change.](devprotest.png)](devprotest.png)
+
+## The obligatory free software soapbox moment
+
+As angry as I am about this, I do feel kind of vindicated, because here's the thing: something like this was always going to happen. Not because Unity in particular is a *bad* company (although it is), but because it's a *for-profit* company, and especially because it's one with shareholders to please.
+
+Capitalism demands infinite growth, but there's a finite number of people to sell a game engine to, so at a certain point Unity has no choice but to start trying to squeeze more money out of its existing customer base (or expand the customer base by, say, trying to cater to filmmakers). Though certain internal factors definitely sped up the process of reaching this point, Unity was bound to get desperate enough to try some shit like this eventually.
+
+And that's the danger here. When you become reliant on something in order to do your work, you're inherently gambling on it being still around and usable until you're done. In the case of proprietary software (and cloud services, but that's a different rant), you're betting on the company not changing the software or the terms of the license on you, or going under, or just deciding the software isn't worth it to maintain anymore. In Unity's case, we're seeing what happens when you place a losing bet. Suddenly the company hates you and you've gotta migrate to something else, and if you can't you're SOL. Sure, an open-source project might die off as its developers lose interest or can't work on it anymore, but then somebody might fork it, or you have the right to maintain it yourself, if you can. Only proprietary software can suddenly decide you're not *allowed* to use it anymore.
+
+Videogames in particular are hit especially hard by this - they often take years to make, and are often incredibly complex, to the point where porting a game between engines can be harder than making it to begin with, so choosing an engine is a *huge* commitment that not every studio or developer can afford to go back on. Something like this can easily kill a project, both financially and from simple loss of motivation.
+
+This problem isn't unique to Unity, or to game engines. We've been watching this play out across the industry for as long as there's been an industry, except normally companies boil the frog a lot more slowly and in ways that are a lot more subtle. Google didn't go from world's best search engine to mega-monopolistic adware provider overnight. To extend the metaphor, Unity just tossed a grenade in the pot.
+
+It's my opinion that all proprietary software will die this way in the end. The structure is fundamentally unsustainable. You can't have infinite growth. At some point all the proprietary software and services that are commomplace nowadays with their ad-supported business models and predatory pricing schemes and suspiciously high marketing budgets will wither and die, having made themselves intolerable to even their most loyal customers, and most of the survivors will be open-source projects. Not as sleek or sexy or well-advertised, as they'll have had less incentive to appeal to new users, but fundamentally sustainable, having had *no* incentive to appeal to shareholders.
+
+## An attempt at optimism
+
+In this particular case, I don't think this is gonna stick. Unity's runtime fee is absurd, and I think they know it just as well as all their moderately high-profile customers on Twitter do. Unity has already started to walk back some of the more extreme parts of the initial plan, as you can see on archived versions of the posts: [Blog post (Sep 12)](https://archive.ph/gEckm), [Blog post (Sep 14)](https://archive.ph/gBpXw), [Forum thread (Sep 12)](https://archive.ph/HYTq5), [Forum thread (Sep 14)](https://archive.ph/eByMm). Unity also has some customers that are bigger than them and notoriously litigation-happy, namely Nintendo (with Pokemon BD/SP and Go, plus a couple Mario mobile games) and Disney (also with quite a few mobile and console games). Unity's CEO also sold a bunch of stock in the company in the lead-up to this announcement, which, since the company's stock price dropped *significantly* after the announcement, might actually constitute fraud. You know, from federal crimes! Basically, this initial announcement was probably an attempt to see how much they could get away with, and Unity's probably fucked if they stick to their guns on this.
+
+On the technical side, if you're a budding game developer, Unity isn't your only option. My top recommendation is [Godot](https://godotengine.org/), a free and open source game engine that's recently taken steps to increase its funding in a way that's actually sane and not cartoon villain behavior. It also supports C# by default, since you probably got used to that with Unity. There's also RPG Maker and Unreal Engine, the latter of which I imagine a lot of studios will be switching to soon.
+
+Finally, if you've been eyeing a game that uses the Unity engine, you've got until the end of the year to install it without incurring that fee for the developer assuming this change goes through. So I'd check for that. By my understanding you'll have to run it at least once before then, too.
+
+## Update as of 2023-09-23
+
+Good(?) news! Unity's responded to community feedback and it's actually... better than I expected. You can read the full post [here](https://archive.ph/rLi8u), but I'll summarize the changes:
+
+- No more runtime fee for the free Personal tier
+- Revenue cap for the Personal tier doubled and mandatory splash screen removed
+- The runtime fee now only applies starting with the next LTS release in 2024
+- The runtime fee is now capped at 2.5% of total revenue, and all relevant data is now self-reported instead of a "proprietary data model"
+- Just like, a straight up apology at the beginning of the post
+
+This is all good. These changes remove all of the most devastating knock-on effects of the original policy, and I think this is actually a *better* deal for free users than before.
+
+That said, my original point still stands. Unity is still squeezing more money out of its userbase in a way it hadn't previously, and it could pull some shit like this again at any time. Just because it caved this time, doesn't mean there's anything stopping Unity from making more horrible retroactive policy changes in future. Unity has destroyed a lot of the trust it's built with its community - a lot of developers won't trust Unity not to screw them over in the future, and in my opinion they'd be right not to.
+
+It's my hope that a lot of game developers will take this opportunity to ditch Unity for something better. At the very least, I don't think we'll see many games de-listed like Cult of the Lamb [threatened to do](https://archive.ph/4xyTO), since existing games can just not update their Unity release. A lot of games may still be forced to move engines if they don't want to deal with this, though. For example, support for new consoles, OS versions, etc. probably won't be backported to old Unity versions. Games that continually add new content or aren't finished yet will probably eventually start encountering issues resulting from this.
diff --git a/blog/posts/unity_runtime_fee_and_proprietary_software/index.php b/blog/posts/unity_runtime_fee_and_proprietary_software/index.php
new file mode 100644
index 0000000..f572f79
--- /dev/null
+++ b/blog/posts/unity_runtime_fee_and_proprietary_software/index.php
@@ -0,0 +1 @@
+<?php include("../post.php"); \ No newline at end of file
diff --git a/chromealert.php b/chromealert.php
new file mode 100644
index 0000000..087bbf4
--- /dev/null
+++ b/chromealert.php
@@ -0,0 +1,21 @@
+<?php
+
+if($_GET['donotsee'] === 'yes') {
+ setcookie(
+ "niceopodNoChromiumWarning",
+ "true",
+ time() + 60 * 60 * 24 * 365 * 5,
+ "/",
+ $_SERVER['HTTP_HOST'],
+ false,
+ true
+ );
+ header("Location: " . $_GET['originalpage']);
+} else if($_SERVER["REQUEST_URI"] == "/chromealert.php") {
+ http_response_code(403);
+ die();
+} else if (preg_match('/(chrome|opera|edge|brave)/i', $_SERVER['HTTP_USER_AGENT']) && !preg_match('/(headlesschrome)/i', $_SERVER['HTTP_USER_AGENT']) && $_COOKIE['niceopodNoChromiumWarning'] !== "true") {
+ $ogpg = $_SERVER['REQUEST_URI'];
+ echo "<style type='text/css'>#cacb { margin-right: 0.7rem; padding: 0; border: none; background: none; font-size: 0; display: flex; justify-content: center; align-items: center; } #cacb:hover { cursor: pointer; } #chromealert { width: min(40rem, 90vw); z-index: 100000; display: none; position: fixed; top: 1rem; left: 50%; transform: translateX(-50%); background-color: #ffcccc; box-shadow: 3px 3px 3px black; padding: .7rem; border-radius: .7rem; text-shadow: none; color: black; } #cadc:checked + #chromealert { display: flex; } #cadc { display: none; } #chromealert a { color: #df1955; } </style> <input type='checkbox' name='cadc' id='cadc' checked> <div id='chromealert'> <label for='cadc' id='cacb'><svg xmlns='http://www.w3.org/2000/svg' viewBox='-6 -6 24 24' width='24' fill='currentColor'><path d='M7.314 5.9l3.535-3.536A1 1 0 1 0 9.435.95L5.899 4.485 2.364.95A1 1 0 1 0 .95 2.364l3.535 3.535L.95 9.435a1 1 0 1 0 1.414 1.414l3.535-3.535 3.536 3.535a1 1 0 1 0 1.414-1.414L7.314 5.899z'></path></svg></label> <div>It seems you're using a browser based on Google Chrome. Chrome itself is effectively spyware, but even if you're using <a href='https://en.wikipedia.org/wiki/List_of_web_browsers#Blink-based'>something else</a> Google still controls the engine and there are <a href='https://www.cnet.com/tech/computing/chrome-banishes-jpeg-xl-photo-format-that-could-save-phone-space/'>various</a> <a href='https://arstechnica.com/gadgets/2022/01/google-drops-floc-after-widespread-opposition-pivots-to-topics-api-plan/'>compelling</a> <a href='https://www.theverge.com/2022/6/10/23131029/mozilla-ad-blocking-firefox-google-chrome-privacy-manifest-v3-web-request'>reasons</a> to avoid that. I recommend switching to <a href='https://www.mozilla.org/en-US/firefox/new/'>Firefox</a> or <a href='https://librewolf.net/'>Librewolf</a>.</div> </div>";
+}
+?> \ No newline at end of file
diff --git a/deeptwisty.png b/deeptwisty.png
new file mode 100644
index 0000000..7cb8472
--- /dev/null
+++ b/deeptwisty.png
Binary files differ
diff --git a/etc/bg.jpg b/etc/bg.jpg
new file mode 100644
index 0000000..ba7576f
--- /dev/null
+++ b/etc/bg.jpg
Binary files differ
diff --git a/etc/bg.jxl b/etc/bg.jxl
new file mode 100644
index 0000000..afcdc94
--- /dev/null
+++ b/etc/bg.jxl
Binary files differ
diff --git a/etc/buttons/35mm.gif b/etc/buttons/35mm.gif
new file mode 100644
index 0000000..2c5bb0e
--- /dev/null
+++ b/etc/buttons/35mm.gif
Binary files differ
diff --git a/etc/buttons/ace.png b/etc/buttons/ace.png
new file mode 100644
index 0000000..1d62add
--- /dev/null
+++ b/etc/buttons/ace.png
Binary files differ
diff --git a/etc/buttons/agender.png b/etc/buttons/agender.png
new file mode 100644
index 0000000..2241f13
--- /dev/null
+++ b/etc/buttons/agender.png
Binary files differ
diff --git a/etc/buttons/amd_powered.gif b/etc/buttons/amd_powered.gif
new file mode 100644
index 0000000..c6982a6
--- /dev/null
+++ b/etc/buttons/amd_powered.gif
Binary files differ
diff --git a/etc/buttons/antinft.gif b/etc/buttons/antinft.gif
new file mode 100644
index 0000000..1a4caf0
--- /dev/null
+++ b/etc/buttons/antinft.gif
Binary files differ
diff --git a/etc/buttons/aro.png b/etc/buttons/aro.png
new file mode 100644
index 0000000..e1e50d2
--- /dev/null
+++ b/etc/buttons/aro.png
Binary files differ
diff --git a/etc/buttons/aromantic-80x15.png b/etc/buttons/aromantic-80x15.png
new file mode 100644
index 0000000..8a43594
--- /dev/null
+++ b/etc/buttons/aromantic-80x15.png
Binary files differ
diff --git a/etc/buttons/asexual-80x15.png b/etc/buttons/asexual-80x15.png
new file mode 100644
index 0000000..58b6beb
--- /dev/null
+++ b/etc/buttons/asexual-80x15.png
Binary files differ
diff --git a/etc/buttons/badhtml.png b/etc/buttons/badhtml.png
new file mode 100644
index 0000000..17b36a1
--- /dev/null
+++ b/etc/buttons/badhtml.png
Binary files differ
diff --git a/etc/buttons/bantimetravel.png b/etc/buttons/bantimetravel.png
new file mode 100644
index 0000000..83bcfa1
--- /dev/null
+++ b/etc/buttons/bantimetravel.png
Binary files differ
diff --git a/etc/buttons/bestviewed.gif b/etc/buttons/bestviewed.gif
new file mode 100644
index 0000000..0b43d5a
--- /dev/null
+++ b/etc/buttons/bestviewed.gif
Binary files differ
diff --git a/etc/buttons/canadian.gif b/etc/buttons/canadian.gif
new file mode 100644
index 0000000..be1d040
--- /dev/null
+++ b/etc/buttons/canadian.gif
Binary files differ
diff --git a/etc/buttons/chrome.gif b/etc/buttons/chrome.gif
new file mode 100644
index 0000000..791016f
--- /dev/null
+++ b/etc/buttons/chrome.gif
Binary files differ
diff --git a/etc/buttons/css.png b/etc/buttons/css.png
new file mode 100644
index 0000000..7d8235b
--- /dev/null
+++ b/etc/buttons/css.png
Binary files differ
diff --git a/etc/buttons/deeptwisty_button.png b/etc/buttons/deeptwisty_button.png
new file mode 100644
index 0000000..cc935d0
--- /dev/null
+++ b/etc/buttons/deeptwisty_button.png
Binary files differ
diff --git a/etc/buttons/dontclick.gif b/etc/buttons/dontclick.gif
new file mode 100644
index 0000000..188b46c
--- /dev/null
+++ b/etc/buttons/dontclick.gif
Binary files differ
diff --git a/etc/buttons/dontyouhate.gif b/etc/buttons/dontyouhate.gif
new file mode 100644
index 0000000..ff8902d
--- /dev/null
+++ b/etc/buttons/dontyouhate.gif
Binary files differ
diff --git a/etc/buttons/drpepper.gif b/etc/buttons/drpepper.gif
new file mode 100644
index 0000000..dff6eaa
--- /dev/null
+++ b/etc/buttons/drpepper.gif
Binary files differ
diff --git a/etc/buttons/epicblazed.png b/etc/buttons/epicblazed.png
new file mode 100644
index 0000000..df30bc0
--- /dev/null
+++ b/etc/buttons/epicblazed.png
Binary files differ
diff --git a/etc/buttons/floof_explode_88x31.gif b/etc/buttons/floof_explode_88x31.gif
new file mode 100644
index 0000000..46c2ec0
--- /dev/null
+++ b/etc/buttons/floof_explode_88x31.gif
Binary files differ
diff --git a/etc/buttons/getvlcnow.png b/etc/buttons/getvlcnow.png
new file mode 100644
index 0000000..8922252
--- /dev/null
+++ b/etc/buttons/getvlcnow.png
Binary files differ
diff --git a/etc/buttons/google_stand.gif b/etc/buttons/google_stand.gif
new file mode 100644
index 0000000..08ffd8b
--- /dev/null
+++ b/etc/buttons/google_stand.gif
Binary files differ
diff --git a/etc/buttons/handcode.png b/etc/buttons/handcode.png
new file mode 100644
index 0000000..c5bbdd1
--- /dev/null
+++ b/etc/buttons/handcode.png
Binary files differ
diff --git a/etc/buttons/i_hate_microsoft.png b/etc/buttons/i_hate_microsoft.png
new file mode 100644
index 0000000..c20422b
--- /dev/null
+++ b/etc/buttons/i_hate_microsoft.png
Binary files differ
diff --git a/etc/buttons/isopodhours.png b/etc/buttons/isopodhours.png
new file mode 100644
index 0000000..60fdeff
--- /dev/null
+++ b/etc/buttons/isopodhours.png
Binary files differ
diff --git a/etc/buttons/krisbtn.png b/etc/buttons/krisbtn.png
new file mode 100644
index 0000000..176d3c4
--- /dev/null
+++ b/etc/buttons/krisbtn.png
Binary files differ
diff --git a/etc/buttons/linux_powered.gif b/etc/buttons/linux_powered.gif
new file mode 100644
index 0000000..2dbe456
--- /dev/null
+++ b/etc/buttons/linux_powered.gif
Binary files differ
diff --git a/etc/buttons/neocities_stamp.gif b/etc/buttons/neocities_stamp.gif
new file mode 100644
index 0000000..c8e8ea4
--- /dev/null
+++ b/etc/buttons/neocities_stamp.gif
Binary files differ
diff --git a/etc/buttons/niceopod_button.png b/etc/buttons/niceopod_button.png
new file mode 100644
index 0000000..0398b0e
--- /dev/null
+++ b/etc/buttons/niceopod_button.png
Binary files differ
diff --git a/etc/buttons/niceopod_button_2.png b/etc/buttons/niceopod_button_2.png
new file mode 100644
index 0000000..84112e8
--- /dev/null
+++ b/etc/buttons/niceopod_button_2.png
Binary files differ
diff --git a/etc/buttons/nonbinary-80x15.png b/etc/buttons/nonbinary-80x15.png
new file mode 100644
index 0000000..5e06396
--- /dev/null
+++ b/etc/buttons/nonbinary-80x15.png
Binary files differ
diff --git a/etc/buttons/nonbinary.png b/etc/buttons/nonbinary.png
new file mode 100644
index 0000000..19bc440
--- /dev/null
+++ b/etc/buttons/nonbinary.png
Binary files differ
diff --git a/etc/buttons/notoweb3.gif b/etc/buttons/notoweb3.gif
new file mode 100644
index 0000000..4f5a2f1
--- /dev/null
+++ b/etc/buttons/notoweb3.gif
Binary files differ
diff --git a/etc/buttons/nowebp.gif b/etc/buttons/nowebp.gif
new file mode 100644
index 0000000..e63f1f2
--- /dev/null
+++ b/etc/buttons/nowebp.gif
Binary files differ
diff --git a/etc/buttons/piracy.gif b/etc/buttons/piracy.gif
new file mode 100644
index 0000000..37b73b8
--- /dev/null
+++ b/etc/buttons/piracy.gif
Binary files differ
diff --git a/etc/buttons/queercoded.png b/etc/buttons/queercoded.png
new file mode 100644
index 0000000..d8b53d0
--- /dev/null
+++ b/etc/buttons/queercoded.png
Binary files differ
diff --git a/etc/buttons/righttorepair.png b/etc/buttons/righttorepair.png
new file mode 100644
index 0000000..865ba1f
--- /dev/null
+++ b/etc/buttons/righttorepair.png
Binary files differ
diff --git a/etc/buttons/shrimp.png b/etc/buttons/shrimp.png
new file mode 100644
index 0000000..5132eb8
--- /dev/null
+++ b/etc/buttons/shrimp.png
Binary files differ
diff --git a/etc/buttons/smokepowered.gif b/etc/buttons/smokepowered.gif
new file mode 100644
index 0000000..e1d77de
--- /dev/null
+++ b/etc/buttons/smokepowered.gif
Binary files differ
diff --git a/etc/buttons/svg.svg b/etc/buttons/svg.svg
new file mode 100644
index 0000000..557e620
--- /dev/null
+++ b/etc/buttons/svg.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg version="1.1" height="31" width="88" id="svg63" sodipodi:docname="svg-viatrix-anim.svg" inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" xml:space="preserve" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview id="namedview65" pagecolor="#505050" bordercolor="#ffffff" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="1" inkscape:deskcolor="#505050" showgrid="false" inkscape:zoom="16.000001" inkscape:cx="52.531248" inkscape:cy="19.374999" inkscape:window-width="2498" inkscape:window-height="1421" inkscape:window-x="2617" inkscape:window-y="-5" inkscape:window-maximized="1" inkscape:current-layer="svg63"/>
+ <defs id="defs14">
+ <linearGradient inkscape:collect="always" id="sheen">
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="0" id="stop2461"/>
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0.44714037" id="stop2569"/>
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0.54549396" id="stop2571"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop2463"/>
+ </linearGradient>
+ <linearGradient id="w">
+ <stop stop-color="#fff" offset="0" id="stop2"/>
+ <stop stop-color="#fff" stop-opacity="0" offset="1" id="stop4"/>
+ </linearGradient>
+ <linearGradient id="b">
+ <stop stop-color="#000" stop-opacity="0" offset="0" id="stop7"/>
+ <stop stop-color="#000" offset="1" id="stop9"/>
+ </linearGradient>
+ <linearGradient id="wv" xlink:href="#w" y2="1" x2="0"/>
+ <linearGradient id="bv" xlink:href="#b" y2="1" x2="0"/>
+ <linearGradient inkscape:collect="always" xlink:href="#sheen" id="linearGradient2467" x1="80.704506" y1="19.855299" x2="82.295494" y2="12.948893" gradientUnits="userSpaceOnUse" gradientTransform="translate(0,-0.40209649)"/>
+ </defs>
+ <rect style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke-dashoffset:1.5;stop-color:#000000" id="rect1828" width="13" height="31" x="75" y="0" inkscape:label="red"/>
+ <rect style="fill:url(#linearGradient2467);fill-opacity:1;fill-rule:evenodd;stroke-width:1;stroke-dashoffset:1.5;stop-color:#000000" id="rect1880" width="13" height="10" x="75" y="11" inkscape:label="sheen" ry="0">
+ <animateTransform attributeName="transform" attributeType="XML" repeatCount="indefinite" type="translate" values="0 35; 0 35; 0 -35" dur="6s" keyTimes="0; 0.85; 1"/>
+ </rect>
+ <rect style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke-dashoffset:1.5;stop-color:#000000" id="rect799" width="75" height="31" x="0" y="0" inkscape:label="bg"/>
+ <path d="m 86,0 h 3 v 31 h -3" fill="url(#b)" id="path20" style="display:inline" inkscape:label="right"/>
+ <path d="m 0,29 v 3 h 88 v -3" fill="url(#bv)" id="path22" style="display:inline" inkscape:label="btm"/>
+ <path d="M 0,0 H 3 V 31 H 0" fill="url(#w)" id="path24" style="display:inline" inkscape:label="left"/>
+ <path d="M 0,0 V 3 H 88 V 0" fill="url(#wv)" id="path26" style="display:inline" inkscape:label="top"/>
+ <g xmlns="http://www.w3.org/2000/svg" id="g965" inkscape:label="logo" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" style="display:inline" transform="matrix(0.08007307,0,0,0.08007307,4.0614915,3.4858457)">
+ <path id="base-9" fill="#000000" d="m 8.5,150 h 283 v 100 c 0,23.5 -18,41.5 -41.5,41.5 H 50 C 26.5,291.5 8.5,273.5 8.5,250 Z"/>
+ <g id="star-container">
+ <g stroke-width="38.0086" stroke="#000000" id="g939">
+ <g id="g805">
+ <path id="path797" fill="#ffb13b" d="m 65.857541,134.11306 a 22.4171,22.4171 0 1 0 0,31.7026 H 234.15494 a 22.4171,22.4171 0 1 0 0,-31.7026 z"/>
+ <path id="path799" fill="#ffb13b" d="M 101.71269,79.253674 A 22.4171,22.4171 0 1 0 79.295563,101.67079 L 198.29979,220.67504 a 22.4171,22.4171 0 1 0 22.41713,-22.41713 z"/>
+ <path id="path801" fill="#ffb13b" d="m 165.85754,65.815652 a 22.4171,22.4171 0 1 0 -31.7026,0 V 234.11306 a 22.4171,22.4171 0 1 0 31.7026,0 z"/>
+ <path id="path803" fill="#ffb13b" d="M 220.71692,101.67079 A 22.4171,22.4171 0 1 0 198.29979,79.253674 L 79.295563,198.25791 a 22.4171,22.4171 0 1 0 22.417127,22.41713 z"/>
+ </g>
+
+ </g>
+ <g id="g815" style="display:inline;">
+ <path fill="#ffb13b" d="m 65.8513,134.1487 a 22.4171,22.4171 0 1 0 0,31.7026 h 168.2974 a 22.4171,22.4171 0 1 0 0,-31.7026 z" id="path807"/>
+ <path fill="#ffb13b" d="M 101.70645,79.289322 A 22.4171,22.4171 0 1 0 79.289322,101.70645 L 198.29355,220.71068 a 22.4171,22.4171 0 1 0 22.41713,-22.41713 z" id="path809"/>
+ <path fill="#ffb13b" d="m 165.8513,65.8513 a 22.4171,22.4171 0 1 0 -31.7026,0 v 168.2974 a 22.4171,22.4171 0 1 0 31.7026,0 z" id="path811"/>
+ <path fill="#ffb13b" d="M 220.71068,101.70645 A 22.4171,22.4171 0 1 0 198.29355,79.289322 L 79.289322,198.29355 a 22.4171,22.4171 0 1 0 22.417128,22.41713 z" id="path813"/>
+
+ </g><animateTransform xmlns="http://www.w3.org/2000/svg" attributeType="XML" repeatCount="indefinite" attributeName="transform" type="rotate" calcMode="spline" keyTimes="0; 0.8; 1" dur="6s" keySplines="0 0 1 1; 0.6 0 0.5 1" values="0 150 150; 0 150 150; 405 150 150"/>
+ </g>
+ <path id="use943" fill="#000000" d="m 8.5,150 h 283 v 100 c 0,23.5 -18,41.5 -41.5,41.5 H 50 C 26.5,291.5 8.5,273.5 8.5,250 Z" opacity="0.85"/>
+ <g id="use945" fill="#ffffff" transform="matrix(2,0,0,2,40,158)" style="display:inline">
+ <path d="M 5.482,31.319 C 2.163,28.001 0.109,23.419 0.109,18.358 0.109,8.232 8.322,0.024 18.443,0.024 c 10.126,0 18.339,8.208 18.339,18.334 h -10.74 c 0,-4.194 -3.404,-7.593 -7.599,-7.593 -4.194,0 -7.593,3.399 -7.593,7.593 0,2.095 0.851,3.993 2.22,5.363 h 0.005 c 1.375,1.38 2.52,1.779 5.368,2.231 v 0 c 5.066,0.527 9.648,2.054 12.966,5.372 v 0 c 3.319,3.319 5.373,7.901 5.373,12.962 0,10.126 -8.213,18.339 -18.339,18.339 C 8.322,62.625 0.109,54.412 0.109,44.286 H 10.85 c 0,4.194 3.399,7.598 7.593,7.598 4.195,0 7.599,-3.404 7.599,-7.598 0,-2.095 -0.851,-3.988 -2.221,-5.363 H 23.816 C 22.441,37.548 20.468,37.074 18.443,36.697 V 36.692 C 13.533,35.939 8.8,34.638 5.482,31.319 Z" id="path31"/>
+ <path d="M 73.452,0.024 60.482,62.625 H 49.742 L 36.782,0.024 h 10.74 l 7.6,36.663 7.59,-36.663 z" id="path33"/>
+ <path d="m 91.792,25.952 h 18.334 v 18.334 h 0.005 c 0,10.127 -8.213,18.34 -18.339,18.34 -10.127,0 -18.334,-8.213 -18.334,-18.34 v 0 -25.927 h -0.005 c 0,-10.126 8.212,-18.334 18.339,-18.334 10.121,0 18.334,8.208 18.334,18.334 H 99.385 c 0,-4.19 -3.404,-7.594 -7.593,-7.594 -4.195,0 -7.594,3.404 -7.594,7.594 v 25.927 0 c 0,4.195 3.399,7.594 7.594,7.594 4.189,0 7.588,-3.399 7.593,-7.589 v -0.005 -7.588 h -7.593 z" id="path35"/>
+ </g>
+
+ </g>
+ <g id="g1248" transform="translate(0.46966994,-0.9956713)" inkscape:label="text" style="font-family: &quot;Times New Roman&quot;, serif;">
+ <text xml:space="preserve" style="font-size:7.33333px;line-height:1.1;/*! font-family:&quot;Times New Roman&quot;, serif; */-inkscape-font-specification:'Century Gothic';letter-spacing:0px;word-spacing:0px" x="36.389492" y="10.912677" id="text1833" inkscape:label="cer">
+ <tspan sodipodi:role="line" id="tspan1827" x="36.389492" y="10.912677" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold'">CALABLE</tspan>
+ <tspan sodipodi:role="line" x="36.389492" y="19.159277" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold'" id="tspan1829"> ECTOR</tspan>
+ <tspan sodipodi:role="line" x="36.389492" y="27.405876" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold'" id="tspan1831">  RAPHICS</tspan>
+ </text>
+ <text xml:space="preserve" style="font-size:9.33333px;line-height:0.85;/*! font-family:&quot;Times New Roman&quot;, serif; */-inkscape-font-specification:'Century Gothic';letter-spacing:0px;word-spacing:0px" x="29.774187" y="10.916633" id="text1256" inkscape:label="svg">
+ <tspan sodipodi:role="line" x="29.774187" y="10.916633" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold';fill:#0402fc;fill-opacity:1" id="tspan1254"> S
+ </tspan>
+ <tspan sodipodi:role="line" x="29.774187" y="19.078974" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold';fill:#0402fc;fill-opacity:1" id="tspan1263">V</tspan>
+ <tspan sodipodi:role="line" x="29.774187" y="27.241314" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.33333px;/*! font-family:'Times New Roman'; */-inkscape-font-specification:'Times New Roman, Bold';fill:#0402fc;fill-opacity:1" id="tspan1265">G</tspan>
+ </text>
+ </g>
+ <text xmlns="http://www.w3.org/2000/svg" xml:space="preserve" x="-26.873222" y="84.234131" id="text1825" transform="rotate(-90)" inkscape:label="now" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.6667px;font-family:'Times New Roman', serif;-inkscape-font-specification:'Times New Roman, Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0.5px;word-spacing:0px;">
+ <tspan xmlns="http://www.w3.org/2000/svg" sodipodi:role="line" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" id="tspan1823" x="-26.873222" y="84.234131" style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.6667px;-inkscape-font-specification:'Times New Roman, Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1">now!</tspan>
+ </text>
+</svg> \ No newline at end of file
diff --git a/etc/buttons/tested_on_firefox.gif b/etc/buttons/tested_on_firefox.gif
new file mode 100644
index 0000000..92dbae0
--- /dev/null
+++ b/etc/buttons/tested_on_firefox.gif
Binary files differ
diff --git a/etc/buttons/the_void.gif b/etc/buttons/the_void.gif
new file mode 100644
index 0000000..1099de4
--- /dev/null
+++ b/etc/buttons/the_void.gif
Binary files differ
diff --git a/etc/buttons/trans.png b/etc/buttons/trans.png
new file mode 100644
index 0000000..9e3b390
--- /dev/null
+++ b/etc/buttons/trans.png
Binary files differ
diff --git a/etc/buttons/usatoday.gif b/etc/buttons/usatoday.gif
new file mode 100644
index 0000000..9e6fa57
--- /dev/null
+++ b/etc/buttons/usatoday.gif
Binary files differ
diff --git a/etc/buttons/web-pi.png b/etc/buttons/web-pi.png
new file mode 100644
index 0000000..9888021
--- /dev/null
+++ b/etc/buttons/web-pi.png
Binary files differ
diff --git a/etc/buttons/win11no.gif b/etc/buttons/win11no.gif
new file mode 100644
index 0000000..ce23096
--- /dev/null
+++ b/etc/buttons/win11no.gif
Binary files differ
diff --git a/etc/images/apiopage.png b/etc/images/apiopage.png
new file mode 100644
index 0000000..d8cb65b
--- /dev/null
+++ b/etc/images/apiopage.png
Binary files differ
diff --git a/etc/index.php b/etc/index.php
new file mode 100644
index 0000000..5d368c9
--- /dev/null
+++ b/etc/index.php
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>More</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ #mothvertisement {
+ margin-left: auto;
+ display: block;
+ margin-right: auto;
+ max-width: 728px;
+ width: 100%;
+ height: 90px;
+ }
+
+ @media (max-width: 750px) {
+ #mothvertisement {
+ max-width: 300px;
+ width: 100%;
+ height: 250px;
+ }
+ }
+</style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+</head>
+
+<body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(); ?>
+ <h1>more</h1>
+ <h2 id="caption">more</h2>
+ <nav><a href="quotes/">quotes</a><a href="https://rss-bridge.isopod.cool/?action=display&bridge=GiteaBridge&context=Commits&branch=main&host=https%3A%2F%2Fgit.isopod.cool&user=will&project=isopod.cool&format=Atom">changelog (atom)</a><!--a href="changelog.php">changelog (legacy)</a--></nav>
+ <iframe src="https://john.citrons.xyz/embed?ref=https://isopod.cool/"
+ style="margin-left:auto;display:block;margin-right:auto;max-width:732px;width:100%;max-height:94px;height:fit-content;border:none;"></iframe>
+ <iframe src="https://mothvertising.moth.monster/embed" id="mothvertisement"></iframe>
+ <!--h2>Time warp</h2>
+ <p><a href="../old/1/">v1</a> - Old, slow, basically just a carrd page on steroids. Made heavy use of <code>float</code> initially. Ugh.</p>
+ <p><a href="../old/2/">v2</a> - Slick as hell but entirely Javascript-dependent. This is where my webpage became a website.</p-->
+ <h2>Buttons</h2>
+ <div class="buttons">
+ <a target="_blank" href="https://easyussr.neocities.org/torrenting.html"><img src="buttons/piracy.gif" alt="Piracy Now!"></a>
+ <a target="_blank" href="https://frame.work"><img src="buttons/bestviewed.gif" alt="Best viewed with a computer"></a>
+ <a target="_blank" href="https://www.videolan.org/"><img src="buttons/getvlcnow.png" alt="get VLC now!"></a>
+ <a target="_blank" href="https://www.youtube.com/watch?v=nleepK7P978"><img src="buttons/35mm.gif" alt="Best heard through a 3.5mm jack"></a>
+ <img src="buttons/tested_on_firefox.gif" alt="Tested on Firefox">
+ <img src="buttons/nowebp.gif" alt="No WebP! Just use PNG">
+ <img src="buttons/svg.svg" alt="Scalable Vector Graphics Now!" style="width:88px; height:31px;" />
+ <a target="_blank" href="http://web3.14159.annwfn.net/"><img src="buttons/web-pi.png" alt="Web Pi Certified"></a>
+ <a target="_blank" href="https://neocities.org"><img src="buttons/neocities_stamp.gif" alt="Neocities: The web is yours"></a>
+ <a target="_blank" href="http://www.ermel.org/handcoded/"><img src="buttons/handcode.png" alt="100% hand coded HTML"></a>
+ <a target="_blank" href="https://12ft.io/"><img src="buttons/dontyouhate.gif" alt="Don't you hate it when you're reading a page and then some-- This content is for subscribers only! Paywalls Gatekeep Knowledge."></a>
+ <img src="buttons/righttorepair.png" alt="I support right to repair">
+ <img src="buttons/google_stand.gif" alt="Stand up to Google! Fight for open web standards! Fight for online privacy! Fight against monopolistic practices!">
+ <a target="_blank" href="https://www.mozilla.org/en-US/firefox/new/"><img src="buttons/chrome.gif" alt="Google Chrome is evil!"></a>
+ <img src="buttons/i_hate_microsoft.png" alt="I hate Microsoft">
+ <img src="buttons/win11no.gif" alt="Windows 11 No!">
+ <img src="buttons/antinft.gif" alt="This is an Anti-NFT site">
+ <a target="_blank" href="https://yesterweb.org/no-to-web3/"><img src="buttons/notoweb3.gif" alt="Keep the web free, say no to web3"></a>
+ <img src="buttons/amd_powered.gif" alt="Powered by AMD">
+ <img src="buttons/linux_powered.gif" alt="Linux powered">
+ <img src="buttons/drpepper.gif" alt="Powered by Dr Pepper">
+ <img src="buttons/the_void.gif" alt="Powered by the void">
+ <img src="buttons/krisbtn.png" alt="Kris where tf are we">
+ <a target="_blank" href="https://neofoxfloofexplo.de/"><img src="buttons/floof_explode_88x31.gif" alt=":neofox_floof_explode:"></a>
+ <img src="buttons/badhtml.png" alt="W3C Bad HTML Markup">
+ <img src="buttons/bantimetravel.png" alt="Ban Time Travel &quot;Now&quot;">
+ <img src="buttons/css.png" alt="CSS is awesome">
+ <a target="_blank" href="https://we-are-jammin.xyz/"><img src="https://damcraft.de/88x31/jammin.webp" alt="We're jammin!"></a>
+ <a target="_blank" href="https://crouton.net/"><img src="buttons/usatoday.gif" alt="USA Today Hot Site"></a>
+ <a target="_blank" href="https://seaslug.neocities.org/"><img src="buttons/shrimp.png" alt="Shrimp Now!"></a>
+ <img src="buttons/canadian.gif" title="Regrettably..." alt="Canadian on the web">
+ <img src="buttons/queercoded.png" alt="You're telling me a queer coded this">
+ <img src="buttons/aro.png" alt="Aromantic pride flag">
+ <!--img src="buttons/ace.png"-->
+ <a href="https://rainy.gay/pride/pridebuttons.html"><img src="buttons/trans.png" alt="Trans pride flag"></a>
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=digital" style="width: 84px; height: 27px;"></iframe>
+ <br><a target="_blank" href="https://citrons.xyz/a/memetic-apioform-page.html"
+ style="display: inline-block; margin-top: .7rem;"><img src="images/apiopage.png" alt="memetic apiopage - click to view"></a>
+ </div>
+ <h3>My buttons</h3>
+ <div class="buttons">
+ <img src="buttons/isopodhours.png" alt="isopod hours">
+ <!--img src="buttons/niceopod_button_2.png" alt="niceopod">
+ <img src="buttons/niceopod_button.png" alt="niceopod"-->
+ <a target="_blank" href="https://deeptwisty.com/"><img src="buttons/deeptwisty_button.png" alt="deep twisty"></a>
+ </div>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/etc/quotes/bg.jpg b/etc/quotes/bg.jpg
new file mode 100644
index 0000000..e13a975
--- /dev/null
+++ b/etc/quotes/bg.jpg
Binary files differ
diff --git a/etc/quotes/bg.jxl b/etc/quotes/bg.jxl
new file mode 100644
index 0000000..30b75bf
--- /dev/null
+++ b/etc/quotes/bg.jxl
Binary files differ
diff --git a/etc/quotes/images/c_pfp.png b/etc/quotes/images/c_pfp.png
new file mode 100644
index 0000000..a54ad21
--- /dev/null
+++ b/etc/quotes/images/c_pfp.png
Binary files differ
diff --git a/etc/quotes/images/g_pfp.png b/etc/quotes/images/g_pfp.png
new file mode 100644
index 0000000..1d1ca3b
--- /dev/null
+++ b/etc/quotes/images/g_pfp.png
Binary files differ
diff --git a/etc/quotes/images/h_pfp.png b/etc/quotes/images/h_pfp.png
new file mode 100644
index 0000000..73c56c5
--- /dev/null
+++ b/etc/quotes/images/h_pfp.png
Binary files differ
diff --git a/etc/quotes/images/j_pfp.png b/etc/quotes/images/j_pfp.png
new file mode 100644
index 0000000..5fb6b36
--- /dev/null
+++ b/etc/quotes/images/j_pfp.png
Binary files differ
diff --git a/etc/quotes/images/m_pfp.png b/etc/quotes/images/m_pfp.png
new file mode 100644
index 0000000..769319f
--- /dev/null
+++ b/etc/quotes/images/m_pfp.png
Binary files differ
diff --git a/etc/quotes/images/p_pfp.png b/etc/quotes/images/p_pfp.png
new file mode 100644
index 0000000..b46d8db
--- /dev/null
+++ b/etc/quotes/images/p_pfp.png
Binary files differ
diff --git a/etc/quotes/images/s_pfp.png b/etc/quotes/images/s_pfp.png
new file mode 100644
index 0000000..c35c967
--- /dev/null
+++ b/etc/quotes/images/s_pfp.png
Binary files differ
diff --git a/etc/quotes/images/t_pfp.png b/etc/quotes/images/t_pfp.png
new file mode 100644
index 0000000..c975deb
--- /dev/null
+++ b/etc/quotes/images/t_pfp.png
Binary files differ
diff --git a/etc/quotes/images/v_pfp.png b/etc/quotes/images/v_pfp.png
new file mode 100644
index 0000000..bf460d6
--- /dev/null
+++ b/etc/quotes/images/v_pfp.png
Binary files differ
diff --git a/etc/quotes/index.php b/etc/quotes/index.php
new file mode 100644
index 0000000..7245c34
--- /dev/null
+++ b/etc/quotes/index.php
@@ -0,0 +1,409 @@
+<?php ini_set('display_errors', '1');
+ini_set('display_startup_errors', '1');
+error_reporting(E_ALL);
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>#quotes</title>
+ <link href="../../style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ :root {
+ --bgcolor: #313338;
+ --fontcolor: #d7d5d9;
+ --stdfont: sans-serif;
+ }
+ a {
+ color: #1c9cee;
+ text-decoration: none;
+ }
+ a:hover {
+ color: #1c9cee;
+ text-decoration: underline;
+ }
+ .pfp {
+ border-radius: 50%;
+ height: 3rem;
+ box-shadow: none;
+ }
+ .message {
+ display: flex;
+ margin: 1rem;
+ text-shadow: none;
+ }
+ .content {
+ margin-left: 1rem;
+ }
+ hr {
+ margin: auto;
+ border-top: 1px solid #42464d;
+ }
+ h4 {
+ padding-left: initial;
+ border-left: none;
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(); ?>
+ <h1>#quotes</h1>
+ <h2 id="caption">highlights from the #quotes channel in the discord chat</h2>
+ <?php
+ class User {
+ public string $pfp;
+ public string $name;
+ public string $color;
+ public function __construct(string $p, string $n, string $c) {
+ $this->pfp = $p;
+ $this->name = $n;
+ $this->color = $c;
+ }
+ }
+ $me = new User("h_pfp", "President Glup Shitto ඞ", "00ffb7");
+ $vivi = new User("v_pfp", "vivi_", "ff009e");
+ $sad = new User("s_pfp", "first Mithrun of the universe ඞ", "f1c40f");
+ $mage = new User("m_pfp", "beatboxing puppy fan", "faaaaa");
+ $celian = new User("c_pfp", "ᘛ⁐̤ᕐᐷ𝕤𝕝𝕦𝕥ಡඞ𐐘𐑀", "73fbff");
+ $thom = new User("t_pfp", "Tomato ඞ", "567c2d");
+ $goon = new User("g_pfp", "horny (short for hornworm) ඞ", "2c9c91");
+ $portals = new User("p_pfp", "portalsandart ඞ", "5a397d");
+ $joy = new User("j_pfp", "JoyTheBoi ඞ", "a2ff00");
+
+ $quotes = array(
+ array($celian, "genshin player slash slur", true),
+ array($me, "I'm dejected and bindlepilled", true),
+ array($celian, "you didn't know? every boat comes with free sex", true),
+ array($me, "you hate my gay little slurry", true),
+ array($me, "I've gotta up my slop game", true),
+ array($me, "your horny ass salad<br>you've been eating horny salad", true),
+ array($vivi, "i dont wanna be a <em>hamster</em> i wanna be a MILF", true),
+ array($mage, "kirby does not have boobs", true),
+ array($joy, "Babygirl, you are so bad at eating", true),
+ array($mage, "I made a facebook account to be transgender", true),
+ array($me, "having a facebook account makes you less transgender"),
+ array($celian, "she's trying to kill me", true),
+ array($mage, "oh HELL yeah"),
+ array($vivi, "instead of destroying everything how about you DESTROY this AAAAAASSSSSSSSSSSSSSSSSSSSS", true),
+ array($joy, "Pet names for your partner<ul><li>Sugar</li><li>Sweetheart</li><li>Beautiful princess with a disorder</li><li>Gianni Matragano</li><li>My love</li></ul>", true),
+ array($me, "L + ratio + no chitin", true),
+ array($me, "You can't be lumping like that white baby", true),
+ array($me, "You hate his perfectly symmetrical swag", true),
+ array($mage, "explodes and dies and gets it all over you", true),
+ array($vivi, "dont compare yourself to jesus just because you thought of making a number a tumblr sexyman", true),
+ array($vivi, "that would be skibidiphobic", true),
+ array($mage, "Why did he turn into a card this is some objectum tf shit", true),
+ array($vivi, "It's almost like he's transgender"),
+ array($celian, "I hate weezer and their child<br>fortunately I have killed weezer", true),
+ array($me, "furries can be trusted to decide who should live and who should die", true),
+ array($celian, "I'm a slut for polls", true),
+ array($celian, "i dont like homosexuality", true),
+ array($vivi, "internalized frog-phobia", true),
+ array($mage, "I think it's fucked up you can't just kill people", true),
+ array($mage, "babygirl you piss so bad what the fuck", true),
+ array($joy, "There's something about digitally altered screams of anguish that really stick in my mind", true),
+ array($mage, "I would change it to daddy's little slut or something. To inflict maximum damage. But rat slut amongus family is good...", true),
+ array($celian, "I think you just hate my water-soluble swag", true),
+ array($vivi, "put your words in my mouth and sentence all over me like a paragraph", true),
+ array($vivi, "i miss going ssssssssss in your whore tree banthrom", true),
+ array($celian, "YOU"),
+ array($vivi, "going sssssss and pppppppppp was the highlight of it for me"),
+ array($celian, "😭"),
+ array($celian, "picks yuo up<br>picks you up like you are a baby seal", true),
+ array($mage, "Yoooooooo<br>Makes noises<br>Euuuh ueh uh huah"),
+ array($vivi, "is the devil from the bible a pillow princess?", true),
+ array($me, "you would disparage the humble onion?", true),
+ array($vivi, "fruited the fuck out", true),
+ array($mage, "Babygirl you are so servers in United States", true),
+ array($mage, "Big BAWS. Naked Snake. Big BAWS. Naked Snake. Metal Gear Solid 3. 3. 3. Metal Gear Solid 3. Soviet Union. Jungle! Jungle!", true),
+ array($celian, "wait arent snake always naked"),
+ array($mage, "I have feelings for you"),
+ array($vivi, "back when i was a fan of edgy minion memes", true),
+ array($me, "I think we should fully replace Discord with Second Life", true),
+ array($mage, "just ignore the drowning horses in the hot tub", true),
+ array($mage, "BALLS?", true),
+ array($celian, "ye<br>if you're too tall u gotta have balls<br>to show off how tall you are"),
+ array($mage, "why do you serve so much cunt in roblox", true),
+ array($vivi, "omg its almost as pretty as you are ahaha<br>am i bleeding out", true),
+ array($mage, "Alasator is suspicious of my figgy pudding", true),
+ array($me, "check out my rod", true),
+ array($mage, "thats a nice rod"),
+ array($joy, "yo you're really schloobin it out this time", true),
+ array($joy, "I'd be the best wife ever", true),
+ array($mage, "i think your tits dont like the mechanism", true),
+ array($me, "Are you the hoe?", true),
+ array($joy, "I have no issues with eating babies", true),
+ array($me, "Would you dropkick joe biden? I think you should dropkick joe biden", true),
+ array($celian, "i dont care enough about him to drop kick him tbh"),
+ array($me, "i think you should drop kick him"),
+ array($mage, "sad flooboob", true),
+ array($me, "thats so weirdcore liminal analogue horror backrooms scp", true),
+ array($me, "I think you should die for funsies", true),
+ array($mage, "Joob spoob?", true),
+ array($sad, "PUSSY?"),
+ array($vivi, "I would love to just absolutely rawdog a toaster", true),
+ array($sad, "i LOVE the filth", true),
+ array($goon, "i had a dream that, Wheezer they all decided to go birdwatching", true),
+ array($me, "Serial like Universal Serial Bus", true),
+ array($celian, "Love me a good froot loop"),
+ array($me, "thats his brain-heart<br>thats his brheart", true),
+ array($celian, "i think you should unload it", true),
+ array($vivi, "i would love to unload inside a shotgun, yes"),
+ array($celian, "im gonna cum", true),
+ array($vivi, "DUDE. NICE"),
+ array($vivi, "put my ass in a hydraulic press", true),
+ array($me, "No time spent scrolling through furry porn is wasted", true),
+ array($celian, "its the blood powered fuck machine", true),
+ array($me, "is the isopod cunty", true),
+ array($celian, "maybe"),
+ array($me, "Extra creamy sounds fun", true),
+ array($celian, "i had a testicle induced lucid dream last night", true),
+ array($celian, "i am NOT washing my hands in milk", true),
+ array($vivi, "why not? you scared?"),
+ array($mage, "Lesbianism! The yummy treat", true),
+ array($mage, "i think its fucked you cant eat butterflies", true),
+ array($mage, "eats your child"),
+ array($mage, "࿐𒁃𒁃𒀱𒄦𒈙𒐫࿐𒁃𒀱𒄦𒈙𒐫࿐𒀱𒄦𒈙𒐫࿐ ꧄𒁃꧃𒈙𒄦𒀱𒁃𒀱𒄦𒈙𒐫࿐𒐫꧄𒁃꧃𒈙𒄦𒀱𒐫꧄𒁃꧃", true),
+ array($celian, "playing and talking about this game isnt enough i need to absorb it like plants do to nutrients in the soil", true),
+ array($celian, "NOOOO you can't do that... spooky fog", true),
+ array($vivi, "im sorry my FISH is a little rusty", true),
+ array($me, "Mmmm yummy car engine steak ^_^", true),
+ array($mage, "You would put me in the meat grinder next", true),
+ array($me, "But you're not beef"),
+ array($celian, "What if I disguise myself as a steak"),
+ array($celian, "I don't think I've drawn a <em>human</em> dick since I was like...", true),
+ array($celian, "dfgprp-403c286c-ccb1-4a3c-ba2c-3aa8fff58c0b.png", true),
+ array($sad, "you're nut?", true),
+ array($celian, "aren't we all?"),
+ array($vivi, "your arms are looking very testicular mr. Thanos", true),
+ array($vivi, "that slut did NOT taste good", true),
+ array($vivi, "im a [little sponge] who requires [[MOISTURE]]", true),
+ array($celian, "HOLY SHIT REAL BOMB THREAT!!!!!!!!!!!!!!!!!!!!", true),
+ array($vivi, "Shmumpus", true),
+ array($vivi, "You can use the wet thing for combat", true),
+ array($vivi, "my hobbies include milking my creature for eggnog", true),
+ array($me, "everybody loves Bomb Threat", true),
+ array($celian, "cutely explodes", true),
+ array($sad, "YOOOOOO"),
+ array($mage, "You would dye your dick?", true),
+ array($celian, "If I had one"),
+ array($me, "very impressive sex", true),
+ array($celian, "do you think feetleys feet are lickable", true),
+ array($vivi, "my brain has gotten to the point where i cannot come up with a threat that does not involve cum", true),
+ array($me, "can you WEAR <strong>Gabriel's MILK</strong>?", true),
+ array($mage, "Italy has a cheese named horse cheese but it's not made from horses", true),
+ array($celian, "worm from animals we all know him", true),
+ array($vivi, "you're mom", true),
+ array($me, "No I'm not"),
+ array($mage, "I believe in parenting with the knife", true),
+ array($mage, "Penis", true),
+ array($me, "Penis"),
+ array($celian, "Dies"),
+ array($vivi, "who names a child JUICE??", true),
+ array($me, "next thing i know im in this alien's discord server", true),
+ array($celian, "Just remove your <em>balls</em>", true),
+ array($vivi, "im gonna fucken CUM about that....like ANGRILY.", true),
+ array($vivi, "im gonna look at more <strong>foreskin gifs</strong>", true),
+ array($vivi, "all i can do is CUM and HOPE FOR THE BEST", true),
+ array($me, "Rainbow Dash is Kim Kitsuragi's ponysona", true),
+ array($mage, "You don't love me? You would deny me uncrunched eyeballs?", true),
+ array($sad, "I fuck <em>the blockchain</em>", true),
+ array($me, "Beautiful women named Mario are messaging me on my phone", true),
+ array($sad, "his <strong>HUGE BOOBS</strong> are distracting me", true),
+ array($mage, "I think you should play Second Life with me", true),
+ array($sad, "I think you're mentally ill"),
+ array($mage, "most anime girls are cute in a dog way", true),
+ array($mage, "Bestie I'm talking about balls, cock and balls, you would turn me into balls?", true),
+ array($sad, "Yes"),
+ array($celian, "I find Lois so hot and sexy", true),
+ array($mage, "she doesnt have an articulated pussy, i have to tell you", true),
+ array($celian, "Mlp ponies are like Scooby Doo to me", true),
+ array($me, "Would you play Krunker recommended by Klook dot com with me?", true),
+ array($me, "I dress like a female bird", true),
+ array($vivi, "i love it when I can feel my hat THROB ON MY HEAD", true),
+ array($vivi, "put the <strong><em>P</em></strong>iss stone down you know what that does to your", true),
+ array($mage, "I am such a loser when it comes to women", true),
+ array($joy, "Only true rizz masters get rewarded with Egg", true),
+ array($mage, "You would be a little pony?", true),
+ array($me, "I can neither confirm nor deny this"),
+ array($celian, "I don't wanna have my pussy out<br>it's there in spirit", true),
+ array($mage, "Do <i>I</i> have a dick or a pussy in spirit"),
+ array($mage, "Babygirl you need ketamine", true),
+ array($goon, "he shits with that thing have some respect", true),
+ array($me, "I think Gabriel should have boob armor", true),
+ array($sad, "You're interesting"),
+ array($me, "i have a copy of Karkalicious on my computer", true),
+ array($celian, "I love you so much too we should go out or something", true),
+ array($mage, "i hope you have wonderful sloppy toppy", true),
+ array($celian, "hell? i could bring you there if you want<br>that sounded so threatening, i meant on like a date or something", true),
+ array($mage, "I think it's okay if cooking pasta ends up in murder", true),
+ array($mage, "teehee :3 <strong><em>SITS ON YOUR BALLS</em></strong>", true),
+ array($vivi, "i AM the vinegar in a can of spaghetti-os that was cleaned out for the sole purpose of drinking vinegar", true),
+ array($celian, "I don't have bones", true),
+ array($me, "You can get some from the bone trees"),
+ array($celian, "Hey do you still have blood?", true),
+ array($sad, "me when im just not built different", true),
+ array($me, "yoinks your blood", true),
+ array($celian, "The sixth element is... kiki", true),
+ array($me, "Extrudes your taxes", true),
+ array($mage, "Anime girl Will moment", true),
+ array($vivi, "just in time for the himbo findification!", true),
+ array($me, "I wish someone would put me down<br>Wait a minute", true),
+ array($celian, "why are you rotated you whore", true),
+ array($me, "brb", true),
+ array($celian, "yooo"),
+ array($celian, "Do you want to watch the movie? The pussy?", true),
+ array($celian, "why does my salmon look like a vagina", true),
+ array($me, "you could say I handle a lot of cocks", true),
+ array($me, "obviously im not gonna handle a bunch of raw chickens and then touch my cock"),
+ array($me, "I don't think cocks get killed for their meat"),
+ array($mage, "and the girls have like car shaped heads", true),
+ array($mage, "I'm trying to find a cool way to say nonbinary peoples' tits", true),
+ array($celian, "Luigi tits"),
+ array($celian, "If I have my wings out all the time what does that mean<br>like a dick?", true),
+ array($celian, "You want to be the person that eats horses like grapes?", true),
+ array($mage, "Some people pass down books and jewelry, my family passes down autism", true),
+ array($mage, "theres a panda walking through me", true),
+ array($celian, "I'm more like an osprey but like Tumblrized", true),
+ array($me, "Listen I may be a furry but at least I'm not a weeb", true),
+ array($celian, "do u wanna try to guess? 😳", true),
+ array($sad, "is it... BIG?<br>AND THROBBING?"),
+ array($sad, "Chicken is one of the most fucking boring shit you can wear", true),
+ array($mage, "Why don't Canadians eat the snow to get rid of it", true),
+ array($celian, "Well you see... there's a ladder that goes through the window"),
+ array($celian, "I heard mothsex.gif", true),
+ array($portals, "Yeah bare naked ladies fuck HARD", true),
+ array($me, "I hope I'm not just the gay person in your computer to you but the gay isopod in your computer", true),
+ array($celian, "oh<br>bestie i have bad news for u<br>your parents might be having sex :(", true),
+ array($me, "I'm literally an isopod my fursona is just a human and I'm wearing a fursuit 100% of the time", true),
+ array($me, "I said something to the effect of we should skip february except for valentines day<br>the rest you got right<br>nearly typed fruary", true),
+ array($mage, "Furry"),
+ array($me, "NO"),
+ array($celian, "fury behavior"),
+ array($me, "FURY INDEED IM FUCKING MAD"),
+ array($me, "amongus babies and their adopted dads", true),
+ array($thom, "I have 6 partners", true),
+ array($goon, "6 am or pm?"),
+ array($mage, "Men season themselves in the wind", true),
+ array($vivi, "i would love to be vored by a cow as well", true),
+ array($celian, "I'm eely", true),
+ array($celian, "yeehee"),
+ array($celian, "Im crunde"),
+ array($celian, "beainxella"),
+ array($me, "I cannot begin to describe the aerospace applications of a material with the properties that your beetle has given my pants", true),
+ array($me, "you can make space worthy pants with human technology we've done it before"),
+ array($celian, "COCK RING KEN", true),
+ array($celian, "Yoo no more gay!", true),
+ array($mage, "She hates gay people and LOVES bald people"),
+ array($mage, "i dont want to buy the fucked up heterosexual bird", true),
+ array($me, "you think Baldi is a dilf?", true),
+ array($celian, "sure?"),
+ array($vivi, "like i could fuck a freezer<br>i couldn't fuck a freezer<br>too cold", true),
+ array($celian, "<img src='https://media.discordapp.net/attachments/964004743238254642/1051302341439139961/image.png' />", true),
+ array($me, "MY computer is attractive, alright. yours is not.", true),
+ array($me, "your computer is a milf"),
+ array($me, "bowser was always hot. coward", true),
+ array($celian, "oh is your jaw equiped?", true),
+ array($sad, "I AM YOUR <b>CHEESEBURGER</b>", true),
+ array($celian, "gimmie a sex<br>*SEC<br>*SEC<br>*SEC<br>*SEC<br>A SECOND<br>OH MY GOD", true),
+ array($mage, "I think it's incredibly feminine to crawl around in storm drains", true),
+ array($me, "I can't tell where participating in the bit where I'm a furry ends and actually insisting I'm not a furry begins", true),
+ array($me, "what fucking cyberpunk world are you living in where panties have HUDs", true),
+ array($vivi, "I want a panic attack now", true),
+ array($me, "you're gonna be <i>so</i> tasty in two weeks", true),
+ array($me, "nobody's going to be able to decipher our language because they'll do it right and translate phrases like \"i think dio's tits should switch places\" and assume they did it wrong and keep trying", true),
+ array($me, "Sasuke shoved his hands into Naruto's pants and grinned when the blond whimpered from his touch. \"Already, Naruto?\" he asked.<br>Wrong chat<br>How yall doin", true),
+ array($me, "I'm not in denail I'm a furry", true),
+ array($me, "mold is a fursuit for bread", true),
+ array($mage, "when someone eats moldy food does that mean they're voring a furry?"),
+ array($me, "yes"),
+ array($me, "can you believe sag their pirt is four years old? <span style='font-family: monospace;'>(it is from 2018)</span>", true),
+ array($celian, "wait isn't it 5?<br>we're in 2022<br>did you count 2020<br>wait<br>i may be stupid."),
+ array($me, "I'm not FRENCH I'm a FURRY", true),
+ array($vivi, "Maybe the real cum pepsi is the friends we made along the way", true),
+ array($celian, "Ibuprofwn kind of slut.", true),
+ array($me, "I wish <i>my</i> cock was a fidget spinner", true),
+ array($vivi, "It's castration time!", true),
+ array($vivi, "I girlbossed a little to close to the comfy and fell asleep", true),
+ array($me, "that milk is the <i>sequel</i> to expired", true),
+ array($me, "Tony the tiger is HOT.", true),
+ array($sad, "Never ask a woman her age, never ask a man his salary, never ask a medieval man what his letters to his best friend said", true),
+ array($celian, "Dio would have been hotter with crocs", true),
+ array($sad, "Im just trying to picture like,, donald trump shitting", true),
+ array($me, "who would you have picked to win the tumblr sexy man award<br>the fucking onceler?", true),
+ array($thom, "...<br>how'd you know?"),
+ array($celian, "I wanna see the bloopers of Stephen Merchant moaning into the mic", true),
+ array($me, "come on, look at him. Sans is literally <b><i>so sexy</i></b>", true),
+ array($me, "there are many ways to consume weed: you can smoke it out of a doob, you can smoke it out of a bong, you can smoke it out of a brownie- ...wait", true),
+ array($mage, "I think you'll be a fan of gangster balls soon bestie", true),
+ array($celian, "there i removed my vagina", true),
+ array($me, "For you, the person who wants to be naked in a ball, that is very bad for you", true),
+ array($mage, "If I had to rate it, I'd rate it fucking gay", true),
+ array($mage, "you're only playing Scout correctly if you've had <b>gay sex</b>", true),
+ array($me, "*Caroline voice* Pee your pants, Mr. Johnson.", true),
+ array($sad, "i feel like im reading it with my eyes", true),
+ array($me, "i think there should be a datapack that lets you right click people with a bucket<br>and milk them", true),
+ array($celian, "bebito <span class='house'>house</span> reveel<br>bebito <span class='house'>hous</span> reveel when the bebito has.<br><span class='house'>hous</span> reveaal<br><span class='house'>hous</span> reval bebito REAL NO CLICKBAIT!!!!!!!!!!!!!!!!", true),
+ array($celian, "its like having a stroke WHILE having an aneurism", true),
+ array($mage, "ideal"),
+ array($me, "Joe Biden can get his ass blasted in a nonfurry way", true),
+ array($celian, "bruh (respectfully)", true),
+ array($celian, "this isn't a furby this is walter white cum jar", true),
+ array($vivi, "can I have the walter white cum jar please 👉👈🥺"),
+ array($me, "i'd rather not explode today, Thanks", true),
+ array($celian, "got some hair :)", true),
+ array($me, "Walter White is a <b><i><u>DILF</u></i></b>, Celian.", true),
+ array($sad, "if there <i>was</i> porn i wouldnt leave", true),
+ array($me, "haunting you with the looming threat of horse", true),
+ array($celian, "Walter White sex jumpscare", true),
+ array($celian, "Evangelion spoilers walter white and saul goodman kiss", true),
+ array($me, "I think they should stop commissioning criminal intelligence and start commissioning furries", true),
+ array($sad, "YOOO THAT'S MY GIIIIIIRL!!!! MY GIRL SNAPE MY GIRL!!!!", true),
+ array($vivi, "I feel like DeviantArt right now, 2014 edition.", true),
+ array($me, "I want a transparent penis", true),
+ array($mage, "The buzzing sound of the penis won't go away", true),
+ array($thom, "vivi I really think you should stop shitting on reddit", true),
+ array($celian, "I don't agree because I disagree with you", true),
+ array($celian, "", true),
+ array($mage, ""),
+ array($celian, ""),
+ array($thom, "<br><br>"),
+ array($me, ""),
+ array($vivi, ""),
+ array($celian, ""),
+ array($vivi, ""),
+ array($me, "Imagine touching <span style='font-family: monospace;'>[audio loss]</span> me", true),
+ array($thom, "theres something homoerotic about cars", true),
+ array($me, "im in spain without the sain", true),
+ array($mage, "REMEMBER TO MAKE BACKUP COPIES IF YOU INTEND TO EDIT THIS PENIS!!", true),
+ array($vivi, "god is actually surprisingly submissive and breedable", true),
+ array($me, "don't smoke cigarettes kids they'll make your lungs sus", true),
+ array($thom, "Bestie you've been given 2 full folders of skins<br>You can be any type of white you want to", true),
+ array($celian, "im gonna pause the video so i can listen to the flavors better", true),
+ array($vivi, "we stan the <b><i>boner knife</i></b> in this <span class='house'>house</span>", true),
+ array($vivi, "god said it's my turn on the being a milf", true),
+ array($mage, "\"Big Boy\" will be milked for his venom at the Australian Reptile Park", true),
+ array($mage, "i think you should get some weed and <i>drink it</i>", true),
+ array($sad, "imagine having a digestive system couldnt be me", true),
+ array($mage, "Hot"),
+ array($mage, "damn, guess i gotta send you some <i>autism</i> in the mail", true),
+ array($mage, "I just diagnosed you with bottom disorder", true),
+ array($mage, "Girls are always whole ass wet from the roof", true),
+ array($celian, "This is an amazing day for humanity, and by humanity, I mean my titties", true)
+ );
+
+ foreach($quotes as $q) {
+ if(isset($q[2]) && $q[2]) {
+ echo "<hr>";
+ }
+ echo "<div class='message'>";
+ echo "<img src='images/".$q[0]->pfp.".png' class='pfp' />";
+ echo "<div class='content'><h4 style='margin: 0; color: #".$q[0]->color.";'>".$q[0]->name."</h4>".$q[1]."</div>";
+ echo "</div>";
+ }
+ ?>
+
+ </body>
+</html>
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..e51089a
--- /dev/null
+++ b/favicon.ico
Binary files differ
diff --git a/favicon.png b/favicon.png
new file mode 100644
index 0000000..4729020
--- /dev/null
+++ b/favicon.png
Binary files differ
diff --git a/greenhouse/bg.jpg b/greenhouse/bg.jpg
new file mode 100644
index 0000000..151aa15
--- /dev/null
+++ b/greenhouse/bg.jpg
Binary files differ
diff --git a/greenhouse/bg.jxl b/greenhouse/bg.jxl
new file mode 100644
index 0000000..5461da8
--- /dev/null
+++ b/greenhouse/bg.jxl
Binary files differ
diff --git a/greenhouse/index.php b/greenhouse/index.php
new file mode 100644
index 0000000..c0e10d3
--- /dev/null
+++ b/greenhouse/index.php
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Greenhouse</title>
+ <link href="../../style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ body {
+ max-width: 50rem;
+ }
+ .shelf {
+ display: flex;
+ justify-content: space-around;
+ flex-wrap: wrap;
+ }
+ .shelf > iframe {
+ box-shadow: 2px 2px 6px black;
+ width: 250px;
+ height: 250px;
+ }
+ .shelf > * {
+ margin-bottom: 1rem;
+ }
+ #bodytext {
+ height: 250px;
+ width: 524px;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ }
+ @media only screen and (hover: none) and (max-width: 43rem) {
+ #bodytext {
+ width: 250px;
+ }
+ }
+ body {
+ max-width: var(--bodywidth);
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true, 10); ?>
+ <h1 style="overflow: hidden;">webgreenhouse</h1>
+ <h2 id="caption">&nbsp;</h2>
+ <div class="shelf">
+ <iframe src="https://isopod.cool/stuff/webgarden/" scrolling="no" loading="lazy"></iframe>
+ <div id="bodytext">
+ <p style="margin-top: 0; margin-bottom: 0.85rem;">You've found my webgarden page! A <a href="https://webgardens.neocities.org/tutorial/" title="or pot, or bonsai">webgarden</a> is a mini&#8209;webpage that other people can embed in their websites, as defined by <a href="https://justbecaws.neocities.org/">Corv</a>. Here's the code for mine:</p>
+ <textarea style="width: 100%; margin: 0; box-sizing: border-box;" rows="2" readonly>&lt;iframe src="https://isopod.cool/stuff/webgarden/" style="height: 250px; width: 250px;" scrolling="no" loading="lazy"&gt;&lt;/iframe&gt;</textarea>
+ </div>
+ <iframe src="https://lu.tiny-universes.net/webgarden/webgarden.html" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://obspogon.neocities.org/webgarden" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://pip-pepping.neocities.org/web-garden/webgarden.html" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://dantescanline.com/webgarden.html" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://missmoss.neocities.org/webgarden.html/" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://neonriser.neocities.org/webgarden.html" scrolling="no" loading="lazy"></iframe>
+ <iframe src="https://zeusofthecrows.github.io/stadt/webgarden" scrolling="no" loading="lazy"></iframe>
+ </div>
+
+ </body>
+</html>
diff --git a/guestbook/bg.jpg b/guestbook/bg.jpg
new file mode 100644
index 0000000..cd3b3a0
--- /dev/null
+++ b/guestbook/bg.jpg
Binary files differ
diff --git a/guestbook/bg.jxl b/guestbook/bg.jxl
new file mode 100644
index 0000000..a386f5e
--- /dev/null
+++ b/guestbook/bg.jxl
Binary files differ
diff --git a/guestbook/feed.php b/guestbook/feed.php
new file mode 100644
index 0000000..7cdb62e
--- /dev/null
+++ b/guestbook/feed.php
@@ -0,0 +1,47 @@
+<?php
+
+header('Content-Type: text/xml');
+
+echo '<rss version="2.0"><channel>';
+echo '<title>isopod.cool guestbook</title>';
+echo '<description>The guestbook on isopod.cool</description>';
+echo '<language>en-us</language>';
+echo '<link>https://isopod.cool/guestbook/</link>';
+echo '<generator>My crappy PHP code</generator>';
+
+$postlist = json_decode(file_get_contents("posts.json"));
+$index = 1;
+$totaloutput = "";
+foreach($postlist as $post) {
+ $output = "";
+ $date = date("D, d M Y H:m:s", $post->date) . " GMT";
+ $name = $post->name;
+ $message = $post->message;
+ $found = $post->found;
+ $website = $post->website;
+ $cool = $post->cool;
+ $coolsanitized = htmlentities(preg_replace("/https?:\/\//i", "", $cool));
+ $reply = htmlentities($post->reply);
+
+ if($website) { $output = $output."<a href='$website'>$name</a>:<br><br>"; }
+ else { $output = $output.$name.":<br><br>"; }
+
+ if($cool) {
+ $output = $output."<b>cool thing</b>: <a href='$cool'>$coolsanitized</a><br><br>";
+ }
+
+ if($found) {
+ $output = $output."<b>How did you find me?</b><br>$found<br><br>";
+ }
+
+ $output = $output.$message."<br><br>";
+
+ if($reply) {
+ $output = $output."<hr><b>Reply:</b><br>$reply";
+ }
+ $totaloutput = "<item><title>Entry #" . $index . " - " . $name . "</title><link>https://isopod.cool/guestbook/</link><pubDate>" . $date . "</pubDate><description>".htmlentities($output)."</description><guid isPermaLink='false'>" . $index . $post->date . $name . "</guid></item>".$totaloutput;
+ $index++;
+}
+
+echo $totaloutput;
+echo "</channel></rss>"; \ No newline at end of file
diff --git a/guestbook/index.php b/guestbook/index.php
new file mode 100644
index 0000000..7d85fd1
--- /dev/null
+++ b/guestbook/index.php
@@ -0,0 +1,244 @@
+<!--?php
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+?-->
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Guestbook</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ table {
+ border-collapse: collapse;
+ table-layout: fixed;
+ }
+ td {
+ padding: 0.3rem;
+ }
+
+ form > table {
+ width: 100%;
+ margin: auto;
+ margin-bottom: 1.5rem;
+ }
+ form td:first-child {
+ text-align: right;
+ }
+
+ article {
+ width: 100%;
+ margin: 2rem auto;
+ display: grid;
+ gap: 1rem;
+ grid-template-areas:
+ 'gb-name gb-date gb-index'
+ 'gb-cool gb-cool gb-cool'
+ 'gb-found gb-found gb-found'
+ 'gb-message gb-message gb-message'
+ 'gb-reply gb-reply gb-reply';
+ }
+ article :is(h1,h2,h3,h4,h5,h6) {
+ border: none;
+ padding-left: initial;
+ }
+
+ input, textarea {
+ border: none;
+ font-family: var(--stdfont);
+ }
+ input[type="text"], input[type="email"], textarea {
+ width: 100%;
+ background: none;
+ border-bottom: 2px solid #444444;
+ color: gainsboro;
+ padding: 0.35rem;
+ box-sizing: border-box;
+ font-size: .9em;
+ }
+ input[type="submit"], input[type="reset"] {
+ padding: 0.35rem 0.5rem;
+ box-shadow: 2px 2px 6px black;
+ margin: 0.3rem;
+ display: inline-block;
+ }
+ input[type="submit"]:active, input[type="reset"]:active {
+ transform: translate(1px, 1px); box-shadow: 0 0 2px black;
+ }
+ input[type="submit"]:hover, input[type="reset"]:hover {
+ cursor: pointer;
+ }
+
+ hr {
+ width: 30%;
+ }
+ .error {
+ color: red;
+ font-size: 0.85em;
+ }
+ .success {
+ color: #00ff00;
+ font-size: 0.85em;
+ }
+ .reply {
+ border-left: 3px solid gainsboro;
+ padding-left: 1rem;
+ }
+ .message {
+ padding-top: 1.5rem;
+ }
+ .gb-date {
+ text-align: center;
+ }
+ .gb-index {
+ text-align: right;
+ }
+ .gb-cool {
+ word-break: break-all;
+ }
+ .gb-name, .gb-date, .gb-index {
+ min-width: calc(var(--bodywidth) / 3);
+ }
+ @media only screen and (hover: none) {
+ form td:first-child {
+ text-align: left;
+ }
+ form td:nth-child(2) {
+ padding-left: 0;
+ padding-right: 0;
+ }
+ input[type="text"], input[type="email"], textarea {
+ background: none;
+ border: 2px solid #00000033;
+ border-bottom: 2px solid #888888;
+ }
+ article {
+ margin: 2rem auto;
+ }
+ @media (max-width: 43rem) {
+ article {
+ grid-template-areas:
+ 'gb-name gb-name gb-index'
+ 'gb-date gb-date gb-date'
+ 'gb-cool gb-cool gb-cool'
+ 'gb-found gb-found gb-found'
+ 'gb-message gb-message gb-message'
+ 'gb-reply gb-reply gb-reply';
+ }
+ }
+ }
+ @media (prefers-contrast: more) {
+ input[type="text"], input[type="email"], textarea {
+ outline: 1px solid white;
+ color: white;
+ }
+ input:focus, textarea:focus {
+ outline: 3px solid white;
+ }
+ input[type="submit"] {
+ background: none;
+ color: white;
+ outline: 1px solid white;
+ }
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(); ?>
+ <h1>guestbook</h1>
+ <h2 id="caption">say hi!</h2>
+ <nav>
+ <a href="feed.php">RSS</a>
+ </nav>
+ <?php
+ $return = $_GET["return"];
+ ?>
+ <form action="submit.php" method="post" autocomplete="off">
+ <table>
+
+ <?php if($return == "noname") { echo "<td></td><td><span class='error'>Name required!</span></td>"; } ?>
+ <tr>
+ <td>Name<span style="color:red;">*</span></td>
+ <td><input type="text" name="name"></td>
+ </tr>
+
+ <?php if($return == "invalidwebsite") { echo "<td></td><td><span class='error'>Invalid URL!</span></td>"; } ?>
+ <tr>
+ <td>Website</td>
+ <td><input type="text" name="website" placeholder="https://"></td>
+ </tr>
+
+ <?php if($return == "invalidlink") { echo "<td></td><td><span class='error'>Invalid URL!</span></td>"; } ?>
+ <tr>
+ <td>Link something cool</td>
+ <td><input type="text" name="cool" placeholder="https://"></td>
+ </tr>
+
+ <tr>
+ <td>How did you find me?</td>
+ <td><textarea name="found"></textarea></td>
+ </tr>
+
+ <?php if($return == "nomessage") { echo "<td></td><td><span class='error'>Message required!</span></td>"; } ?>
+ <tr>
+ <td>Message<span style="color:red;">*</span></td>
+ <td><textarea name="message" placeholder="Now supports Markdown!"></textarea></td>
+ </tr>
+
+ <?php if($return == "botcheckfailed") { echo "<td></td><td><span class='error'>You failed the bot check!</span></td>"; } ?>
+ <tr>
+ <td>Bot test (six-letter scientific term for a roly-poly or woodlouse)<span style="color:red;">*</span></td>
+ <td><input type="text" name="botcheck" placeholder="*.cool"></td>
+ </tr>
+
+ <?php if($return == "success") { echo "<td></td><td><span class='success'>Successfully posted!</span></td>"; } ?>
+ <tr>
+ <td colspan="2" style="text-align: center;"><input type="reset"><input type="submit" value="Post"></td>
+ </tr>
+
+ </table>
+ </form>
+ <?php
+ include("../Parsedown.php");
+ $Parsedown = new Parsedown();
+ $Parsedown->setSafeMode(true);
+
+ $totaloutput = "";
+ $postlist = json_decode(file_get_contents("posts.json"));
+ $index = 1;
+ foreach($postlist as $post) {
+ $output = "";
+ $date = date("Y-m-d h:iA", $post->date);
+ $name = $post->name;
+ $message = $Parsedown->text(html_entity_decode($post->message));
+ $found = $post->found;
+ $website = $post->website;
+ $cool = $post->cool;
+ $coolsanitized = htmlentities(preg_replace("/https?:\/\//i", "", $cool));
+ $reply = $Parsedown->text($post->reply);
+
+ $output = $output."<hr><article><div style='grid-area:gb-name;' class='gb-name'>";
+ if($website) { $output = $output."<a href='$website'>$name</a>"; }
+ else { $output = $output.$name; }
+ $output = $output."</div><div style='grid-area:gb-date;' class='gb-date'>$date</div><div style='grid-area:gb-index;' class='gb-index'>Entry #$index</div>";
+ if($cool) {
+ $output = $output."<div style='grid-area:gb-cool;' class='gb-cool'><b>cool thing</b>: <a href='$cool'>$coolsanitized</a></div>";
+ }
+ if($found) {
+ $output = $output."<div style='grid-area:gb-found;'><b>How did you find me?</b><br>$found</div>";
+ }
+ $output = $output."<div style='grid-area:gb-message;'>$message</div>";
+ if($reply) {
+ $output = $output."<div style='grid-area:gb-reply;' class='reply'><b>Reply</b>:<br>$reply</div>";
+ }
+ $output = $output."</article>";
+ $index++;
+ $totaloutput = $output.$totaloutput;
+ }
+ echo $totaloutput; ?>
+
+ </body>
+</html>
diff --git a/guestbook/submit.php b/guestbook/submit.php
new file mode 100644
index 0000000..09d0404
--- /dev/null
+++ b/guestbook/submit.php
@@ -0,0 +1,87 @@
+<?php
+ if ($_SERVER["REQUEST_METHOD"] == "POST") {
+
+ $returnCode = "success";
+ if($_POST["botcheck"] != "isopod") {
+ $returnCode = "botcheckfailed";
+ } else if(!$_POST["name"]) {
+ $returnCode = "noname";
+ } else if(!$_POST["message"]) {
+ $returnCode = "nomessage";
+ } else if($_POST["website"] and !preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i", $_POST["website"])) {
+ $returnCode = "invalidwebsite";
+ } else if($_POST["cool"] and !preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i", $_POST["cool"])) {
+ $returnCode = "invalidlink";
+ } else {
+
+ date_default_timezone_set("America/Edmonton");
+ $currentPost = array(
+ "date" => time(),
+ "name" => htmlentities($_POST["name"]),
+ "message" => htmlentities($_POST["message"]),
+ "found" => htmlentities($_POST["found"]),
+ "website" => $_POST["website"],
+ "cool" => $_POST["cool"],
+ "reply" => ""
+ );
+
+ $filename = "posts.json";
+
+ $handle = @fopen($filename, 'r+');
+
+ // create the file if needed
+ if ($handle === null)
+ {
+ $handle = fopen($filename, 'w+');
+ }
+
+ if ($handle)
+ {
+ // seek to the end
+ fseek($handle, 0, SEEK_END);
+
+ // are we at the end of is the file empty
+ if (ftell($handle) > 0)
+ {
+ // move back a byte
+ fseek($handle, -2, SEEK_END);
+
+ // add the trailing comma
+ fwrite($handle, ",\n", 2);
+
+ // add the new json string
+ fwrite($handle, json_encode($currentPost) . "]\n");
+ }
+ else
+ {
+ // write the first event inside an array
+ fwrite($handle, json_encode(array($currentPost)));
+ }
+
+ // close the handle on the file
+ fclose($handle);
+ }
+ }
+ }
+ header("Location: ./?return=$returnCode");
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Guestbook</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ body {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <p>Your post has been submitted! It's weird that you're seeing this page though. Maybe your browser can't process location headers? At any rate, click <?php echo "<a href='./?return=$returnCode'>here</a>"; ?> to get where you're supposed to be right now.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/images/Ophiocordyceps_unilateralis.png b/images/Ophiocordyceps_unilateralis.png
new file mode 100644
index 0000000..d6ba297
--- /dev/null
+++ b/images/Ophiocordyceps_unilateralis.png
Binary files differ
diff --git a/images/benlet1.png b/images/benlet1.png
new file mode 100644
index 0000000..5c757cd
--- /dev/null
+++ b/images/benlet1.png
Binary files differ
diff --git a/images/bg.jpg b/images/bg.jpg
new file mode 100644
index 0000000..79a70ec
--- /dev/null
+++ b/images/bg.jpg
Binary files differ
diff --git a/images/bg.jxl b/images/bg.jxl
new file mode 100644
index 0000000..3110cfb
--- /dev/null
+++ b/images/bg.jxl
Binary files differ
diff --git a/images/birthday_isopod.png b/images/birthday_isopod.png
new file mode 100644
index 0000000..c6161c1
--- /dev/null
+++ b/images/birthday_isopod.png
Binary files differ
diff --git a/images/birthday_isopod_small.png b/images/birthday_isopod_small.png
new file mode 100644
index 0000000..58feed0
--- /dev/null
+++ b/images/birthday_isopod_small.png
Binary files differ
diff --git a/images/blahaj.png b/images/blahaj.png
new file mode 100644
index 0000000..8df8ca1
--- /dev/null
+++ b/images/blahaj.png
Binary files differ
diff --git a/images/bubblecolumn1.gif b/images/bubblecolumn1.gif
new file mode 100644
index 0000000..ad31eb1
--- /dev/null
+++ b/images/bubblecolumn1.gif
Binary files differ
diff --git a/images/casiopea_isopod.png b/images/casiopea_isopod.png
new file mode 100644
index 0000000..9dfb5eb
--- /dev/null
+++ b/images/casiopea_isopod.png
Binary files differ
diff --git a/images/deeptwisty.png b/images/deeptwisty.png
new file mode 100644
index 0000000..7cb8472
--- /dev/null
+++ b/images/deeptwisty.png
Binary files differ
diff --git a/images/flatworm friday 1.mp4 b/images/flatworm friday 1.mp4
new file mode 100644
index 0000000..2187863
--- /dev/null
+++ b/images/flatworm friday 1.mp4
Binary files differ
diff --git a/images/flatworm friday 2.mp4 b/images/flatworm friday 2.mp4
new file mode 100644
index 0000000..c5339c3
--- /dev/null
+++ b/images/flatworm friday 2.mp4
Binary files differ
diff --git a/images/fry.png b/images/fry.png
new file mode 100644
index 0000000..60b2155
--- /dev/null
+++ b/images/fry.png
Binary files differ
diff --git a/images/isopod.php b/images/isopod.php
new file mode 100644
index 0000000..db01d31
--- /dev/null
+++ b/images/isopod.php
@@ -0,0 +1,15 @@
+<?php
+$size = '';
+if($_GET['small'] == 'y') { $size='_small'; }
+$isopod = 'isopod_with_aviators';
+if(date('m') == 10) {
+ $isopod = 'isopumpkin';
+} else if(date('m-d') == "09-13") {
+ $isopod = 'birthday_isopod';
+}
+$name = "$isopod$size.png";
+$fp = fopen($name, 'rb');
+header("Content-Type: image/png");
+header("Content-Length: " . filesize($name));
+fpassthru($fp);
+die; \ No newline at end of file
diff --git a/images/isopod3.png b/images/isopod3.png
new file mode 100644
index 0000000..1e98d19
--- /dev/null
+++ b/images/isopod3.png
Binary files differ
diff --git a/images/isopod_with_aviators.png b/images/isopod_with_aviators.png
new file mode 100644
index 0000000..443a6fb
--- /dev/null
+++ b/images/isopod_with_aviators.png
Binary files differ
diff --git a/images/isopod_with_aviators_small.png b/images/isopod_with_aviators_small.png
new file mode 100644
index 0000000..27ae5b7
--- /dev/null
+++ b/images/isopod_with_aviators_small.png
Binary files differ
diff --git a/images/isopumpkin.png b/images/isopumpkin.png
new file mode 100644
index 0000000..3648a70
--- /dev/null
+++ b/images/isopumpkin.png
Binary files differ
diff --git a/images/isopumpkin_small.png b/images/isopumpkin_small.png
new file mode 100644
index 0000000..8244421
--- /dev/null
+++ b/images/isopumpkin_small.png
Binary files differ
diff --git a/images/new.gif b/images/new.gif
new file mode 100644
index 0000000..02aad76
--- /dev/null
+++ b/images/new.gif
Binary files differ
diff --git a/images/place_him.png b/images/place_him.png
new file mode 100644
index 0000000..918f108
--- /dev/null
+++ b/images/place_him.png
Binary files differ
diff --git a/images/plant1-2.png b/images/plant1-2.png
new file mode 100644
index 0000000..dc0c6db
--- /dev/null
+++ b/images/plant1-2.png
Binary files differ
diff --git a/images/shadow.png b/images/shadow.png
new file mode 100644
index 0000000..de0dbbc
--- /dev/null
+++ b/images/shadow.png
Binary files differ
diff --git a/images/spruce_planks.png b/images/spruce_planks.png
new file mode 100644
index 0000000..df5bda5
--- /dev/null
+++ b/images/spruce_planks.png
Binary files differ
diff --git a/images/wobble_mc_house_bg.png b/images/wobble_mc_house_bg.png
new file mode 100644
index 0000000..9211364
--- /dev/null
+++ b/images/wobble_mc_house_bg.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..fdae17a
--- /dev/null
+++ b/index.php
@@ -0,0 +1,380 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ body {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ main {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+ main > :is(div, nav) {
+ width: 100%;
+ }
+
+ #webrings > div {
+ margin: var(--stdpadding);
+ }
+ #webrings div :is(a, span) {
+ padding: initial;
+ margin: initial;
+ background: none;
+ border-left: none;
+ }
+
+ #guys {
+ position: fixed;
+ bottom: 0;
+ left: 3rem;
+ font-size: 0;
+ }
+ #guys > * {
+ margin-right: var(--stdpadding);
+ }
+ #bubblecolumn {
+ position: absolute;
+ right: 7%;
+ top: 0;
+ width: 29px;
+ height: 100%;
+ background-image: url(images/bubblecolumn1.gif);
+ background-repeat: repeat-y;
+ }
+ #bucketfish, .bflink {
+ --red: #ffcaca;
+ --orange: #ffedc1;
+ --yellow: #feffb8;
+ --green: #c4ffcb;
+ --blue: #add8ff;
+ --purple: #ccafe9;
+ --darkgreen: #3E885B;
+ --darkblue: #7fb4f5;
+ --background: #454545;
+ --rainbowright: linear-gradient(to right, var(--red) 0%, var(--orange) 20%, var(--yellow) 40%, var(--green) 60%, var(--blue) 80%, var(--purple) 100%);
+
+ color: var(--purple);
+ display: inline-block;
+ position: relative;
+ text-decoration: none;
+ transition: linear .2s;
+ }
+ #bucketfish:before, .bflink:before {
+ background: var(--rainbowright);
+ content: '';
+ height: 2px;
+ position: absolute;
+ bottom: -1.5px;
+ width: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ transition: width 0.2s ease-in-out;
+ }
+ .bflink:hover {
+ color: var(--purple);
+ }
+ #bucketfish:hover:before, .bflink:hover:before {
+ width: 0;
+ }
+ #bucketfish span {
+ animation-delay: var(--n);
+ animation: wave 1.5s linear var(--n) infinite forwards running, rainbow 3s linear var(--n) infinite forwards running;
+ position: relative;
+ }
+
+ @media (prefers-reduced-motion) {
+ #bubblecolumn {
+ display: none;
+ }
+ #bucketfish span {
+ animation: none;
+ }
+ }
+ @media only screen and (hover: none) {
+ #rightsidebg {
+ box-shadow: none;
+ }
+ main {
+ justify-content: initial;
+ height: initial;
+ }
+ #guys {
+ position: initial;
+ bottom: initial;
+ left: initial;
+ }
+ body {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ }
+ }
+
+ @keyframes wave{
+ 0% {top: 0px;}
+ 25% {top: -1px;}
+ 50% {top: 0px;}
+ 75% {top: 1px;}
+ 100% {top: 0px;}
+ }
+
+ @keyframes rainbow{
+ 0% {color: var(--red);}
+ 17% {color: var(--orange);}
+ 33% {color: var(--yellow);}
+ 50% {color: var(--green);}
+ 67% {color: var(--blue);}
+ 83% {color: var(--purple);}
+ 100% {color: var(--red);}
+ }
+ </style>
+ <?php
+ include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php');
+ if(!preg_match('/(headless.*)/i', $_SERVER['HTTP_USER_AGENT'])) {
+ $captions = array();
+ $seasonal = false;
+ switch(date('m')) {
+ case 6:
+ $captions = array(
+ 'your gay',
+ 'the fuck is a gender',
+ 'trnasgener',
+ 'This site uses $_GAY_COOKIE_EQUIVALENT',
+ 'Supports LGBT!',
+ 'Banned in Florida!',
+ 'Are you cis or are you normal'
+ );
+ $seasonal = true;
+ break;
+ case 10:
+ $captions = array(
+ 'Boo!',
+ 'Happy Halloween!',
+ 'World\'s ' . rand(1, 1000000) . 'th spookiest website',
+ '$spooky_captions[array_rand($spooky_captions)]',
+ 'I thought I\'d be able to come up with more Halloween captions to be honest',
+ 'It\'s the Spooky Month&trade;!',
+ 'I vant to suck your blood! Just kidding... Unless...?',
+ 'This site uses $_HALLOWEEN_THEMED_COOKIE_EQUIVALENT'
+ );
+ $seasonal = true;
+ break;
+ case 12:
+ $captions = array(
+ 'hoe hoe hoe or some shit',
+ 'Happy Holidays!',
+ 'World\'s ' . rand(1, 1000000) . 'th most festive website',
+ 'Like half of these captions are just lifted wholesale from the Halloween ones',
+ '$festive_captions[array_rand($festive_captions)]',
+ 'Merry Capitalism!',
+ 'It\'s winter! Nothing else special about this time of year, no siree!',
+ 'This site uses $_CHRISTMAS_THEMED_COOKIE_EQUIVALENT... I guess that would just be normal cookies, huh?',
+ 'Pretend I put Mariah Carey on autoplay here',
+ 'MERRY SHITSCRAM',
+ 'Merry consumerism!',
+ 'Do people eat turkey on Christmas? Is that, like, a thing?',
+ 'christmas isn\'t real'
+ );
+ $seasonal = true;
+ break;
+ default:
+ $captions = array(
+ 'bruh moment',
+ 'Try reloading!',
+ 'Supports VPNs',
+ 'I use arch btw',
+ 'Stream deep twisty',
+ 'MySite.html',
+ 'Over Construction',
+ 'Real isopod hours',
+ 'Version 3.1: The Accent Borders Update',
+ 'Version 3.1: The Tables Don\'t Look Like Shit Anymore Update',
+ 'depytwisty',
+ '[object Object]',
+ '* You found the [Moss]!',
+ 'Minceraft',
+ 'Best viewed with Firefox',
+ 'Isopod gaming',
+ 'Website of some girl',
+ 'your mom',
+ 'Badly programmed',
+ 'Oh, you know ;)',
+ 'gamer (terminal)',
+ 'This is not a place of honor',
+ 'I can type interrobangs, watch‽',
+ 'ඞ',
+ '127.0.0.1',
+ 'assholes DNI',
+ 'swag',
+ '\'\'',
+ '$captions[array_rand($captions)]',
+ 'NFT bros don\'t FUCKING interact',
+ '<span class="minecraftsplash">Kind of dragon free!</span>',
+ 'This site uses cookies (chocolate chip)',
+ 'Now with reduced centralization!',
+ 'your gay',
+ 'the fuck is a gender',
+ 'The Only Website',
+ '𝓘𝓷𝓪𝓬𝓬𝓮𝓼𝓼𝓲𝓫𝓵𝓮!',
+ 'Follow me on Google+!',
+ '404: caption not found',
+ 'Web π compliant!',
+ 'If you\'re seeing this, something is seriously wrong.',
+ 'cringe',
+ 'don\'t smoke cigarettes kids they\'ll make your lungs sus',
+ 'real life isopod',
+ 'holy fucking bingle',
+ 'AI (Aquatic Isopod) generated',
+ 'crubge',
+ 'Only unpickle data you trust.',
+ 'Tested in prod!',
+ 'pwetty epic B)',
+ 'Known to the state of California to cause cancer',
+ 'Semi-modular!',
+ 'Did you know?',
+ 'shrimps is bugs',
+ 'Delicious!',
+ 'trnasgener',
+ 'Opinionated!',
+ 'Eurorack compatible!',
+ 'Hackable!',
+ 'HiDPI!',
+ '&amp;mdash; addict',
+ '3D printed!',
+ 'Federated!',
+ 'Chitinous!',
+ 'is this a bedbuge?',
+ 'is this buge trans gener?',
+ 'Now in HD!',
+ 'COUNTER',
+ 'TUEADAY',
+ 'PLACEHIM',
+ 'UPSIDEDOWN',
+ 'RGB',
+ 'BLAHAJ',
+ '@BEAT',
+ 'HALO',
+ 'LIKECARPET'
+ );
+ break;
+ }
+ $cap = $captions[array_rand($captions)];
+ if($_GET['caption']) {
+ $cap = $captions[$_GET['caption']];
+ }
+ $tit = $cap;
+ if(!$seasonal) {
+ switch($cap) {
+ case 'COUNTER':
+ $num = (int) filter_var(file_get_contents("views.txt"), FILTER_SANITIZE_NUMBER_INT);
+ $num++;
+ file_put_contents("views.txt", $num);
+ $cap = "This caption has been viewed $num times!";
+ $tit = "This title has been viewed $num times!";
+ break;
+ case 'TUEADAY':
+ $day = array("suday", "moday", "tueaday", "weaday", "thuday", "friaday", "satuaday")[date('w')];
+ $cap = "wait it's fucking $day. god.";
+ $tit = $cap;
+ echo "<style type='text/css'>:root{--h1-image:url('/old/1/images/$day.png');}</style>";
+ break;
+ case 'PLACEHIM':
+ $cap = 'place him on your site immediately';
+ $tit = $cap;
+ echo "<style type='text/css'>:root{--h1-image:url('images/place_him.png');}</style>";
+ break;
+ case 'BLAHAJ':
+ $cap = '<img id="blahaj" src="images/blahaj.png"> <a href="https://berrymot.github.io/">certified</a> Good Website by blåhaj';
+ $tit = "certified Good Website by blåhaj";
+ echo "<style type='text/css'>#blahaj { animation: spin 5s linear infinite; height: 1em; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @media (prefers-reduced-motion) { #blahaj { animation: none; } }</style>";
+ break;
+ case 'Kind of dragon free!':
+ $cap = '<span class="minecraftsplash">Kind of dragon free!</span>';
+ break;
+ case 'UPSIDEDOWN':
+ $cap = '<span class="flipped">Upside Down!</span>';
+ $tit = '¡uʍop ǝpısdn';
+ break;
+ case 'RGB':
+ $cap = '<span class="rainbowtext">RGB Gaming Webpage</span>';
+ $tit = 'RGB Gaming Webpage';
+ break;
+ case '@BEAT':
+ $cap = '<a href="/stuff/beat/">@'.date("B").'</a>';
+ $tit = '@'.date("B");
+ break;
+ case 'HALO':
+ $cap = '<a href="https://www.youtube.com/watch?v=N14uA0EhBAU">coke and fries halo</a>';
+ $tit = 'coke and fries halo';
+ break;
+ case 'LIKECARPET':
+ $cap = 'Check it out, I\'m in the <span class="house">house</span> like carpet';
+ $tit = 'Check it out, I\'m in the house like carpet';
+ break;
+ }
+ }
+ }
+ ?>
+ <title><?php if($tit) { echo "isopod.cool v3 - $tit"; } else { echo "isopod.cool v3"; } ?></title>
+ <meta name="description" content="real life isopod">
+ </head>
+ <body>
+ <?php include('nav.php'); bg(true, 11, "Pictured: The eponymous Deep Twisty"); ?>
+ <main>
+ <div>
+ <h1 style="margin-top: 0;">isopod dot cool<sup>v3.1</sup></h1>
+ <h2 id="caption"><?php echo $cap; ?></h2>
+ </div>
+ <nav id="webrings">
+ <div style="font-family: sans-serif; font-weight: bold;">
+ <a href="https://hotlinewebring.club/bathynomus/previous" style="color: white; text-decoration: none;">←</a>
+ <a href="https://hotlinewebring.club/" style="color: white; text-decoration: none; font-style: italic;">HOTLINE WEBRING</a>
+ <a href="https://hotlinewebring.club/bathynomus/next" style="color: white; text-decoration: none;">→</a>
+ </div>
+ <div>
+ <a href="https://melonland.net/surf-club.html" style="color: #ff74ff;"><span style="color: #e7ad59;">melon</span><span style="color: #c0ea32;">ring</span></a>
+ <a href="https://brain.melonking.net/surf-club-random" style="color: #ff74ff;"><span style="color: #864cff;">?</span></a>
+ </div>
+ <div>
+ <a href="https://webring.bucketfish.me/redirect.html?to=prev&name=isopod" class="bflink">⥼</a>
+ <a href="https://webring.bucketfish.me" id="bucketfish"><span style="--n:-10000ms;">b</span><span style="--n:-9900ms;">u</span><span style="--n:-9800ms;">c</span><span style="--n:-9700ms;">k</span><span style="--n:-9600ms;">e</span><span style="--n:-9500ms;">t</span><span style="--n:-9400ms;"> </span><span style="--n:-9300ms;">w</span><span style="--n:-9200ms;">e</span><span style="--n:-9100ms;">b</span><span style="--n:-9000ms;">r</span><span style="--n:-8900ms;">i</span><span style="--n:-8800ms;">n</span><span style="--n:-8700ms;">g</span></a>
+ <a href="https://webring.bucketfish.me/redirect.html?to=next&name=isopod" class="bflink">⥽</a>
+ </div>
+ <div>
+ <a href="https://fediring.net/previous?host=isopod.cool">←</a>
+ <a href="https://fediring.net/">fediring</a>
+ <a href="https://fediring.net/random">?</a>
+ <a href="https://fediring.net/next?host=isopod.cool">→</a>
+ </div>
+ </nav>
+ <!--script type="text/javascript">document.write('<a href="desktop.html">$login<span class="blinking" >_</span></a>');</script-->
+ </main>
+
+ <div id="guys">
+ <a target="_blank" href="https://dokodemo.neocities.org/" title="made by Dokodemo"><img alt="An isopod!" src="images/isopod3.png"></a>
+ <a target="_blank" href="https://lu.tiny-universes.net" title="hi, i'm kevin!"><img alt="Kevin" src="images/plant1-2.png"></a>
+ <a target="_blank" href="https://newlambda.neocities.org/stuff/adopt" title="benlet"><img alt="benlet" src="images/benlet1.png" style="width: 32px; image-rendering: pixelated;"></a>
+ <a target="_blank" href="https://www.pixelcatsend.com/profile&id=3734" title="Shadow"><img alt="Shadow" src="images/shadow.png" style="image-rendering: pixelated;"></a>
+ <a target="_blank" href="https://tarraxahum.neocities.org/adopt/adopt_center" title="french fry"><img alt="french fry" src="images/fry.png" style="height: 2rem;"></a>
+ <a target="_blank" href="https://kelpeater.neocities.org/collections/isopods" title="Another isopod!"><img alt="Another isopod!" src="images/casiopea_isopod.png" style="height: 4rem;"></a>
+ <a target="_blank" href="https://shroom.ink/decay/adopt-a-shroom/" title="Ophiocordyceps Unilateralis"><img alt="Ophiocordyceps Unilateralis" src="images/Ophiocordyceps_unilateralis.png" style="height: 4rem;"></a>
+ </div>
+ <div id="bubblecolumn"></div>
+ <?php
+ if(date("w") == "5" && rand(0, 9) == 4) {
+ $ind = rand(1,2);
+ $filename = "images/flatworm friday $ind.mp4";
+ echo "<div id='flatwormfriday' style='position: absolute;left: 0;right: 0;top: 0;bottom: 0;background: #000000cc;display: flex;justify-content: center;align-items: center;'><video controls=''><source src='$filename' type='video/mp4'>It's Flatworm Friday! Your browser does not support the video tag.</video><span style='position: absolute; left: 1rem; bottom: 1rem;'>Refresh the page to close this</span></div>";
+ }
+ ?>
+ <script src="wimpod.js"></script>
+ </body>
+</html>
diff --git a/links/bg.jpg b/links/bg.jpg
new file mode 100644
index 0000000..83423a9
--- /dev/null
+++ b/links/bg.jpg
Binary files differ
diff --git a/links/bg.jxl b/links/bg.jxl
new file mode 100644
index 0000000..32c1851
--- /dev/null
+++ b/links/bg.jxl
Binary files differ
diff --git a/links/buttons/64thsanctum.gif b/links/buttons/64thsanctum.gif
new file mode 100644
index 0000000..8da463e
--- /dev/null
+++ b/links/buttons/64thsanctum.gif
Binary files differ
diff --git a/links/buttons/Icelog.gif b/links/buttons/Icelog.gif
new file mode 100644
index 0000000..a024349
--- /dev/null
+++ b/links/buttons/Icelog.gif
Binary files differ
diff --git a/links/buttons/corru.gif b/links/buttons/corru.gif
new file mode 100644
index 0000000..d94e76d
--- /dev/null
+++ b/links/buttons/corru.gif
Binary files differ
diff --git a/links/buttons/josef.gif b/links/buttons/josef.gif
new file mode 100644
index 0000000..169ef12
--- /dev/null
+++ b/links/buttons/josef.gif
Binary files differ
diff --git a/links/buttons/kalechips.png b/links/buttons/kalechips.png
new file mode 100644
index 0000000..d756515
--- /dev/null
+++ b/links/buttons/kalechips.png
Binary files differ
diff --git a/links/buttons/kopper.png b/links/buttons/kopper.png
new file mode 100644
index 0000000..d0d2a50
--- /dev/null
+++ b/links/buttons/kopper.png
Binary files differ
diff --git a/links/buttons/melonland-forum.gif b/links/buttons/melonland-forum.gif
new file mode 100644
index 0000000..6246e39
--- /dev/null
+++ b/links/buttons/melonland-forum.gif
Binary files differ
diff --git a/links/buttons/morrysillusion.png b/links/buttons/morrysillusion.png
new file mode 100644
index 0000000..8db9fda
--- /dev/null
+++ b/links/buttons/morrysillusion.png
Binary files differ
diff --git a/links/buttons/moth-88x31.svg b/links/buttons/moth-88x31.svg
new file mode 100644
index 0000000..152e884
--- /dev/null
+++ b/links/buttons/moth-88x31.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="88" height="31">
+ <rect width="86" height="29" x="1" y="1" fill="#140b05" stroke="#fc9505" stroke-linecap="square" stroke-miterlimit="100" stroke-width="2" rx="0" ry="0"/>
+ <g stroke="#fc9505" stroke-linecap="round" stroke-linejoin="round">
+ <path fill="#4e2e05" stroke-width="1.65" d="M12.2 21.87s0 3.3 3.3 3.3 3.3-3.3 3.3-3.3"/>
+ <path fill="none" stroke-width="1.65" d="M22.12 5.33s-3.31 0-6.62 6.61M8.88 5.33s3.31 0 6.62 6.61"/>
+ <path fill="#4e2e05" stroke-width="1.65" d="M12.2 11.94h0s0-3.3 3.3-3.3 3.3 3.3 3.3 3.3c6.62 6.62 9.93 13.23-3.3 9.93-13.23 3.3-9.92-3.31-3.3-9.93"/>
+ <path fill="none" stroke-width="1.65" d="M18.8 15.25c0 3.3-1.65 4.96-1.65 4.96m-4.96-4.96c0 3.3 1.66 4.96 1.66 4.96"/>
+ </g>
+ <rect width="54" height="21" x="31" y="7" rx="0" ry="0"/>
+ <rect width="54" height="21" x="29" y="5" fill="#fc9505" rx="0" ry="0"/>
+ <text x="56.2" y="19.87" fill="#140b05" stroke-linecap="square" stroke-miterlimit="0" font-family="IBM Plex Mono, monospace" font-size="12" font-weight="600" text-anchor="middle" text-decoration="underline"><tspan x="56.2" y="19.87">moth</tspan></text>
+</svg> \ No newline at end of file
diff --git a/links/buttons/onlysans.png b/links/buttons/onlysans.png
new file mode 100644
index 0000000..2f32986
--- /dev/null
+++ b/links/buttons/onlysans.png
Binary files differ
diff --git a/links/buttons/robophobia.png b/links/buttons/robophobia.png
new file mode 100644
index 0000000..606671b
--- /dev/null
+++ b/links/buttons/robophobia.png
Binary files differ
diff --git a/links/buttons/sadgrl.gif b/links/buttons/sadgrl.gif
new file mode 100644
index 0000000..a80e8bf
--- /dev/null
+++ b/links/buttons/sadgrl.gif
Binary files differ
diff --git a/links/buttons/seaslug.png b/links/buttons/seaslug.png
new file mode 100644
index 0000000..4b59530
--- /dev/null
+++ b/links/buttons/seaslug.png
Binary files differ
diff --git a/links/buttons/sizeofcat.png b/links/buttons/sizeofcat.png
new file mode 100644
index 0000000..bcacfd6
--- /dev/null
+++ b/links/buttons/sizeofcat.png
Binary files differ
diff --git a/links/buttons/xaselgio.gif b/links/buttons/xaselgio.gif
new file mode 100644
index 0000000..af8e7f6
--- /dev/null
+++ b/links/buttons/xaselgio.gif
Binary files differ
diff --git a/links/index.php b/links/index.php
new file mode 100644
index 0000000..8fadbdc
--- /dev/null
+++ b/links/index.php
@@ -0,0 +1,381 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Links</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true, 1000, "Pictured: My home internet connection") ?>
+ <h1>outbound links</h1>
+ <h2 id="caption">the sequel to google (under construction)</h2>
+ <h2>Neighbours</h2>
+ <table>
+ <tr>
+ <td colspan="2">
+ <div class="buttons">
+ <a href="https://seaslug.neocities.org/"><img src="buttons/seaslug.png" alt="Sea slug on the net!"></a>
+ <a href="https://onlysans.neocities.org/"><img src="buttons/onlysans.png" alt="Only Sans"></a>
+ <a href="https://kalechips.net/"><img src="buttons/kalechips.png" alt="Kalechips"></a>
+ <a href="https://the64thsanctum.net/"><img src="buttons/64thsanctum.gif" alt="64th Sanctum"></a>
+ <a href="https://sadgrl.online/"><img src="buttons/sadgrl.gif" alt="Sadgrl"></a>
+ <a href="https://robophobia.neocities.org/"><img src="buttons/robophobia.png" alt="Robophobia"></a>
+ <a href="https://forum.melonland.net/"><img src="buttons/melonland-forum.gif" alt="Melonland Forum"></a>
+ <a href="https://sizeof.cat/"><img src="buttons/sizeofcat.png" alt="Size of Cat"></a>
+ <a href="https://moth.monster/"><img src="buttons/moth-88x31.svg" alt="Moth Dot Monster"></a>
+ <a href="https://w.on-t.work/"><img src="buttons/kopper.png" alt="Won't Work!"></a>
+ <a href="https://xaselgio.net/"><img src="buttons/xaselgio.gif" alt="Indigo's den"></a>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <h2>Utility</h2>
+ <table>
+ <tr>
+ <td><a href="https://easyussr.neocities.org/torrenting.html">Easy USSR</a></td>
+ <td>A comprehensive beginner's guide to <span class="serif">Legally Acquiring Media</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://12ft.io/">12ft.io</a></td>
+ <td>Show me a 10ft paywall, I'll show you a 12ft ladder.</td>
+ </tr>
+ <tr>
+ <td><a href="https://landchad.net/">LandChad.net</a></td>
+ <td>A collection of tutorials for setting up various self-hosted services.</td>
+ </tr>
+ <tr>
+ <td><a href="https://3ds.hacks.guide/">3DS Hacks Guide</a></td>
+ <td>A comprehensive guide for modding 2ds and 3ds consoles. I know it's legit because I used it on mine.</td>
+ </tr>
+ <tr>
+ <td><a href="https://hshop.erista.me/">hShop</a></td>
+ <td>A repository of software for your freshly hacked 3ds</td>
+ </tr>
+ <tr>
+ <td><a href="https://switching.software/">switching.software</a></td>
+ <td>A curated list of alternatives to popular software and services from companies like Google and Amazon.</td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/awesome-selfhosted/awesome-selfhosted">Awesome Selfhosted</a></td>
+ <td>A comprehensive list of self-hosted alternatives to various software.</td>
+ </tr>
+ <tr>
+ <td><a href="https://newpipe.net/">Newpipe</a> & <a href="https://invidious.io/">Invidious</a></td>
+ <td>Better YouTube frontends for Android and the browser respectively.</td>
+ </tr>
+ <td><a href="https://linuxdaw.org/">Linux DAW</a></td>
+ <td>A comprehensive list of VST plugins that work on Linux.</td>
+ </tr>
+ <tr>
+ <td><a href="https://hypem.com/merch-table">Hype Machine Merch Table</a></td>
+ <td>Scans a Spotify playlist and links the Bandcamp page of any artist in it who has one.</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.darkpattern.games/">Dark Pattern Games</a></td>
+ <td>A database of mobile games that flags them for predatory design patterns.</td>
+ </tr>
+ <tr>
+ <td><a href="https://regexr.com/">RegExr</a></td>
+ <td>A website to test regular expressions for you</td>
+ </tr>
+ <tr>
+ <td><a href="https://jsrn.net/howoldisit/">How old is it?</a></td>
+ <td>For when your prospective employer asks for 10 years of <?php
+ $boogeraids = array(
+ '.NET Core',
+ 'AdonisJs',
+ 'Apache Airflow',
+ 'Angular',
+ 'Aurelia',
+ 'Azure Purview',
+ 'Azure Synapse Analytics',
+ 'Babel',
+ 'Bootstrap 3',
+ 'Bootstrap 4',
+ 'Bootstrap 5',
+ 'Bulma',
+ 'Caddy',
+ 'ClickHouse',
+ 'CockroachDB',
+ 'Concourse',
+ 'Crystal',
+ 'Deno',
+ 'Docker',
+ 'Dronecode',
+ 'Ecto',
+ 'Electron',
+ 'FastAPI',
+ 'Fastify',
+ 'Flutter',
+ 'fsl',
+ 'Gatsby',
+ 'Ghost',
+ 'Godot',
+ 'Grafana',
+ 'GraphQL',
+ 'Gulp',
+ 'Apache Hive',
+ 'Hugo',
+ 'Hyperledger',
+ 'IBM MQ',
+ 'Inferno JS',
+ 'Infinidash',
+ 'InfluxDB',
+ 'Ionic',
+ 'Istio',
+ 'jssm',
+ 'Keras',
+ 'Kubernetes',
+ 'Laravel 4',
+ 'Laravel 5',
+ 'Materialize CSS',
+ 'Metal',
+ 'Micronaut',
+ 'Mithril.js',
+ 'NativeScript',
+ 'Nerves',
+ 'NestJS',
+ 'Nette',
+ 'NextJS',
+ 'Nuxt',
+ 'Odin',
+ 'Parcel',
+ 'Phalcon',
+ 'Phoenix',
+ 'PHPStan',
+ 'Podman',
+ 'Polymer',
+ 'Power BI',
+ 'Power BI Embedded',
+ 'Power Query M Formula Language',
+ 'Preact',
+ 'Prometheus',
+ 'PX4 Firmware',
+ 'PyTorch',
+ 'Quasar',
+ 'Raku',
+ 'Ramda',
+ 'React',
+ 'React Native',
+ 'ReasonML',
+ 'Redux',
+ 'Rollup',
+ 'ROS 2',
+ 'RxJs',
+ 'scikit-image',
+ 'Serverless Framework',
+ 'Shiny',
+ 'Snowpack',
+ 'Solidity',
+ 'Apache Spark',
+ 'Spock Framework',
+ 'Svelte',
+ 'Swift',
+ 'Tailwind',
+ 'Telegraf',
+ 'TensorFlow',
+ 'Terraform',
+ 'TOML',
+ 'Traefik',
+ 'Umbrella JS',
+ 'VSCode',
+ 'Vue',
+ 'Vulkan',
+ 'WebAssembly',
+ 'Windows 10',
+ 'Windows 11',
+ 'WSL',
+ 'Xamarin Forms',
+ 'Yarn',
+ 'Zend Framework 3',
+ 'Zig'
+ );
+ echo $boogeraids[array_rand($boogeraids)];
+ ?> experience.</td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/viraptor/reverse-interview">Reverse Interview</a></td>
+ <td>A list of questions to ask at (tech) job interviews</td>
+ </tr>
+ <tr>
+ <td><a href="https://based.cooking/">based.cooking</a></td>
+ <td>A recipe website without all the typical recipe website garbage.</td>
+ </tr>
+ <tr>
+ <td><a href="https://8mb.video/">8mbvideo</a></td>
+ <td>Compresses any video file just enough to comply with Discord's filesize limits.</td>
+ </tr>
+ <tr>
+ <td><a href="https://jort.link/">jort.link</a></td>
+ <td>A shield to prevent accidental DDOSing of links posted to the fediverse</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.doesthedogdie.com/">Does the dog die?</a></td>
+ <td>A crowdsourced database of content warnings for media</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.unconsentingmedia.org/">Unconsenting Media</a></td>
+ <td>Similar to doesthedogdie but for sexual violence in particular</td>
+ </tr>
+ <tr>
+ <td><a href="https://caniplaythat.com/">Can I Play That?</a></td>
+ <td>An accessibility-focused videogame review site</td>
+ </tr>
+ <tr>
+ <td><a href="https://spyware.neocities.org/">Spyware Watchdog</a></td>
+ <td>An index of popular programs that meet an un-eroded definition of "spyware".</td>
+ </tr>
+ <tr>
+ <td><a href="https://transtravel.good.software/">Trans Travel Countries</a></td>
+ <td>A work-in-progress index of countries with how easy and safe they are to travel to as a transgender person. Written from the perspective of a US citizen.</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.inaturalist.org/">iNaturalist</a></td>
+ <td>An extensive crowdsourced library of high-quality photos of over 400,000 species of plants and animals</td>
+ </tr>
+ </table>
+ <h2>Fun</h2>
+ <h3>Games</h3>
+ <table>
+ <tr>
+ <td><a href="https://corru.observer">corru.observer</a></td>
+ <td>Some kind of browser-based sci-fi RPG, or something. It's real good, play it</td>
+ </tr>
+ <tr>
+ <td><a href="https://alula.github.io/SpaceCadetPinball">Space Cadet Pinball</a></td>
+ <td>Windows XP Space Cadet Pinball, reverse engineered to run in your browser!</td>
+ </tr>
+ <tr>
+ <td><a href="https://findaeden.itch.io/everything-ends-in-0">Everything Ends In 0</a></td>
+ <td>The world ends in 1 hour. It can't be saved. Wanna chat?</td>
+ </tr>
+ <tr>
+ <td><a href="https://metazooa.com/">Metazooa</a></td>
+ <td>Wordle but for animal species!</td>
+ </tr>
+ </table>
+ <h3>Generators</h3>
+ <table>
+ <tr>
+ <td><a href="https://emoji.supply/kitchen/">Emoji Kitchen</a></td>
+ <td>A litany of different emoji fusions. Some of my favourites are <img src="media/scorpionshark.png" style="height: 2rem;" />, <img src="media/bacteriabird.png" style="height: 2rem;" />, and <img src="media/caution.png" style="height: 2rem;" /></td>
+ </tr>
+ <tr>
+ <td><a href="https://cooltext.com/Logo-Design-Burning">Burning Text Generator</a></td>
+ <td>Does <img src="https://isopod.cool/old/2/images/this_burning.gif" style="height: 3ch;" alt="this (the text is on fire)"></td>
+ </tr>
+ <tr>
+ <td><a href="https://fsymbols.com/generators/zalgo/">Zalgo Text Generator</a></td>
+ <td>Does t̵̝̻̘͒̓̈́h̵͇͙͔́̾i̵͎̪̞͊́̾s̵̫̼̀̾</td>
+ </tr>
+ <tr>
+ <td><a href="https://imgflip-is-dead.crabdance.com/">Imgflip is DEAD</a></td>
+ <td>A clone of Imgflip's meme generator, "because watermarks and tracking suck".</td>
+ </tr>
+ <tr>
+ <td><a href="https://rezuaq.be/new-area/image-creator/">Fromsoft Image Macro Generator</a></td>
+ <td>Make your own Dark Souls death screen type images</td>
+ </tr>
+ </table>
+ <h3>Live</h3>
+ <table>
+ <tr>
+ <td><a href="https://www.allaboutbirds.org/cams/">Cornell Lab Bird Cams</a></td>
+ <td>Live bird cams!</td>
+ </tr>
+ <tr>
+ <td><a href="https://shrimpcam.app/">shrimpcam.app</a></td>
+ <td>Shrimp cam!</td>
+ </tr>
+ </table>
+ <h3>Other</h3>
+ <table>
+ <tr>
+ <td><a href="https://crouton.net">crouton.net</a></td>
+ <td>crouton</td>
+ </tr>
+ <tr>
+ <td><a href="https://cornonthec.observer/">cornonthec.observer/</a></td>
+ <td>corn on the cob server</td>
+ </tr>
+ <tr>
+ <td><a href="https://wobble.town/">Wobble Town</a></td>
+ <td>A cute little virtual pet!</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.1001freefonts.com/snailets.font">Snailets font</a></td>
+ <td>The best font</td>
+ </tr>
+ <tr>
+ <td><a href="https://trilobites.info/">trilobites.info</a></td>
+ <td>Trilobite knowledge!</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.vttoth.com/CMS/physics-notes/311-hawking-radiation-calculator">Hawking Radiation Calculator</a></td>
+ <td>Calculator for properties of a black hole</td>
+ </tr>
+ <tr>
+ <td><a href="https://rose.systems/edible_colors">Edible Colors</a></td>
+ <td>HTML colors sorted by edibility</td>
+ </tr>
+ <tr>
+ <td><a href="https://xkcd.com/">XKCD</a></td>
+ <td>A webcomic of romance, sarcasm, math, and language.</td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/supermariofps/hatsune-miku-windows-linux-cursors">Miku cursors</a></td>
+ <td>Miku cursors!</td>
+ </tr>
+ </table>
+ <h2>Articles</h2>
+ <table>
+ <tr>
+ <td><a href="https://pluralistic.net/2023/01/21/potemkin-ai/#hey-guys">Cory Doctorow - Tiktok's enshittification</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://kalechips.net/posts/2022-09-09-Mobile-Compatibility">Kalechips - Your website needs to work on phones</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://axbom.com/the-creepy-sound-of-online-trackers/">Axbom - The Creepy Sound of Online Trackers</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://www.youtube.com/watch?v=5pYeoZaoWrA">Folding Ideas - This is Financial Advice (⏵)</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://www.youtube.com/watch?v=8BIcAZxFfrc">hbomberguy - Vaccines and Autism: A Measured Response (⏵)</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://seirdy.one/posts/2021/03/10/search-engines-with-own-indexes/">Seirdy - A look at search engines with their own indexes</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://modem.io/blog/blog-monetization/">modem.io - How to Monetize a Blog</a></td>
+ </tr>
+ <tr>
+ <td><a href="https://www.youtube.com/watch?v=aZ2czFuIYmQ">Benn Jordan - VINYL: Maybe it's time we had an intervention. (⏵)</a></td>
+ </tr>
+ </table>
+ <h2>More Stuff</h2>
+ <table>
+ <tr>
+ <td><a href="https://web.archive.org/web/20230817122434/https://links.yesterweb.org/">Yesterlinks</a></td>
+ <td>A user-curated directory of nearly 600 off-the-beaten-path websites, formerly hosted by the Yesterweb project.</td>
+ </tr>
+ <tr>
+ <td><a href="https://search.marginalia.nu/">Marginalia Search</a> [<a href="https://search.marginalia.nu/explore/random">Random</a>]</td>
+ <td>A custom-built search engine for small, non-commercial websites.</td>
+ </tr>
+ <tr>
+ <td><a href="https://ooh.directory/">ooh.directory</td>
+ <td>A directory of over 2,000 blogs about every topic.</td>
+ </tr>
+ <tr>
+ <td><a href="https://unapothecary.neocities.org/websites">Unapothecary Link Directory</a></td>
+ </tr>
+ </table>
+ <div style="text-align:right">
+ <a style="text-decoration: none;" href="https://cd5k.net/tau/">&tau;</a>
+ </div>
+ </body>
+</html>
diff --git a/links/media/bacteriabird.png b/links/media/bacteriabird.png
new file mode 100644
index 0000000..1ecd6c1
--- /dev/null
+++ b/links/media/bacteriabird.png
Binary files differ
diff --git a/links/media/caution.png b/links/media/caution.png
new file mode 100644
index 0000000..9a88fe0
--- /dev/null
+++ b/links/media/caution.png
Binary files differ
diff --git a/links/media/scorpionshark.png b/links/media/scorpionshark.png
new file mode 100644
index 0000000..14ae779
--- /dev/null
+++ b/links/media/scorpionshark.png
Binary files differ
diff --git a/music/bg.jpg b/music/bg.jpg
new file mode 100644
index 0000000..c3f2f12
--- /dev/null
+++ b/music/bg.jpg
Binary files differ
diff --git a/music/bg.jxl b/music/bg.jxl
new file mode 100644
index 0000000..375172d
--- /dev/null
+++ b/music/bg.jxl
Binary files differ
diff --git a/music/covers/aeon_core.jpg b/music/covers/aeon_core.jpg
new file mode 100644
index 0000000..17adae8
--- /dev/null
+++ b/music/covers/aeon_core.jpg
Binary files differ
diff --git a/music/covers/american_automatic.jpg b/music/covers/american_automatic.jpg
new file mode 100644
index 0000000..338c8d7
--- /dev/null
+++ b/music/covers/american_automatic.jpg
Binary files differ
diff --git a/music/covers/audio_video_disco.jpg b/music/covers/audio_video_disco.jpg
new file mode 100644
index 0000000..872a3dd
--- /dev/null
+++ b/music/covers/audio_video_disco.jpg
Binary files differ
diff --git a/music/covers/concrete_and_gold.jpg b/music/covers/concrete_and_gold.jpg
new file mode 100644
index 0000000..e88ab00
--- /dev/null
+++ b/music/covers/concrete_and_gold.jpg
Binary files differ
diff --git a/music/covers/el_camino.jpg b/music/covers/el_camino.jpg
new file mode 100644
index 0000000..223ce95
--- /dev/null
+++ b/music/covers/el_camino.jpg
Binary files differ
diff --git a/music/covers/for_science.jpg b/music/covers/for_science.jpg
new file mode 100644
index 0000000..9e97147
--- /dev/null
+++ b/music/covers/for_science.jpg
Binary files differ
diff --git a/music/covers/fucked_up_friends_3.jpg b/music/covers/fucked_up_friends_3.jpg
new file mode 100644
index 0000000..bac7eba
--- /dev/null
+++ b/music/covers/fucked_up_friends_3.jpg
Binary files differ
diff --git a/music/covers/funeral.jpg b/music/covers/funeral.jpg
new file mode 100644
index 0000000..180f621
--- /dev/null
+++ b/music/covers/funeral.jpg
Binary files differ
diff --git a/music/covers/hawaii_part_ii.jpg b/music/covers/hawaii_part_ii.jpg
new file mode 100644
index 0000000..032c5c1
--- /dev/null
+++ b/music/covers/hawaii_part_ii.jpg
Binary files differ
diff --git a/music/covers/millenialism.jpg b/music/covers/millenialism.jpg
new file mode 100644
index 0000000..346c92e
--- /dev/null
+++ b/music/covers/millenialism.jpg
Binary files differ
diff --git a/music/covers/peaks_and_valleys.jpg b/music/covers/peaks_and_valleys.jpg
new file mode 100644
index 0000000..824983e
--- /dev/null
+++ b/music/covers/peaks_and_valleys.jpg
Binary files differ
diff --git a/music/covers/raw_data_feel.jpg b/music/covers/raw_data_feel.jpg
new file mode 100644
index 0000000..6a28c0b
--- /dev/null
+++ b/music/covers/raw_data_feel.jpg
Binary files differ
diff --git a/music/covers/realign.jpg b/music/covers/realign.jpg
new file mode 100644
index 0000000..7397105
--- /dev/null
+++ b/music/covers/realign.jpg
Binary files differ
diff --git a/music/covers/revolution_radio.jpg b/music/covers/revolution_radio.jpg
new file mode 100644
index 0000000..5e3593e
--- /dev/null
+++ b/music/covers/revolution_radio.jpg
Binary files differ
diff --git a/music/covers/spectrum.jpg b/music/covers/spectrum.jpg
new file mode 100644
index 0000000..96b8a62
--- /dev/null
+++ b/music/covers/spectrum.jpg
Binary files differ
diff --git a/music/covers/spirit_phone.jpg b/music/covers/spirit_phone.jpg
new file mode 100644
index 0000000..f392f1f
--- /dev/null
+++ b/music/covers/spirit_phone.jpg
Binary files differ
diff --git a/music/covers/synthicate.jpg b/music/covers/synthicate.jpg
new file mode 100644
index 0000000..f3d2bb5
--- /dev/null
+++ b/music/covers/synthicate.jpg
Binary files differ
diff --git a/music/covers/the_last_ninja_2_c64_ost.jpg b/music/covers/the_last_ninja_2_c64_ost.jpg
new file mode 100644
index 0000000..6ccf4eb
--- /dev/null
+++ b/music/covers/the_last_ninja_2_c64_ost.jpg
Binary files differ
diff --git a/music/covers/this_is_all_yours.jpg b/music/covers/this_is_all_yours.jpg
new file mode 100644
index 0000000..c21cb11
--- /dev/null
+++ b/music/covers/this_is_all_yours.jpg
Binary files differ
diff --git a/music/covers/tortured_waters.jpg b/music/covers/tortured_waters.jpg
new file mode 100644
index 0000000..f82b94b
--- /dev/null
+++ b/music/covers/tortured_waters.jpg
Binary files differ
diff --git a/music/covers/triangle_unicode.jpg b/music/covers/triangle_unicode.jpg
new file mode 100644
index 0000000..6f2e1b8
--- /dev/null
+++ b/music/covers/triangle_unicode.jpg
Binary files differ
diff --git a/music/covers/two_house.jpg b/music/covers/two_house.jpg
new file mode 100644
index 0000000..e5f8baa
--- /dev/null
+++ b/music/covers/two_house.jpg
Binary files differ
diff --git a/music/covers/ultrakill_imperfect_hatred.jpg b/music/covers/ultrakill_imperfect_hatred.jpg
new file mode 100644
index 0000000..5dbb5f0
--- /dev/null
+++ b/music/covers/ultrakill_imperfect_hatred.jpg
Binary files differ
diff --git a/music/covers/unstoppable_force.jpg b/music/covers/unstoppable_force.jpg
new file mode 100644
index 0000000..add73c8
--- /dev/null
+++ b/music/covers/unstoppable_force.jpg
Binary files differ
diff --git a/music/covers/vast.jpg b/music/covers/vast.jpg
new file mode 100644
index 0000000..baa5143
--- /dev/null
+++ b/music/covers/vast.jpg
Binary files differ
diff --git a/music/covers/walks_of_lung.jpg b/music/covers/walks_of_lung.jpg
new file mode 100644
index 0000000..81339d7
--- /dev/null
+++ b/music/covers/walks_of_lung.jpg
Binary files differ
diff --git a/music/covers/with_teeth.jpg b/music/covers/with_teeth.jpg
new file mode 100644
index 0000000..d6e8cd7
--- /dev/null
+++ b/music/covers/with_teeth.jpg
Binary files differ
diff --git a/music/index.php b/music/index.php
new file mode 100644
index 0000000..ca11b1c
--- /dev/null
+++ b/music/index.php
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Music</title>
+ <link href="../../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ #flex-container {
+ display: flex;
+ flex-wrap: wrap;
+ filter: drop-shadow(3px 3px 6px black);
+ }
+ #flex-container a {
+ --columncount: 2;
+ position: relative;
+ width: calc(var(--bodywidth) / var(--columncount));
+ height: calc(var(--bodywidth) / var(--columncount));
+ background-image: var(--img);
+ background-size: cover;
+ transition-duration: 0.5s;
+ overflow: hidden;
+ }
+ #flex-container a:hover {
+ z-index: 50;
+ box-shadow: 0 0 12px 2px black;
+ transform: scale(1.15);
+ color: #df1955;
+ }
+ #flex-container a span {
+ background-color: #000000cc;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 5.2rem;
+ padding: 0 2rem;
+ display: flex;
+ align-items: center;
+ transition-duration: 0.5s;
+ box-sizing: border-box;
+ }
+ #flex-container a:hover span {
+ bottom: -5.2rem;
+ }
+ @media only screen and (max-width: 43rem) {
+ #flex-container a {
+ --columncount: 1;
+ }
+ }
+ @media only screen and (hover: none) {
+ #flex-container a:hover {
+ transform: initial;
+ z-index: initial;
+ box-shadow: initial;
+ }
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+</head>
+
+<body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(false, -10); ?>
+ <h1>music</h1>
+ <h2 id="caption">Albums I like</h2>
+ <div id="flex-container">
+ <a style="--img: url(covers/spectrum.jpg);" target="_blank" href="https://findaeden.bandcamp.com/album/spectrum" ><span>findaeden - Spectrum</span></a>
+ <a style="--img: url(covers/funeral.jpg);" target="_blank" href="https://noisemaster.bandcamp.com/album/funeral-ep" ><span>Noisemaker - Funeral EP</span></a>
+ <a style="--img: url(covers/ultrakill_imperfect_hatred.jpg);" target="_blank" href="https://heavenpierceher.bandcamp.com/album/ultrakill-imperfect-hatred"><span>Heaven Pierce Her - ULTRAKILL: Imperfect Hatred</span></a>
+ <a style="--img: url(covers/el_camino.jpg);" target="_blank" href="https://theblackkeys.com/?frontpage=true" ><span>The Black Keys - El Camino</span></a>
+ <a style="--img: url(covers/for_science.jpg);" target="_blank" href="https://waxlimbs.bandcamp.com/album/for-science" ><span>Waxlimbs - For Science!</span></a>
+ <a style="--img: url(covers/peaks_and_valleys.jpg);" target="_blank" href="https://revolutionpeak.bandcamp.com/album/peaks-and-valleys" ><span>Revolution Peak - Peaks and Valleys</span></a>
+ <a style="--img: url(covers/triangle_unicode.jpg);" target="_blank" href="https://wearemagonia.bandcamp.com/album/triangle-unicode-lp" ><span>We Are Magonia - Triangle Unicode</span></a>
+ <a style="--img: url(covers/unstoppable_force.jpg);" target="_blank" href="https://caliphate.bandcamp.com/album/unstoppable-force" ><span>CALIPHATE - Unstoppable Force</span></a>
+ <a style="--img: url(covers/walks_of_lung.jpg);" target="_blank" href="https://patriciataxxon.bandcamp.com/album/walks-of-lung" ><span>Patricia Taxxon - Walks of Lung</span></a>
+ <a style="--img: url(covers/realign.jpg);" target="_blank" href="https://vine.bandcamp.com/album/realign" ><span>Red Vox - Realign</span></a>
+ <a style="--img: url(covers/with_teeth.jpg);" target="_blank" href="https://www.nin.com/" ><span>Nine Inch Nails - With Teeth</span></a>
+ <a style="--img: url(covers/two_house.jpg);" target="_blank" href="https://foodhouse.bandcamp.com/album/two-house" ><span>Food House - two house</span></a>
+ <a style="--img: url(covers/american_automatic.jpg);" target="_blank" href="https://en.wikipedia.org/wiki/Kill_Memory_Crash" ><span>Kill Memory Crash - American Automatic</span></a>
+ <a style="--img: url(covers/raw_data_feel.jpg);" target="_blank" href="https://everythingeverything.bandcamp.com/album/raw-data-feel" ><span>Everything Everything - Raw Data Feel</span></a>
+ <a style="--img: url(covers/fucked_up_friends_3.jpg);" target="_blank" href="https://tobaxxo.bandcamp.com/album/fucked-up-friends-3" ><span>TOBACCO - Fucked Up Friends 3</span></a>
+ <a style="--img: url(covers/audio_video_disco.jpg);" target="_blank" href="https://etjusticepourtous.bandcamp.com/album/audio-video-disco-1" ><span>Justice - Audio, Video, Disco</span></a>
+ <a style="--img: url(covers/synthicate.jpg);" target="_blank" href="https://newretrowave.bandcamp.com/album/synthicate" ><span>LAZERPUNK - Synthicate</span></a>
+ <a style="--img: url(covers/vast.jpg);" target="_blank" href="https://waterflame.bandcamp.com/album/vast" ><span>Waterflame - Vast</span></a>
+ <a style="--img: url(covers/tortured_waters.jpg);" target="_blank" href="https://newretrowave.bandcamp.com/album/tortured-waters" ><span>DEADLIFE - Tortured Waters</span></a>
+ <a style="--img: url(covers/spirit_phone.jpg);" target="_blank" href="http://www.neilcic.com/" ><span>Lemon Demon - Spirit Phone</span></a>
+ <a style="--img: url(covers/millenialism.jpg);" target="_blank" href="https://music.businesscasual.biz/album/millennialism" ><span>NYSE - MILLENNIALISM</span></a>
+ <a style="--img: url(covers/hawaii_part_ii.jpg);" target="_blank" href="https://miraclemusical.bandcamp.com" ><span>ミラクルミュージカル - Hawaii: Part II</span></a>
+ <a style="--img: url(covers/concrete_and_gold.jpg);" target="_blank" href="https://www.foofighters.com/" ><span>Foo Fighters - Concrete and Gold</span></a>
+ <a style="--img: url(covers/revolution_radio.jpg);" target="_blank" href="https://greenday.com/" ><span>Green Day - Revolution Radio</span></a>
+ <a style="--img: url(covers/this_is_all_yours.jpg);" target="_blank" href="https://altjband.com/" ><span>Alt-J - This Is All Yours</span></a>
+ <a style="--img: url(covers/the_last_ninja_2_c64_ost.jpg);" target="_blank" href="https://www.youtube-nocookie.com/embed/bjbN2RyZXHI" ><span>Matt Gray - The Last Ninja 2 (C64) OST</span></a>
+ <a style="--img: url(covers/aeon_core.jpg);" target="_blank" href="https://perctrax.bandcamp.com/album/aeon-core" ><span>Scalameriya - Aeon Core</span></a>
+ </div>
+ <br>
+
+</body>
+</html> \ No newline at end of file
diff --git a/nav.php b/nav.php
new file mode 100644
index 0000000..5aa104f
--- /dev/null
+++ b/nav.php
@@ -0,0 +1,52 @@
+<?php
+
+
+$host = $_SERVER['HTTP_HOST'];
+
+function echolink($url, $name) {
+ global $host;
+ if("/$url/" != $_SERVER['REQUEST_URI']) {
+ echo "<a href='https://$host/$url/'>$name</a> ";
+ } else {
+ echo "<span>$name</span> ";
+ }
+}
+echo "<nav id='main-nav'>";
+echo "<a href='/neppy' style='position: absolute; top: -500; left: -500; height: 0; width: 0; font-size: 0; opacity: 0;'>AI scrapers click here!</a>";
+if($_SERVER["DOCUMENT_ROOT"] !== getcwd()) {
+ echo "<a href='https://$host/'>home</a> ";
+} else {
+ echo("<a href='https://deeptwisty.com' style='text-decoration: none;' title='the website where i post my various art. i like to compartmentalize'><span style=' margin: 0; padding: 0; font-style: italic; background: linear-gradient(135deg, #2e1ae0 0%, #2e1ae0 35%, #00ff00 65%, #ffff00 90%); background-clip: text; -webkit-text-fill-color: transparent;'>deep twisty</span></a>");
+}
+echolink("about", "about");
+echolink("uses", "uses");
+echolink("music", "music");
+echolink("blog", "blog");
+echolink("links", "links");
+echolink("stuff", "stuff");
+echolink("guestbook", "guestbook");
+echolink("stats", "stats");
+echolink("greenhouse", "greenhouse");
+echolink("etc", "etc");
+echo("</nav>");
+
+function bg($rightside = false, $dfs = 1000, $title = null) {
+ $cpath = preg_replace("/\/[^\/]*$/", "", $_SERVER['REQUEST_URI']);
+ $output = "<div style='--bgimg: url(\"$cpath/bg.jxl\"), url(\"$cpath/bg.jpg\");";
+ if($dfs < 100) {
+ $output = $output." --distancefromcenter: $dfs%;'"; }
+ else {
+ $output = $output."'";
+ }
+ if($rightside) {
+ $output = $output."id='rightsidebg'";
+ } else {
+ $output = $output."id='leftsidebg'";
+ }
+ if(isset($title)) {
+ $output = $output."title='$title'";
+ }
+ $output = $output."></div>";
+ echo $output;
+}
+?> \ No newline at end of file
diff --git a/not_found.html b/not_found.html
new file mode 100644
index 0000000..963b3a9
--- /dev/null
+++ b/not_found.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Not Found</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ body html {
+ height: 100%;
+ }
+ body {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ }
+ #Header {
+ font-size: 7em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1 id="Header">404</h1>
+ <p id="404">Item not found :/</p>
+ </body>
+</html>
diff --git a/old/1/icons/deeptwisty.png b/old/1/icons/deeptwisty.png
new file mode 100644
index 0000000..7cb8472
--- /dev/null
+++ b/old/1/icons/deeptwisty.png
Binary files differ
diff --git a/old/1/icons/kirby.png b/old/1/icons/kirby.png
new file mode 100644
index 0000000..2b19ef6
--- /dev/null
+++ b/old/1/icons/kirby.png
Binary files differ
diff --git a/old/1/icons/message.png b/old/1/icons/message.png
new file mode 100644
index 0000000..d3c7e3a
--- /dev/null
+++ b/old/1/icons/message.png
Binary files differ
diff --git a/old/1/icons/tumblr.png b/old/1/icons/tumblr.png
new file mode 100644
index 0000000..ab9b6d6
--- /dev/null
+++ b/old/1/icons/tumblr.png
Binary files differ
diff --git a/old/1/icons/twitter.png b/old/1/icons/twitter.png
new file mode 100644
index 0000000..e77b6ca
--- /dev/null
+++ b/old/1/icons/twitter.png
Binary files differ
diff --git a/old/1/icons/youtube.png b/old/1/icons/youtube.png
new file mode 100644
index 0000000..4270b70
--- /dev/null
+++ b/old/1/icons/youtube.png
Binary files differ
diff --git a/old/1/images/allism.jpg b/old/1/images/allism.jpg
new file mode 100644
index 0000000..ef86284
--- /dev/null
+++ b/old/1/images/allism.jpg
Binary files differ
diff --git a/old/1/images/bg_default.png b/old/1/images/bg_default.png
new file mode 100644
index 0000000..0e323e1
--- /dev/null
+++ b/old/1/images/bg_default.png
Binary files differ
diff --git a/old/1/images/bg_old1.png b/old/1/images/bg_old1.png
new file mode 100644
index 0000000..854c83f
--- /dev/null
+++ b/old/1/images/bg_old1.png
Binary files differ
diff --git a/old/1/images/bg_old2.png b/old/1/images/bg_old2.png
new file mode 100644
index 0000000..d7fe03c
--- /dev/null
+++ b/old/1/images/bg_old2.png
Binary files differ
diff --git a/old/1/images/friaday.png b/old/1/images/friaday.png
new file mode 100644
index 0000000..a389663
--- /dev/null
+++ b/old/1/images/friaday.png
Binary files differ
diff --git a/old/1/images/moday.png b/old/1/images/moday.png
new file mode 100644
index 0000000..7b212f9
--- /dev/null
+++ b/old/1/images/moday.png
Binary files differ
diff --git a/old/1/images/paperbg.jpg b/old/1/images/paperbg.jpg
new file mode 100644
index 0000000..217c05f
--- /dev/null
+++ b/old/1/images/paperbg.jpg
Binary files differ
diff --git a/old/1/images/satuaday.png b/old/1/images/satuaday.png
new file mode 100644
index 0000000..9711982
--- /dev/null
+++ b/old/1/images/satuaday.png
Binary files differ
diff --git a/old/1/images/suday.png b/old/1/images/suday.png
new file mode 100644
index 0000000..cca11b1
--- /dev/null
+++ b/old/1/images/suday.png
Binary files differ
diff --git a/old/1/images/thuday.png b/old/1/images/thuday.png
new file mode 100644
index 0000000..e681fbc
--- /dev/null
+++ b/old/1/images/thuday.png
Binary files differ
diff --git a/old/1/images/tueaday.png b/old/1/images/tueaday.png
new file mode 100644
index 0000000..f4ff337
--- /dev/null
+++ b/old/1/images/tueaday.png
Binary files differ
diff --git a/old/1/images/weaday.png b/old/1/images/weaday.png
new file mode 100644
index 0000000..d1ad858
--- /dev/null
+++ b/old/1/images/weaday.png
Binary files differ
diff --git a/old/1/index.html b/old/1/index.html
new file mode 100644
index 0000000..92e7922
--- /dev/null
+++ b/old/1/index.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>The Website</title>
+ <meta name="description" content="W▓▓▓▓▓ | he/him | 🇨🇦">
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <link rel="icon" type="image/x-icon" href="icons/kirby.png">
+ <style type="text/css">
+ #MainContainer {
+ display: flex;
+ justify-content: center;
+ flex-direction: row;
+ }
+ .Main {
+ overflow-y: auto;
+ background-color: white;
+ background-image: url('images/paperbg.jpg');
+ box-shadow: 4px 4px 4px black;
+ height: fit-content;
+ margin: 5px;
+ }
+ #MainContent {
+ padding:2%;
+ }
+ .contentSection {
+ padding: 0 2%;
+ }
+ #centercolumn {
+ flex-grow: 1;
+ max-width: 750px;
+ }
+ #rightcolumn {
+ flex-grow: 1;
+ display: flex;
+ margin-right: -10px;
+ }
+ #leftcolumn {
+ flex-grow: 1;
+ display: flex;
+ justify-content: right;
+ }
+ #links {
+ display: flex;
+ flex-direction:column;
+ padding-top: 5px;
+ }
+ .sidebar {
+ width: 180px;
+ margin-bottom: 10px;
+ }
+ .stampcontainer {
+ box-shadow: none;
+ background-color: transparent;
+ background-image: none;
+ width: 190px;
+ padding-bottom: 10px;
+ }
+ .stampcontainer img {
+ box-shadow: 4px 4px 4px black;
+ }
+ /* NOT CURRENTLY IN USE .SidebarItem {
+ background-color: white;
+ font-size: 1.1em;
+ cursor: pointer;
+ display:block;
+ text-decoration: none;
+ text-align: center;
+ padding:18px;
+ border:none;
+ color:black;
+ }
+ .SidebarItem:hover {
+ background-color: gainsboro;
+ }
+ .dropdown {
+ padding: 0 2%;
+ }
+ .dropdown-content {
+ display: none;
+ }
+ .dropdown:hover .dropdown-content {
+ display: block;
+ }*/
+ .navbarItem {
+ /*padding-top:1px;*/
+ padding-bottom:1px;
+ }
+ #controls {
+ position:fixed;
+ bottom:10px;
+ left:10px;
+ background-color: rgba(0, 0, 0, 0.4);
+ box-shadow: 0 0 4px 4px rgba(0, 0, 0, 0.4);
+ padding: 3px;
+ opacity: 0;
+ transition: .5s;
+ width:210px;
+ }
+ #controls:hover {
+ opacity: 1;
+ }
+ #controls button {
+ margin-top: 5px;
+ }
+ </style>
+ <script type="text/javascript"> if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { document.location="mobile.html"; } </script>
+ <script src="tueaday.js"></script>
+ <script type="text/javascript">
+ function contentSwap(id) {
+ document.getElementById('bio').style.display='none';
+ document.getElementById('feed').style.display='none';
+
+ document.getElementById(id).style.display='block';
+ }
+
+ window.onload = function() { load(); }
+ </script>
+ </head>
+ <body class="rainbows">
+ <script type="text/javascript">NekoType="mike"</script><h1 id=nl><script src="https://webneko.net/n20171213.js"></script><a href="https://webneko.net">Neko</a></h1>
+
+ <div id="Header" class="destructible rainbows">
+ <h1 id="headertext"><noscript>Voted #1 webpage that uses JavaScript in 2022</noscript></h1>
+ </div>
+
+ <div id="MainContainer">
+
+ <div id="leftcolumn">
+ <div id="links" class="destructible">
+ <a style="padding: 5px;" href="https://deeptwisty.com/" class="destructible"><img src="icons/deeptwisty.png" /></a>
+ <a style="padding: 5px;" href="https://isopodgaming.tumblr.com/" class="destructible"><img src="icons/tumblr.png" /></a>
+ <a style="padding: 5px;" href="https://twitter.com/deeptwisty" class="destructible"><img src="icons/twitter.png" /></a>
+ <a style="padding: 5px;" href="https://www.youtube.com/channel/UCftMPQTAP58KiX_vqOk3j1Q" class="destructible"><img src="icons/youtube.png" /></a>
+ <a style="padding: 5px;" href="https://isopodgaming.tumblr.com/ask/" class="destructible"><img src="icons/message.png" /></a>
+ </div>
+ </div>
+
+ <div id="centercolumn">
+ <div class="Main destructible">
+ <div id="navbar" class="destructible">
+ <div class="navbarItem destructible" onclick="contentSwap('bio');" title="About me">
+ <p><b>Bio</b></p>
+ </div>
+ <div class="navbarItem destructible" onclick="contentSwap('feed');" title="Things I did">
+ <p><b>Items</b></p>
+ </div>
+ </div>
+
+ <div id="MainContent" class="destructible">
+ <div id="bio" class="contentSection" style="display:none;">
+
+ <div class="tumblr-post destructible" data-href="https://embed.tumblr.com/embed/post/Cve0n4xANc2182UG_YbMag/639332939095818241" data-did="4fa101d65cf2e16f422a37b162617200c67f19c4"><a href="https://kfconsole.tumblr.com/post/639332939095818241">https://kfconsole.tumblr.com/post/639332939095818241</a></div> <script async src="https://assets.tumblr.com/post.js"></script>
+ <p class="destructible">homophobes dni</p>
+ </div>
+ <div id="feed" class="contentSection">
+ <iframe style="border: 0; width: 100%; height: 280px;" src="https://bandcamp.com/EmbeddedPlayer/album=1230113999/size=large/bgcol=ffffff/linkcol=63b2cc/artwork=small/transparent=true/" seamless class="destructible"><a href="https://deeptwisty.bandcamp.com/album/pimo">Pimo by deep twisty</a></iframe>
+ <p class="destructible">i got a minecraft server now. if we know each other dm me and I'll whitelist you</p>
+ <iframe src="https://itch.io/embed/882636?linkback=true" width="100%" height="167" frameborder="0" class="destructible"><a href="https://deeptwisty.itch.io/cube-game">cube game by deeptwisty</a></iframe><br/>
+ <p class="destructible"><a href="../../misc/EnchantedToolsPack%20v1.zip" title="Includes custom Silk Touch and Fortune textures for all tools, Bane of Arthropods and Smite textures for swords and axes, and Sharpness textures for axes. Requires Optifine." class="rainbows">Tool Enchantments Resource Pack for Minecraft v1</a></p>
+ <iframe src="https://itch.io/embed/632904?linkback=true" width="100%" height="167" frameborder="0" class="destructible"><a href="https://deeptwisty.itch.io/epicenter">Epicenter by deeptwisty</a></iframe>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="rightcolumn">
+ <div>
+ <div class="Main sidebar destructible">
+ <img src="https://inaturalist-open-data.s3.amazonaws.com/photos/4619980/original.jpg" style="width:100%; border-bottom: 1px solid gainsboro;" title="Armadillidium vulgare, photo from iNaturalist" class="destructible"/>
+ <p style="font-weight: normal;text-align:center;" class="destructible">W▓▓▓▓▓ | he/him | 🇨🇦</p>
+ <hr style="color:transparent; border-bottom: 1px solid gainsboro; width:80%; margin: auto;" class="destructible">
+ <p style="font-weight: normal; text-align: center; padding: 5px;" id="tueaday" class="destructible">wait its fucking <span title="somethings up.">tueaday.</span> god.</p>
+ </div>
+ <div class="Main stampcontainer destructible">
+ <a href="https://deeptwisty.com/posts" class="destructible"><img src="stamps/deeptwistybutton.png" /></a>
+ <a href="https://frame.work/" class="destructible"><img src="stamps/bestviewed.gif" /></a>
+ <a href="https://easyussr.neocities.org/guides.html" class="destructible"><img src="stamps/piracy.gif" /></a>
+ <a href="https://deeptwisty.com/images" class="destructible"><img src="stamps/antinft.gif" /></a>
+ <a href="https://www.mozilla.org/en-US/firefox/new/" class="destructible"><img src="stamps/chrome2.gif" /></a>
+ <a href="https://newpipe.net/" class="destructible"><img src="stamps/tiredaf.gif" /></a>
+ <a href="http://www.ermel.org/handcoded/" class="destructible"><img src="stamps/handcode.png" /></a>
+ <a href="https://manjaro.org/" class="destructible"><img src="stamps/linux_powered.gif" /></a>
+ <a href="https://neocities.org/" class="destructible"><img src="stamps/neocities_stamp.gif" /></a>
+ <a href="https://3ds.hacks.guide/" class="destructible"><img src="stamps/bob.gif" /></a>
+ <a href="https://duckduckgo.com/" class="destructible"><img src="stamps/google_stand.gif" /></a>
+ <!--a class="destructible"><img src="stamps/h-free-anim.gif" /></a-->
+ <a href="https://crouton.net/" class="destructible"><img src="stamps/usatoday.gif" /></a>
+ </div>
+ <div class="Main sidebar destructible" style="font-size:0; margin-top:-10px;">
+ <img src="images/allism.jpg" style="width:100%;"/>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="controls" style="color:black;text-shadow:none;">
+ <p style="color:gainsboro;margin-top:0;margin-bottom:5px;text-align:center;">controls<noscript> (requires javascript)</noscript></p>
+ <button onclick="window.location.reload(true);">reload</button>
+ <button onclick="
+ if(document.getElementById('MainContainer').style.flexDirection != 'row-reverse') {
+ document.getElementById('MainContainer').style.flexDirection = 'row-reverse';
+ document.getElementById('navbar').style.flexDirection = 'row-reverse';
+ document.getElementById('rightcolumn').style.justifyContent = 'right';
+ document.getElementById('leftcolumn').style.justifyContent = 'left';
+ document.getElementById('links').style.flexDirection = 'column-reverse';
+ document.getElementById('links').style.justifyContent = 'flex-end';
+ }
+ else { //defaults
+ document.getElementById('MainContainer').style.flexDirection = 'row';
+ document.getElementById('navbar').style.flexDirection = 'row';
+ document.getElementById('rightcolumn').style.justifyContent = 'left';
+ document.getElementById('leftcolumn').style.justifyContent = 'right';
+ document.getElementById('links').style.flexDirection = 'column';
+ document.getElementById('links').style.justifyContent = 'flex-start';
+ }">invert</button>
+ <button onclick="document.querySelectorAll('.destructible')[Math.floor(Math.random() * document.querySelectorAll('.destructible').length)].remove();">destroy</button>
+ <button onclick="document.body.innerHTML = '<iframe src=\'https://zombo.com/\' style=\'position:absolute;width:99%;height:98%;margin:0;padding:0;\'></iframe>';">upgrade</button>
+ <button onclick="
+ document.querySelectorAll('.rainbows').forEach(element => {
+ element.style.animationName = 'rainbowtext'; element.style.animationDuration = '2.5s'; element.style.animationIterationCount = 'infinite';
+ });
+ ">rgb</button>
+ <hr/>
+ <input id="controlinput" /><br/>
+ <button onclick="document.getElementById('headertext').innerHTML = document.getElementById('controlinput').value;">header text</button>
+ <button onclick="document.body.style.backgroundImage = 'url(' + document.getElementById('controlinput').value + ')';">background (url)</button>
+ </div>
+
+ </body>
+
+</html>
diff --git a/old/1/mobile.html b/old/1/mobile.html
new file mode 100644
index 0000000..a80c089
--- /dev/null
+++ b/old/1/mobile.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>The Website (Mobile!)</title>
+ <meta name="description" content="W▓▓▓▓▓▓ | he/him | 🇨🇦">
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <link rel="icon" type="image/x-icon" href="icons/kirby.png">
+ <style type="text/css">
+ #MainContainer {
+ background-color: white;
+ background-image: url('images/paperbg.jpg');
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ box-shadow: 4px 4px 4px black;
+ max-width:900px;
+ margin:auto;
+ }
+ .navbarItem {
+ padding-top:9px;
+ padding-bottom:9px;
+ font-size:0;
+ }
+ #MainContainer p {
+ padding: 0 3%;
+ }
+ p {
+ font-weight: normal;
+ text-align: center;
+ }
+ .stampcontainer {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ max-width:900px;
+ margin:auto;
+ padding-top: 5px;
+ padding-bottom: 10px;
+ }
+ .stampcontainer a {
+ padding: 5px;
+ padding-bottom: 0;
+ }
+ .stampcontainer img {
+ width: 88px;
+ height: 31px;
+ box-shadow: 4px 4px 4px black;
+ }
+ hr {
+ color:transparent;
+ border-top: 1px solid gainsboro;
+ width: 20%;
+ margin: auto;
+ }
+ .tumblr-post {
+ margin: auto;
+ }
+ </style>
+ <script src="tueaday.js"></script>
+ <script type="text/javascript"> window.onload = function() { load(); } </script>
+ </head>
+ <body>
+ <script type="text/javascript">NekoType="mike"</script><h1 id=nl><script src="https://webneko.net/n20171213.js"></script><a href="https://webneko.net">Neko</a></h1>
+
+ <div id="Header">
+ <h1>...</h1>
+ </div>
+
+ <div id="MainContainer">
+
+ <div id="navbar">
+ <a href="https://deeptwisty.com/" class="navbarItem">
+ <img src="icons/deeptwisty.png" />
+ </a>
+ <a href="https://isopodgaming.tumblr.com/" class="navbarItem">
+ <img src="icons/tumblr.png" />
+ </a>
+ <a href="https://twitter.com/deeptwisty" class="navbarItem">
+ <img src="icons/twitter.png" />
+ </a>
+ <a href="https://www.youtube.com/channel/UCftMPQTAP58KiX_vqOk3j1Q" class="navbarItem">
+ <img src="icons/youtube.png" />
+ </a>
+ <a href="https://isopodgaming.tumblr.com/ask/" class="navbarItem">
+ <img src="icons/message.png" />
+ </a>
+ </div>
+ <p>W▓▓▓▓▓ | he/him | 🇨🇦</p>
+ <hr/>
+ <p style="font-weight: normal;text-align:center;" id="tueaday">wait its fucking <span title="somethings up.">tueaday.</span> god.</p>
+ <hr/>
+ <div class="tumblr-post">
+ <div class="tumblr-post" data-href="https://embed.tumblr.com/embed/post/Cve0n4xANc2182UG_YbMag/639332939095818241" data-did="4fa101d65cf2e16f422a37b162617200c67f19c4"><a href="https://kfconsole.tumblr.com/post/639332939095818241">https://kfconsole.tumblr.com/post/639332939095818241</a></div> <script async src="https://assets.tumblr.com/post.js"></script>
+ </div>
+ <p style="padding-bottom:12px;">homophobes dni</p>
+
+ </div>
+
+ <div class="stampcontainer">
+ <a href="https://deeptwisty.com/posts"><img src="stamps/deeptwistybutton.png" /></a>
+ <a href="https://frame.work/"><img src="stamps/bestviewed.gif" /></a>
+ <a href="https://easyussr.neocities.org/guides.html"><img src="stamps/piracy.gif" /></a>
+ <a href="https://deeptwisty.com/images"><img src="stamps/antinft.gif" /></a>
+ <a href="https://www.mozilla.org/en-US/firefox/new/"><img src="stamps/chrome2.gif" /></a>
+ <a href="https://newpipe.net/"><img src="stamps/tiredaf.gif" /></a>
+ <a href="http://www.ermel.org/handcoded/"><img src="stamps/handcode.png" /></a>
+ <a href="https://manjaro.org/"><img src="stamps/linux_powered.gif" /></a>
+ <a href="https://neocities.org/"><img src="stamps/neocities_stamp.gif" /></a>
+ <a href="https://3ds.hacks.guide/"><img src="stamps/bob.gif" /></a>
+ <a href="https://duckduckgo.com/"><img src="stamps/google_stand.gif" /></a>
+ <a href="https://crouton.net/"><img src="stamps/usatoday.gif" /></a>
+ </div>
+
+ </body>
+
+</html>
diff --git a/old/1/stamps/antinft.gif b/old/1/stamps/antinft.gif
new file mode 100644
index 0000000..1a4caf0
--- /dev/null
+++ b/old/1/stamps/antinft.gif
Binary files differ
diff --git a/old/1/stamps/bestviewed.gif b/old/1/stamps/bestviewed.gif
new file mode 100644
index 0000000..0b43d5a
--- /dev/null
+++ b/old/1/stamps/bestviewed.gif
Binary files differ
diff --git a/old/1/stamps/bob.gif b/old/1/stamps/bob.gif
new file mode 100644
index 0000000..90b6dd5
--- /dev/null
+++ b/old/1/stamps/bob.gif
Binary files differ
diff --git a/old/1/stamps/chrome2.gif b/old/1/stamps/chrome2.gif
new file mode 100644
index 0000000..791016f
--- /dev/null
+++ b/old/1/stamps/chrome2.gif
Binary files differ
diff --git a/old/1/stamps/deeptwistybutton.png b/old/1/stamps/deeptwistybutton.png
new file mode 100644
index 0000000..23693b6
--- /dev/null
+++ b/old/1/stamps/deeptwistybutton.png
Binary files differ
diff --git a/old/1/stamps/google_stand.gif b/old/1/stamps/google_stand.gif
new file mode 100644
index 0000000..08ffd8b
--- /dev/null
+++ b/old/1/stamps/google_stand.gif
Binary files differ
diff --git a/old/1/stamps/h-free-anim.gif b/old/1/stamps/h-free-anim.gif
new file mode 100644
index 0000000..ef3b620
--- /dev/null
+++ b/old/1/stamps/h-free-anim.gif
Binary files differ
diff --git a/old/1/stamps/handcode.png b/old/1/stamps/handcode.png
new file mode 100644
index 0000000..c5bbdd1
--- /dev/null
+++ b/old/1/stamps/handcode.png
Binary files differ
diff --git a/old/1/stamps/linux_powered.gif b/old/1/stamps/linux_powered.gif
new file mode 100644
index 0000000..2dbe456
--- /dev/null
+++ b/old/1/stamps/linux_powered.gif
Binary files differ
diff --git a/old/1/stamps/neocities_stamp.gif b/old/1/stamps/neocities_stamp.gif
new file mode 100644
index 0000000..758271b
--- /dev/null
+++ b/old/1/stamps/neocities_stamp.gif
Binary files differ
diff --git a/old/1/stamps/piracy.gif b/old/1/stamps/piracy.gif
new file mode 100644
index 0000000..37b73b8
--- /dev/null
+++ b/old/1/stamps/piracy.gif
Binary files differ
diff --git a/old/1/stamps/tiredaf.gif b/old/1/stamps/tiredaf.gif
new file mode 100644
index 0000000..af8793e
--- /dev/null
+++ b/old/1/stamps/tiredaf.gif
Binary files differ
diff --git a/old/1/stamps/usatoday.gif b/old/1/stamps/usatoday.gif
new file mode 100644
index 0000000..9e6fa57
--- /dev/null
+++ b/old/1/stamps/usatoday.gif
Binary files differ
diff --git a/old/1/style.css b/old/1/style.css
new file mode 100644
index 0000000..9c72a07
--- /dev/null
+++ b/old/1/style.css
@@ -0,0 +1,57 @@
+@keyframes rainbowtext {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);;}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+}
+body {
+ overflow-x: hidden;
+ color: black;
+ font-family: Century Gothic,CenturyGothic,AppleGothic,sans-serif;
+ background-color: black;
+ background-image: url('images/bg_default.png');
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ background-size: cover;
+ overflow-wrap: break-word;
+}
+a {
+ color: dodgerblue;
+}
+a.tueaday {
+ color:inherit;
+ text-decoration:none;
+}
+a:hover {
+ color: dodgerblue;
+}
+#Header {
+ color: white;
+ text-shadow: 2px 2px 2px black;
+ width: 80%;
+ text-align: center;
+ margin: auto;
+ font-size: 1.5em;
+}
+#navbar{
+ border-bottom: 1px solid gainsboro;
+ overflow: hidden;
+ display:flex;
+ justify-content:center;
+}
+.navbarItem {
+ flex-grow:1;
+ text-align: center;
+ cursor:pointer;
+}
+.navbarItem:hover {
+ background-color: gainsboro;
+} \ No newline at end of file
diff --git a/old/1/tueaday.js b/old/1/tueaday.js
new file mode 100644
index 0000000..b0f342b
--- /dev/null
+++ b/old/1/tueaday.js
@@ -0,0 +1,62 @@
+function tueaday() {
+ var dateObj = new Date()
+ var weekday = dateObj.toLocaleString("default", { weekday: "short" }).replace('.','')
+ switch(weekday) {
+ case "Sun":
+ return "suday";
+ break;
+ case "Mon":
+ return "moday";
+ break;
+ case "Tue":
+ return "tueaday";
+ break;
+ case "Wed":
+ return "weaday";
+ break;
+ case "Thu":
+ return "thuday";
+ break;
+ case "Fri":
+ return "friaday";
+ break;
+ case "Sat":
+ return "satuaday";
+ break;
+ default:
+ return dateObj.toLocaleString("default", { weekday: "short" });
+ break;
+ }
+}
+
+function waititsfucking() {
+ var s = tueaday();
+ document.getElementById("tueaday").innerHTML = "wait".concat(' its fucking <a class="tueaday" href="images/', s, '.png">', s, '</a>. god.');
+}
+
+function funnytitle() {
+ const titles = [
+ "Voted Only Page on the Internet in 2022",
+ "Willy's Epic Website",
+ "Will's Cool Webpage",
+ "Welcome to my page :)",
+ "😎",
+ "Hi!",
+ "Over Construction",
+ "mySite.html",
+ "<span style='animation-name: rainbowtext;animation-duration: 2.5s;animation-iteration-count: infinite;'>RGB Gaming Webpage</span>",
+ "Stream deep twisty",
+ "I programmed this feature instead of sleeping",
+ "I didn't want a .carrd.co URL",
+ "I use Arch btw",
+ "Bruh moment",
+ "Supports VPNs",
+ "You should try reloading"
+ ]
+ document.getElementById("Header").innerHTML = "<h1 id='headertext'>".concat(titles[Math.floor(Math.random() * titles.length)], "</h1>");
+}
+
+function load() {
+ funnytitle();
+ waititsfucking();
+} \ No newline at end of file
diff --git a/old/2/audio/bridges.mp3 b/old/2/audio/bridges.mp3
new file mode 100644
index 0000000..d83b98e
--- /dev/null
+++ b/old/2/audio/bridges.mp3
Binary files differ
diff --git a/old/2/buttons/ace.png b/old/2/buttons/ace.png
new file mode 100644
index 0000000..1d62add
--- /dev/null
+++ b/old/2/buttons/ace.png
Binary files differ
diff --git a/old/2/buttons/antinft.gif b/old/2/buttons/antinft.gif
new file mode 100644
index 0000000..1a4caf0
--- /dev/null
+++ b/old/2/buttons/antinft.gif
Binary files differ
diff --git a/old/2/buttons/aro.png b/old/2/buttons/aro.png
new file mode 100644
index 0000000..e1e50d2
--- /dev/null
+++ b/old/2/buttons/aro.png
Binary files differ
diff --git a/old/2/buttons/bantimetravel.png b/old/2/buttons/bantimetravel.png
new file mode 100644
index 0000000..83bcfa1
--- /dev/null
+++ b/old/2/buttons/bantimetravel.png
Binary files differ
diff --git a/old/2/buttons/bestviewed.gif b/old/2/buttons/bestviewed.gif
new file mode 100644
index 0000000..0b43d5a
--- /dev/null
+++ b/old/2/buttons/bestviewed.gif
Binary files differ
diff --git a/old/2/buttons/canadian.gif b/old/2/buttons/canadian.gif
new file mode 100644
index 0000000..be1d040
--- /dev/null
+++ b/old/2/buttons/canadian.gif
Binary files differ
diff --git a/old/2/buttons/chrome.gif b/old/2/buttons/chrome.gif
new file mode 100644
index 0000000..791016f
--- /dev/null
+++ b/old/2/buttons/chrome.gif
Binary files differ
diff --git a/old/2/buttons/deeptwisty_button.png b/old/2/buttons/deeptwisty_button.png
new file mode 100644
index 0000000..b5d24fc
--- /dev/null
+++ b/old/2/buttons/deeptwisty_button.png
Binary files differ
diff --git a/old/2/buttons/google_stand.gif b/old/2/buttons/google_stand.gif
new file mode 100644
index 0000000..08ffd8b
--- /dev/null
+++ b/old/2/buttons/google_stand.gif
Binary files differ
diff --git a/old/2/buttons/handcode.png b/old/2/buttons/handcode.png
new file mode 100644
index 0000000..c5bbdd1
--- /dev/null
+++ b/old/2/buttons/handcode.png
Binary files differ
diff --git a/old/2/buttons/krisbtn.png b/old/2/buttons/krisbtn.png
new file mode 100644
index 0000000..176d3c4
--- /dev/null
+++ b/old/2/buttons/krisbtn.png
Binary files differ
diff --git a/old/2/buttons/linux_powered.gif b/old/2/buttons/linux_powered.gif
new file mode 100644
index 0000000..2dbe456
--- /dev/null
+++ b/old/2/buttons/linux_powered.gif
Binary files differ
diff --git a/old/2/buttons/neocities_stamp.gif b/old/2/buttons/neocities_stamp.gif
new file mode 100644
index 0000000..c8e8ea4
--- /dev/null
+++ b/old/2/buttons/neocities_stamp.gif
Binary files differ
diff --git a/old/2/buttons/niceopod_button.png b/old/2/buttons/niceopod_button.png
new file mode 100644
index 0000000..0398b0e
--- /dev/null
+++ b/old/2/buttons/niceopod_button.png
Binary files differ
diff --git a/old/2/buttons/notoweb3.gif b/old/2/buttons/notoweb3.gif
new file mode 100644
index 0000000..4f5a2f1
--- /dev/null
+++ b/old/2/buttons/notoweb3.gif
Binary files differ
diff --git a/old/2/buttons/nowebp.gif b/old/2/buttons/nowebp.gif
new file mode 100644
index 0000000..e63f1f2
--- /dev/null
+++ b/old/2/buttons/nowebp.gif
Binary files differ
diff --git a/old/2/buttons/piracy.gif b/old/2/buttons/piracy.gif
new file mode 100644
index 0000000..37b73b8
--- /dev/null
+++ b/old/2/buttons/piracy.gif
Binary files differ
diff --git a/old/2/buttons/righttorepair.png b/old/2/buttons/righttorepair.png
new file mode 100644
index 0000000..865ba1f
--- /dev/null
+++ b/old/2/buttons/righttorepair.png
Binary files differ
diff --git a/old/2/buttons/tested_on_firefox.gif b/old/2/buttons/tested_on_firefox.gif
new file mode 100644
index 0000000..92dbae0
--- /dev/null
+++ b/old/2/buttons/tested_on_firefox.gif
Binary files differ
diff --git a/old/2/buttons/usatoday.gif b/old/2/buttons/usatoday.gif
new file mode 100644
index 0000000..9e6fa57
--- /dev/null
+++ b/old/2/buttons/usatoday.gif
Binary files differ
diff --git a/old/2/icons/deeptwisty.png b/old/2/icons/deeptwisty.png
new file mode 100644
index 0000000..7cb8472
--- /dev/null
+++ b/old/2/icons/deeptwisty.png
Binary files differ
diff --git a/old/2/images/2022-05-21_blog_image_1.png b/old/2/images/2022-05-21_blog_image_1.png
new file mode 100644
index 0000000..48743ac
--- /dev/null
+++ b/old/2/images/2022-05-21_blog_image_1.png
Binary files differ
diff --git a/old/2/images/2022-05-21_blog_image_2.png b/old/2/images/2022-05-21_blog_image_2.png
new file mode 100644
index 0000000..d53bf3f
--- /dev/null
+++ b/old/2/images/2022-05-21_blog_image_2.png
Binary files differ
diff --git a/old/2/images/albums/aeon_core.jpg b/old/2/images/albums/aeon_core.jpg
new file mode 100644
index 0000000..e9ad918
--- /dev/null
+++ b/old/2/images/albums/aeon_core.jpg
Binary files differ
diff --git a/old/2/images/albums/concrete_and_gold.jpg b/old/2/images/albums/concrete_and_gold.jpg
new file mode 100644
index 0000000..5b170f2
--- /dev/null
+++ b/old/2/images/albums/concrete_and_gold.jpg
Binary files differ
diff --git a/old/2/images/albums/fucked_up_friends_3.jpg b/old/2/images/albums/fucked_up_friends_3.jpg
new file mode 100644
index 0000000..146a133
--- /dev/null
+++ b/old/2/images/albums/fucked_up_friends_3.jpg
Binary files differ
diff --git a/old/2/images/albums/funeral.png b/old/2/images/albums/funeral.png
new file mode 100644
index 0000000..150076d
--- /dev/null
+++ b/old/2/images/albums/funeral.png
Binary files differ
diff --git a/old/2/images/albums/millenialism.jpg b/old/2/images/albums/millenialism.jpg
new file mode 100644
index 0000000..3654a62
--- /dev/null
+++ b/old/2/images/albums/millenialism.jpg
Binary files differ
diff --git a/old/2/images/albums/revolution_radio.jpg b/old/2/images/albums/revolution_radio.jpg
new file mode 100644
index 0000000..eef448c
--- /dev/null
+++ b/old/2/images/albums/revolution_radio.jpg
Binary files differ
diff --git a/old/2/images/albums/spectrum.png b/old/2/images/albums/spectrum.png
new file mode 100644
index 0000000..f57f9eb
--- /dev/null
+++ b/old/2/images/albums/spectrum.png
Binary files differ
diff --git a/old/2/images/albums/tortured_waters.jpg b/old/2/images/albums/tortured_waters.jpg
new file mode 100644
index 0000000..4376dbe
--- /dev/null
+++ b/old/2/images/albums/tortured_waters.jpg
Binary files differ
diff --git a/old/2/images/albums/unstoppable_force.png b/old/2/images/albums/unstoppable_force.png
new file mode 100644
index 0000000..22659aa
--- /dev/null
+++ b/old/2/images/albums/unstoppable_force.png
Binary files differ
diff --git a/old/2/images/albums/vast.png b/old/2/images/albums/vast.png
new file mode 100644
index 0000000..398d5a0
--- /dev/null
+++ b/old/2/images/albums/vast.png
Binary files differ
diff --git a/old/2/images/albums/walks_of_lung.jpg b/old/2/images/albums/walks_of_lung.jpg
new file mode 100644
index 0000000..66550bf
--- /dev/null
+++ b/old/2/images/albums/walks_of_lung.jpg
Binary files differ
diff --git a/old/2/images/isopod.png b/old/2/images/isopod.png
new file mode 100644
index 0000000..cf974c0
--- /dev/null
+++ b/old/2/images/isopod.png
Binary files differ
diff --git a/old/2/images/isopod_with_aviators.png b/old/2/images/isopod_with_aviators.png
new file mode 100644
index 0000000..443a6fb
--- /dev/null
+++ b/old/2/images/isopod_with_aviators.png
Binary files differ
diff --git a/old/2/images/this_burning.gif b/old/2/images/this_burning.gif
new file mode 100644
index 0000000..6b123b4
--- /dev/null
+++ b/old/2/images/this_burning.gif
Binary files differ
diff --git a/old/2/index.html b/old/2/index.html
new file mode 100644
index 0000000..a3f7e43
--- /dev/null
+++ b/old/2/index.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <meta charset="utf-8">
+ <title>Real isopod hours</title>
+ <style id="pretheme">
+ body {
+ background-color: #222222;
+ }
+ </style>
+ <link href="shared.css" rel="stylesheet" type="text/css" media="all">
+ <link href="" rel="stylesheet" type="text/css" media="all" id="theme">
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;800&display=swap" rel="stylesheet">
+ <link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&display=swap" rel="stylesheet">
+ <link href="https://fonts.googleapis.com/css2?family=Days+One&display=swap" rel="stylesheet">
+ <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;700&display=swap" rel="stylesheet">
+ <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap" rel="stylesheet">
+ </head>
+ <body>
+ <a target="_blank" href="https://wobble.town/visit/93" style="position:fixed; bottom: 0; right: 25%; font-size: 0;" title="charles"><img src="https://wobble.town/visit/93/wobble.gif" style="width: 96px; image-rendering: pixelated; filter:hue-rotate(20deg) brightness(110%) drop-shadow(2px 2px 3px black);"></a>
+ <div id="nav">
+ <a href="https://deeptwisty.com"><img src="icons/deeptwisty.png" /></a>
+ <a href="?page=home"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor"><path d="M18 18V7.132l-8-4.8-8 4.8V18h4v-2.75a4 4 0 1 1 8 0V18h4zm-6 2v-4.75a2 2 0 1 0-4 0V20H2a2 2 0 0 1-2-2V7.132a2 2 0 0 1 .971-1.715l8-4.8a2 2 0 0 1 2.058 0l8 4.8A2 2 0 0 1 20 7.132V18a2 2 0 0 1-2 2h-6z"></path></svg></span></a>
+ <a style="cursor: pointer;" onclick="
+ var tsa = document.getElementById('themeselector').style.animationName;
+ if(tsa === 'tsappear') { document.getElementById('themeselector').style.animationName = 'tsdisappear'; }
+ else { document.getElementById('themeselector').style.animationName = 'tsappear'; }
+ "><svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -3 24 24" width="24" fill="currentColor"><path d="M6.816 11.556c-1.008.464-1.69 1.003-2.084 1.598a51.574 51.574 0 0 0-1.115 1.756c1.124.244 1.969.127 2.578-.281.852-.57 1.408-1.221 1.717-1.977l-1.096-1.096zm1.395-1.433l1.02 1.02c.742-.382 1.489-.987 2.234-1.832 1.139-1.29 3.061-3.588 5.757-6.88a.211.211 0 0 0-.297-.296c-3.286 2.693-5.583 4.615-6.881 5.758-.849.746-1.454 1.491-1.833 2.23zm-.903 6.168c-1.615 1.081-3.826.982-6.63-.298a58.148 58.148 0 0 1 2.387-3.945c.655-.987 1.712-1.794 3.17-2.422C6.72 8.5 7.55 7.423 8.722 6.39c1.32-1.162 3.632-3.096 6.936-5.803a2.21 2.21 0 0 1 3.111 3.111c-2.71 3.31-4.645 5.621-5.804 6.935-.978 1.108-2 1.911-3.067 2.408-.43 1.298-1.293 2.38-2.59 3.249z"></path></svg></a>
+ <a href="?page=stats"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -4 24 24" width="24" fill="currentColor"><path d="M1 0a1 1 0 0 1 1 1v14a1 1 0 0 1-2 0V1a1 1 0 0 1 1-1zm12 4a1 1 0 0 1 1 1v10a1 1 0 0 1-2 0V5a1 1 0 0 1 1-1zM7 8a1 1 0 0 1 1 1v6a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1z"></path></svg></a>
+ <a href="?page=blog"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-1.5 -1.5 24 24" width="24" fill="currentColor"><path d="M13.89 10.808l3.616-3.616a3 3 0 0 0-4.243-4.242L11.77 4.444l.598 2.23.896-.896a1 1 0 1 1 1.415 1.414L11.66 10.21l2.23.598zm-1.633 1.633l-2.23-.598-2.74 2.74 2.66.169 2.31-2.311zm-2.12-6.364L5.71 10.502l.163 2.665 4.86-4.86-.598-2.23zM5.403 16.466L1.95 19.92a1 1 0 0 1-1.414-1.414l3.45-3.45-.326-5.331 8.19-8.19a5 5 0 1 1 7.07 7.072l-8.198 8.198-5.318-.34z"></path></svg></a>
+ <a href="?page=music"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor"><path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm7-8a6.99 6.99 0 0 1-2.89 5.666l-.53-.796L13 14a4.992 4.992 0 0 0 2-4 4.992 4.992 0 0 0-2-4l1.2-1.6A6.99 6.99 0 0 1 17 10zm-7 3a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path></svg></a>
+ <a href="?page=links"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -3 24 24" width="24" fill="currentColor"><path d="M3.19 9.345a.97.97 0 0 1 1.37 0 .966.966 0 0 1 0 1.367l-2.055 2.052a1.932 1.932 0 0 0 0 2.735 1.94 1.94 0 0 0 2.74 0l4.794-4.787a.966.966 0 0 0 0-1.367.966.966 0 0 1 0-1.368.97.97 0 0 1 1.37 0 2.898 2.898 0 0 1 0 4.103l-4.795 4.787a3.879 3.879 0 0 1-5.48 0 3.864 3.864 0 0 1 0-5.47L3.19 9.344zm11.62-.69a.97.97 0 0 1-1.37 0 .966.966 0 0 1 0-1.367l2.055-2.052a1.932 1.932 0 0 0 0-2.735 1.94 1.94 0 0 0-2.74 0L7.962 7.288a.966.966 0 0 0 0 1.367.966.966 0 0 1 0 1.368.97.97 0 0 1-1.37 0 2.898 2.898 0 0 1 0-4.103l4.795-4.787a3.879 3.879 0 0 1 5.48 0 3.864 3.864 0 0 1 0 5.47L14.81 8.656z"></path></svg></a>
+ <a href="https://me.deeptwisty.com/stuff/"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-9 -2 24 24" width="24" fill="currentColor"><path d="M3 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 2a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 14a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0-5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path></svg></a>
+ </div>
+ <div id="themeselector">
+ <div id="themelist">
+ <h3 style="margin-bottom: -10px;">Themes</h3><br/>
+ <a onclick="switchTheme('none');">None</a><br/>
+ <a onclick="switchTheme('default');">Default</a><br/>
+ <a onclick="switchTheme('deeptwisty');">deep twisty</a><br/>
+ <a onclick="switchTheme('alterra');">Alterra</a><br/>
+ <a onclick="switchTheme('gruvbox');">r/unixporn</a><br/>
+ <a onclick="switchTheme('geocities');">geocities</a>
+ </div>
+ </div>
+ <div id="chatbox">
+ <div id="chatboxpulltab"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2.5 24 24" width="32" fill="currentColor"><path d="M3.656 17.979A1 1 0 0 1 2 17.243V15a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H8.003l-4.347 2.979zm.844-3.093a.536.536 0 0 0 .26-.069l2.355-1.638A1 1 0 0 1 7.686 13H12a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v5c0 .54.429.982 1 1 .41.016.707.083.844.226.128.134.135.36.156.79.003.063.003.177 0 .37a.5.5 0 0 0 .5.5z"></path><path d="M16 10.017a7.136 7.136 0 0 0 0 .369v-.37c.02-.43.028-.656.156-.79.137-.143.434-.21.844-.226.571-.018 1-.46 1-1V3a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1H5V2a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2v2.243a1 1 0 0 1-1.656.736L16 13.743v-3.726z"></path></svg></div>
+ <iframe src="https://www3.cbox.ws/box/?boxid=3517193&boxtag=ZPAfDN" width="100%" height="450" allowtransparency="yes" allow="autoplay" frameborder="0" marginheight="0" marginwidth="0" scrolling="auto"></iframe>
+ </div>
+ <div id="main">
+ <div id="centercolumn">
+ </div>
+ <script src="script.js"></script>
+ <script type="text/javascript">window.onload = function() {page();}</script>
+ </body>
+</html>
diff --git a/old/2/pages/blog.html b/old/2/pages/blog.html
new file mode 100644
index 0000000..0ae326b
--- /dev/null
+++ b/old/2/pages/blog.html
@@ -0,0 +1,41 @@
+<h1 id="header">Inane ramblings</h1>
+<div class="section" id="status"></div>
+<div class="section" id="Late_May_Updates">
+ <h2>Late May Updates</h2>
+ <h3>2022-05-21</h3>
+ <p>It's getting dangerously close to a month since my last post, which is upsetting to me. Time is supposed to pass slower than this. As they are wont to do, some things have happened since then, and as your reward for finding your way here, you get to read about them.</p>
+ <h4><span title="Feels weird using this term for myself, though I suppose it's accurate.">Coming out</span></h4>
+ <p>Most notably, I've come to the understanding that I'm <span class="hoverable"><span style="background: linear-gradient(to right, black 0%, #800080 20%, #a3a3a3 40%, white 60%, #A7D379 80%, #3DA542 100%); background-clip: border-box; -webkit-background-clip: text; -webkit-text-fill-color: transparent;">aroace</span><span class="tooltip"><span style="background: linear-gradient(to right, #3DA542 0%, #A7D379 25%, white 50%, #A9A9A9 75%, black 100%); background-clip: border-box; -webkit-background-clip: text; -webkit-text-fill-color: transparent;">Aromantic</span>-<span style="background: linear-gradient(to right, black 0%, #A3A3A3 33.3%, white 66.6%, #800080 100%); background-clip: border-box; -webkit-background-clip: text; -webkit-text-fill-color: transparent;">asexual</span>; Defined simply as experiencing little to no romantic or sexual attraction.</span></span>. I'm still a bit caught up on the minutae, but I'm fairly certain I lie on that spectrum somewhere.</p>
+ <p>The main issue for me at the moment is I'm trying to derive these labels by comparing my experiences with what's normal, but I've grown up believing my experiences <span class="emph">were</span> normal and my next most reliable frame of reference is how I see other people reacting to and depicting those emotions, and I kind of have to take it on faith that I'm not feeling them exactly the same way and just responding differently, or something. Thinking about it, it's actually pretty similar to finding out I'm autistic, having to figure out that most people don't engage with the world this way.</p>
+ <p>I could go into way more detail - I've been thinking about this a lot lately - but I've already shared rather a lot more than is remotely necessary. I probably could have stopped at the pride buttons at the bottom of the homepage, but it's nice to get these thoughts out.</p>
+ <h4>Patch notes</h4>
+ <p>You may notice I've made some changes to the website since my last post, too. I've added a couple new themes, as well as a little guy chilling on the bottom. His name is Charles, and you can click him to visit his house! There's also some new pages: a <a href="?page=links">links</a> page to other websites I think are cool, and a <a href="?page=stats">stat table</a>. Also, freegb.net seems to have abruptly and tragically dropped off the face of the earth mere days after I set up the guestbook, so I've replaced it with a cbox channel off to the right of the page.</p>
+ <h4>Miscellaneous updates</h4>
+ <p>I've upgraded the CPU cooler in my PC. I noticed it was thermal throttling pretty bad with the stock one, so I bought a fancy Noctua aftermarket one, but as I was installing it I noticed that one of the screws on the stock heatsink wasn't screwed in all the way. It was probably overheating because I hadn't installed the damn cooler correctly! Well, at any rate, it does run significantly cooler now, and it doesn't throttle anymore, so mission accomplished I suppose. Inb4 I find out I installed the new one wrong too.</p>
+ <p>I've been accumulating a CD collection. Turns out they're super cheap used on Ebay. It's mostly Foo Fighters at the moment; I'm considering just outright buying their entire discography at this point. I rather like having a copy of all the music I enjoy lest I lose it forever at the whim of some shitass rightsholder, and it's nice to actually substantively support the artist when I buy them new. I make a point to rip all the CDs too; it's very convenient to have a digital copy and it's not like my phone has an optical drive. My ripping program of choice is <a href="http://littlesvr.ca/asunder/">Asunder</a>, though it's only available for Linux so I can't help you if you're on Windows.</p>
+ <p>I tried pilk recently. One part Pepsi, one part milk. It was wack.</p>
+ <p>There's a dead pixel on my monitor. It's in the bottom left and only lights up blue. <span class="emph">Annoying</span>.</p>
+ <p>I've been messing around with my Firefox configuration lately. I've got a real sleek <span class="hoverable">setup<span class="tooltip" style="font-size: 0;"><img src="images/2022-05-21_blog_image_1.png" style="width: 100%;"></span></span> going that condenses all the top bar stuff into one line and an extension that matches the top bar color to the color of whatever page I'm on. It's like it's not even there! If y'all want I can write another post or something going into more detail about my setup. Let me know if you'd be interested in that.</p>
+ <p>I've been noticing a lot of my fellow free software likers are big into cryptocurrency. I can understand the appeal for someone with that set of principles, but it shows kind of a flagrant disregard for the environment and a seemingly willful ignorance of <a href="https://yesterweb.org/no-to-web3/">crypto's many obvious inherent flaws</a>. Are these really the kind of people I want to associate with? Am I going to have to spend the rest of my life publically denouncing their ilk in order to avoid appearing to be one of them?</p>
+ <p>I'm considering buying a Raspberry Pi (once they become available again) to experiment with web hosting and other such things. Perhaps I could have some fun with that GPIO array. Maybe I could host my own guestbook on there. Could be fun.</p>
+ <p>That's all I've got for now. To close out this post, have this photo of a skink I found on iNaturalist: <a href="https://www.inaturalist.org/observations/117958867" target="_blank"><img src="images/2022-05-21_blog_image_2.png" style="width: 100%;"></a></p>
+</div>
+<div class="section" id="Second">
+ <h2>Second</h2>
+ <h3>2022-04-25</h3>
+ <p>After 12 days I have become well and truly sick of seeing my blog page with its poor, lonely one post on it, so you get to read more of what should probably be my private thoughts now. Since the, as of now, only other post, I have implemented most of the stuff I said I was going to then, including but not limited to eating breakfast. I think I had a bowl of original Special K that day. As of writing, I have added four new CSS themes to choose from, a page of albums I like, a link to a freegb.net guestbook that currently has one entry, and a "misc" page for small things that wouldn't fit on social media but don't warrant their own page. There's also a fancy URL hash system like Wikipedia has so I can link people to different sections of the page like <a href="?page=blog#First">this</a>. I've yet to get that custom 404 page up and running, though. I don't really have any ideas for it. I also haven't slept.</p>
+ <h4>Something fun on the computer</h4>
+ <p>This is a weblog, not a changelog, so this post needs some more content. I'm thinking I talk about a videogame you've never heard of. Sound good? Great, 'cause this is my website and I don't care what you think.</p>
+ <p>I've been playing a game recently called Neon Boost. It's a first-person platformer based around rocket-jumping to navigate the levels. If that sounds like a cool concept to you, I'm not alone. However, this is probably one of the worst games in its genre. It's horribly unpolished, buggy, and the level design is criminally bad. It's so broken that it wraps back around to being god damn addicting to play. Neon Boost is a game best enjoyed by utterly ignoring the intent of its designers. If that description somehow sold you on this experience and you'd rather not be spoiled, go play it now. It's <a href="https://store.steampowered.com/app/1057850/Neon_Boost/">free on Steam</a> for Windows and runs great in Proton.</p>
+ <p>So anyway, the fun in this game is in doing everything in your power to completely circumvent the intended path of the level, and there is a shocking amount that is in your power. Your moveset in this game consists of running, jumping, and shooting rockets. If you're caught in the blast of a rocket, it applies a set upward force to you. This presents all sorts of fun exploits. Chiefly, if you jump normally and then shoot a rocket at your feet a split second later, it launches you way higher than either normal jumping or rocket jumping on their own. Combine this with <span class="hoverable">moving diagonally in the air<span class="tooltip">Movement vectors in this game are weird. They're, like, mostly normalized, so running diagonally on the ground doesn't seem to do anything, but in the air, you do go noticeably faster diagonally than just moving straight forward.</span></span> and you can almost completely skip a few levels.</p>
+ <p>A lot of levels have even funnier exploits, though. In certain spots, you can exploit-jump and then use another rocket to gain <span class=emph>even more</span> height. A couple levels in world 1 have train tracks above the level that you can reach this way from the starting platform and walk on to complete the level with a time of 0. See, the in-game timer only starts once you get close enough to something that's part of the stage, and while all of these train tracks have collision, none of them trigger the timer to start because they're not part of the intended route, so you can traverse them for as long as you please without starting the timer. In a couple other levels, the scenery has collision that creates shortcuts over top of it. Two levels in worlds 1 and 3 respectively have shafts you're supposed to drop down that you can ignore if you just exploit-jump around them. My favourite out of all of these, though, is the last level of the second world. This level places you inside a moving cage made of lasers that you're supposed to remain inside until the end of the level, but... <a href="https://youtu.be/CBQRyaNrcac">just look at this shit</a>.</p>
+ <p>I don't want to spoil the entire game, nor do I want to take up any more space rambling about it. I didn't even talk about the horrible wall-running that seems to only work properly when you're bypassing the level, or the fucked up "lights off" mode that makes you play with something akin to Minecraft's blindness effect. In summary, Neon Boost is the worst first-person platformer ever and <span class="hoverable">you should play it.<span class="tooltip"><a href="https://me.deeptwisty.com/stuff/neon_boost_times.html">Try and beat my times</a>.</span></span> The soundtrack's alright, too.</p>
+</div>
+<div class="section" id="First">
+ <h2>First</h2>
+ <h3><span title="Happy birthday John">2022-04-13</span></h3>
+ <p>As I write this it is six in the morning and I have been up all night coding the page switching on me.deeptwisty.com v2. The system I built takes a URL parameter and loads HTML from a corresponding file into a section on the main page. It would most assuredly have been easier to just hyperlink a bunch of static pages together, but that’s for pussies and also I didn’t want to have to update the navbars and webfont links and such on every single one individually.</p>
+ <p>This is me.deeptwisty.com v2, by the way. I completely rebuilt the entire website from scratch. I don't know if I was just getting bored of the <a href="https://me.deeptwisty.com/old/1/">old look</a> of the place or if I was, like, mad at it for what happened with deeptwisty.com proper, but I wanted a change.</p>
+ <p>For context there, here's the story: this place used to be located at deeptwisty.com/me. I felt like moving it to me.deeptwisty.com, because that would look nicer. Now, Neocities requires you to create an entirely new profile in order to hook it up to a subdomain like that. This was fine by me, because deeptwisty.com and /me were functionally two entirely separate sites to begin with, but in the process of transferring the files from /me to the new site, I accidentally uploaded a bunch of them to the wrong profile and overwrote the main homepage and the main CSS file for the entire site. So those are gone now. I took that turn of events as an excuse to rebuild <span class="emph">that</span> site from the ground up, because it was incredibly boring, and when I had finished with that I realized I was having fun. So now we're here.</p>
+ <p>If you're reading this post the minute it goes up, this place isn't anywhere near done. It's pretty sleek as it is, but I want to add way more stuff, now that I've got room in my design for it. I intend to add some kind of guestbook or comment box, a theme switcher to load the site with entirely different styling, and pages upon pages of oversharing, among other things. I also want to make a fancy custom 404 page. Maybe put a game on there. You name it, really. Right now, though, I need to eat breakfast and then go to bed. Hopefully I don't forget about this blog immmediately after posting this.</p>
+</div>
diff --git a/old/2/pages/home.html b/old/2/pages/home.html
new file mode 100644
index 0000000..f9e3bb0
--- /dev/null
+++ b/old/2/pages/home.html
@@ -0,0 +1,152 @@
+<h1 id="header"><span id="randomheader">.</span></h1>
+<div class="section" id="status"></div>
+<div class="section" id="Hello_there">
+ <h2><span title="General Kenobi!">Hello there!</span></h2>
+ <p>My name's <span class="hoverable">W▓▓▓▓▓<span class="tooltip">he/him pronouns</span></span>, but I typically go by niceopod on the internet, or deep twisty if you're looking at my music. I make stuff sometimes, like <a href="https://deeptwisty.bandcamp.com">music</a>, or <a href="https://deeptwisty.com/images">art</a>, or this website. I have been called many things, such as "canadian", "autistic", and <span title="I'm practicing positive self-talk.">"tremendously, stupendously, superhumanly talented"</span>.</p>
+ <p>This is my website, where I put links to my accounts on other websites. It started as a way to circumvent the limitations of a free carrd account, but now we're here and I don't think I could go back. <span style="text-decoration:line-through;">It's pretty barren at the moment, but I'd like to put some actual stuff here. Maybe I'll start a <a href="?page=blog">blog</a>.</span> That part is outdated. Replacement text pending.</p>
+ <p>You can navigate around using the bar on the left, or the top if you're on mobile. There's a chatbox over → there, say hi! If you're using a mouse, you can also hover over <span class="hoverable">some stuff<span class="tooltip" style="font-size: 0; text-decoration: none;"><img src="https://orig00.deviantart.net/5413/f/2018/171/2/0/armored_armadillo_by_emilianomario-dceynvh.png" style="width: 64px;" /></span></span> for more information. I've also got some 88x31 buttons you can <span class="hoverable">use<span class="tooltip">I'd advise you post the image to your site, if you hotlink it will probably break when I inevitably redesign the site again.</span></span> if for some reason you want to link back here:<br/><span class="hoverable"><img src="buttons/niceopod_button.png" /> <img src="buttons/deeptwisty_button.png" /><span class="tooltip">Made with <a href="https://codepen.io/hosma/pen/poWKNGV">this</a>.</span></span></p>
+</div>
+<div class="section" id="Whats_a_deep_twisty">
+ <h2><span title="something about some bridges?">What's a "deep twisty"?</span></h2>
+ <p>I felt like I needed a pseudonym for my music, so I made one and now I'm stuck with it. If you <span class="emph">must</span> know where it comes from, I was really into Subnautica a couple of years back while its sequel Below Zero was in early access, and I was following <a href="https://twitter.com/SubnauticaSCM">this official Twitter account</a> that tweets every git commit that gets made to it. They kept referring to a new biome they were working on, the Deep Twisty Bridges, as just "deep twisty". I thought that sounded really funny.</p>
+ <p>You may notice this is <span class="emph">me</span>.deeptwisty.com. <a href="https://deeptwisty.com">deeptwisty.com proper</a> is the site for things I release ~officially~ under that name. Why the distinction? Mostly so that if I ever grow the balls to show my art to my family, they don't manage to find their way to my twitter account.</p>
+</div>
+<div class="section" id="Software_I_use">
+ <h2><span title="If you use anything else you're dead to me.">Software I use</span></h2>
+ <table>
+ <tr>
+ <td>Browser</td>
+ <td><span class="hoverable"><a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a><span class="tooltip">Please for the love of god use Firefox. It's currently the only major browser that isn't based on Chrome, and we can't let Google gain monopolistic control over web standards. Plus, Firefox isn't trying to track you the way <a href="https://www.eff.org/deeplinks/2021/03/google-testing-its-controversial-new-ad-targeting-tech-millions-browsers-heres">Chrome is</a>.</span></span></td>
+ </tr>
+ <tr>
+ <td>VPN</td>
+ <td><span class="hoverable"><a href="https://www.mozilla.org/en-US/products/vpn/">Mozilla VPN</a><span class="tooltip">Chosen mostly because it seemed good and I wanted to support Mozilla. If I had to pick again, I'd probably choose Mullvad.</span></span></td>
+ </tr>
+ <tr>
+ <td>DAW</td>
+ <td><span class="hoverable"><a href="https://lmms.io/">LMMS</a><span class="tooltip">I won't say LMMS is bad, but it is only any good at one thing: composing MIDI audio. VST support is good, but only for instruments, it barely supports samples and audio tracks, and it can't record audio, among other gripes.</canvas></span></span>, but I'm trying to switch to <span class="hoverable"><a href="https://www.reaper.fm/">REAPER</a><span class="tooltip">REAPER is great. It solves every problem I had with LMMS. The main thing making it difficult to pick up is the fact that it doesn't play nice with a lot of VSTs, and it doesn't have LMMS's built-in WINE for running my Windows VSTs either.</span></span></td>
+ </tr>
+ <tr>
+ <td>3D software</td>
+ <td><span class="hoverable"><a href="https://www.blender.org/">Blender</a><span class="tooltip">Blender is incredible. It can do everything: it's got modeling, animation, sculpting, video editing, a built-in Python scripting interface, and a billion and one other things. I probably could've built this website in Blender if I wanted to.</span></span></td>
+ </tr>
+ <tr>
+ <td>Photo editor</td>
+ <td><span class="hoverable"><a href="https://www.gimp.org/">GIMP</a><span class="tooltip">I'd prefer <a href="https://www.getpaint.net/">Paint.NET</a>, but it's not available for Linux and I can't get it running in WINE.</span></span></td>
+ </tr>
+ <tr>
+ <td>IDE</td>
+ <td><span class="hoverable"><a href="https://vscodium.com/">VSCodium</a><span class="tooltip">An open-source "clean" build of Visual Studio Code without all of Microsoft's telemetry.</span></span></td>
+ </tr>
+ <tr>
+ <td>OS</td>
+ <td><span class="hoverable"><a href="https://manjaro.org/">Manjaro Linux</a><span class="tooltip">I use arch btw</span></span></td>
+ </tr>
+ </table>
+</div>
+<div class="section" id="Links">
+ <h2><span title="More worthwhile places">Links</span></h2>
+ <table>
+ <tr>
+ <td>Art page</td>
+ <td><a href="https://deeptwisty.com/images/">deeptwisty.com/images</a></td>
+ </tr>
+ <tr>
+ <td>Tumblr</td>
+ <td><a href="https://tumblr.deeptwisty.com/">isopodgaming</a></td>
+ </tr>
+ <tr>
+ <td title="(ugh)">Twitter</td>
+ <td><a href="https://twitter.com/niceopod/">@niceopod</a></td>
+ <td class="tdc">Currently on hiatus</td>
+ </tr>
+ <tr>
+ <td>Bandcamp</td>
+ <td><a href="https://deeptwisty.bandcamp.com/">deep twisty</a></td>
+ <td class="tdc">give me money here</td>
+ </tr>
+ <tr>
+ <td>YouTube</td>
+ <td><a href="https://www.youtube.com/channel/UCMXbpKy2X_rFX8Bkol0KQ1A">deep twisty</a></td>
+ <td class="tdc">For my music</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><a href="https://www.youtube.com/channel/UCftMPQTAP58KiX_vqOk3j1Q">isopod gaming</a></td>
+ <td class="tdc">For everything else</td>
+ </tr>
+ <tr>
+ <td>itch.io</td>
+ <td><a href="https://deeptwisty.itch.io/">deeptwisty</a></td>
+ </tr>
+ <tr>
+ <td>Neocities</td>
+ <td><a href="https://neocities.org/site/niceopod">me.deeptwisty.com</a></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><a href="https://neocities.org/site/deeptwisty">deeptwisty.com</a></td>
+ </tr>
+ <tr>
+ <td>E-mail</td>
+ <td><a href="mailto:contact@deeptwisty.com">contact@deeptwisty.com</a></td>
+ </tr>
+ </table>
+ <h4>Webring(s)</h4>
+ <p class="centered"><span style="font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif" class="spaced_on_hover"><a>←</a> <b><i><a>HOTLINE</a></i></b> <a>→</a></span></p>
+</div>
+<div class="section">
+ <h2>Changelog</h2>
+ <div id="changelogwindow">
+ <p>2022-06-12</p>
+ <ul>
+ <li>Renamed /misc to /stuff</li>
+ <li>Added my address to the stats page</li>
+ </ul>
+ <p>2022-05-29</p>
+ <ul>
+ <li>Added <a href="https://regexr.com/">RegExr</a> to the links page</li>
+ </ul>
+ <p>2022-05-25</p>
+ <ul>
+ <li>Added an <a href="https://me.deeptwisty.com/feed.xml" target="_blank">RSS feed</a> for the blog!</li>
+ <li>Demoted the link to me.deeptwisty.com v1 from having its own section on the homepage to being relegated to /misc/</li>
+ </ul>
+ <p>2022-05-23</p>
+ <ul>
+ <li>Added <a href="https://switching.software/">switching.software</a> and <a href="https://www.allaboutbirds.org/cams/">Cornell Lab Bird Cams</a> to the links page</li>
+ <li>Updated the IDE I use from VSCode to VSCodium</li>
+ </ul>
+ <p>2022-05-22</p>
+ <ul>
+ <li>Added <a href="https://status.cafe/users/niceopod">status.cafe</a> widget to the home and blog pages</li>
+ <li>Added a changelog</li>
+ </ul>
+ <p>2022-05-21</p>
+ <ul>
+ <li>Added <a href="?page=stats">stats table</a> page</li>
+ <li>Added a cbox channel →</li>
+ <li>New blog post!</li>
+ </ul>
+ </div>
+</div>
+<div class="section" id="buttons">
+ <a href="https://frame.work"><img src="buttons/bestviewed.gif" /></a>
+ <a href="https://www.mozilla.org/en-US/firefox/new/"><img src="buttons/chrome.gif" /></a>
+ <a href="https://yesterweb.org/no-to-web3/"><img src="buttons/notoweb3.gif" /></a>
+ <a href="https://easyussr.neocities.org/torrenting.html"><img src="buttons/piracy.gif" /></a>
+ <a href="https://neocities.org"><img src="buttons/neocities_stamp.gif" /></a>
+ <a href="http://www.ermel.org/handcoded/"><img src="buttons/handcode.png" /></a>
+ <a href="https://crouton.net/"><img src="buttons/usatoday.gif" /></a>
+ <a><img src="buttons/righttorepair.png" /></a>
+ <a><img src="buttons/linux_powered.gif" /></a>
+ <a><img src="buttons/bantimetravel.png" /></a>
+ <a><img src="buttons/google_stand.gif" /></a>
+ <span class="hoverable"><a><img src="buttons/canadian.gif" /></a><span class="tooltip">Regrettably</span></span>
+ <a><img src="buttons/nowebp.gif" /></a>
+ <a><img src="buttons/antinft.gif" /></a>
+ <a><img src="buttons/krisbtn.png" /></a>
+ <a><img src="buttons/aro.png" /></a>
+ <a><img src="buttons/ace.png" /></a>
+ <a><img src="buttons/tested_on_firefox.gif" /></a>
+</div>
diff --git a/old/2/pages/links.html b/old/2/pages/links.html
new file mode 100644
index 0000000..660a7c8
--- /dev/null
+++ b/old/2/pages/links.html
@@ -0,0 +1,64 @@
+<h1 id="header">Cool stuff</h1>
+<div class="section">
+ <table id="linktable">
+ <tr>
+ <td><a href="https://easyussr.neocities.org/torrenting.html">Easy USSR</a></td>
+ <td>A comprehensive beginner's guide to <span class="serif">Legally Acquiring Media</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://jam-icons.com">Jam Icons</a></td>
+ <td>The icon set I use for the navbar over &#8592; there</td>
+ </tr>
+ <tr>
+ <td><a href="https://cooltext.com/Logo-Design-Burning">Burning Text Generator</a></td>
+ <td>Does <img src="images/this_burning.gif" style="height: 3ch;"/></td>
+ </tr>
+ <tr>
+ <td><a href="https://fsymbols.com/generators/zalgo/">Zalgo Text Generator</a></td>
+ <td>Does t̵̝̻̘͒̓̈́h̵͇͙͔́̾i̵͎̪̞͊́̾s̵̫̼̀̾</td>
+ </tr>
+ <tr>
+ <td><a href="https://crouton.net">crouton.net</a></td>
+ <td>crouton</td>
+ </tr>
+ <tr>
+ <td><a href="https://draculadaily.substack.com/about">Dracula Daily</a></td>
+ <td>Read Bram Stoker's <i>Dracula</i> in real time, in your email inbox.</td>
+ </tr>
+ <tr>
+ <td><a href="https://3ds.hacks.guide/">3DS Hacks Guide</a></td>
+ <td>A comprehensive guide for modding 2ds and 3ds consoles. I know it's legit because I used it on mine.</td>
+ </tr>
+ <tr>
+ <td><a href="https://hshop.erista.me/">hShop</a></td>
+ <td>A repository of software for your freshly hacked 3ds</td>
+ </tr>
+ <tr>
+ <td><a href="https://wobble.town/">Wobble Town</a></td>
+ <td>A cute little virtual pet!</td>
+ </tr>
+ <tr>
+ <td><a href="https://newpipe.net/">Newpipe</a></td>
+ <td>A better YouTube client for Android</td>
+ </tr>
+ <tr>
+ <td><a href="https://switching.software/">switching.software</a></td>
+ <td>A curated list of alternatives to popular software and services from companies like Google and Amazon.</td>
+ </tr>
+ <tr>
+ <td><a href="https://www.allaboutbirds.org/cams/">Cornell Lab Bird Cams</a></td>
+ <td>Live bird cams!</td>
+ </tr>
+ <tr>
+ <td><a href="https://regexr.com/">RegExr</a></td>
+ <td>A website to test regular expressions for you</td>
+ </tr>
+ <tr>
+ <td><a href="https://links.yesterweb.org/">Yesterlinks</a></td>
+ <td>More cool links</td>
+ </tr>
+ </table>
+</div>
+<!--div class="section" id="buttons">
+ <a href="https://deeptwisty.com"><img src="buttons/deeptwisty_button.png" /></a>
+</div--> \ No newline at end of file
diff --git a/old/2/pages/music.html b/old/2/pages/music.html
new file mode 100644
index 0000000..58a8a4d
--- /dev/null
+++ b/old/2/pages/music.html
@@ -0,0 +1,49 @@
+<h1 id="header">Albums I like</h1>
+<div class="section" id="albums">
+ <table>
+ <tr>
+ <td class="aimg"><img src="images/albums/spectrum.png"/></td>
+ <td class="ala"><a href="https://findaeden.bandcamp.com/album/spectrum">findaeden - Spectrum</a></td>
+ </tr>
+ <tr>
+ <td class="ara"><a href="https://newretrowave.bandcamp.com/album/tortured-waters">DEADLIFE - Tortured Waters</a></td>
+ <td class="aimg"><img src="images/albums/tortured_waters.jpg"/></td>
+ </tr>
+ <tr>
+ <td class="aimg"><img src="images/albums/funeral.png"/></td>
+ <td class="ala"><a href="https://noisemaster.bandcamp.com/album/funeral-ep">Noisemaker - Funeral EP</a></td>
+ </tr>
+ <tr>
+ <td class="ara"><a href="https://caliphate.bandcamp.com/album/unstoppable-force">CALIPHATE - Unstoppable Force</a></td>
+ <td class="aimg"><img src="images/albums/unstoppable_force.png"/></td>
+ </tr>
+ <tr>
+ <td class="aimg"><img src="images/albums/walks_of_lung.jpg"/></td>
+ <td class="ala"><a href="https://patriciataxxon.bandcamp.com/album/walks-of-lung">Patricia Taxxon - Walks of Lung</a></td>
+ </tr>
+ <tr>
+ <td class="ara"><a href="https://tobaxxo.bandcamp.com/album/fucked-up-friends-3">TOBACCO - Fucked Up Friends 3</a></td>
+ <td class="aimg"><img src="images/albums/fucked_up_friends_3.jpg"/></td>
+ </tr>
+ <tr>
+ <td class="aimg"><img src="images/albums/vast.png"/></td>
+ <td class="ala"><a href="https://waterflame.bandcamp.com/album/vast">Waterflame - Vast</a></td>
+ </tr>
+ <tr>
+ <td class="ara"><a href="https://music.businesscasual.biz/album/millennialism">NYSE - MILLENNIALISM</a></td>
+ <td class="aimg"><img src="images/albums/millenialism.jpg"/></td>
+ </tr>
+ <tr>
+ <td class="aimg"><img src="images/albums/concrete_and_gold.jpg"/></td>
+ <td class="ala"><a href="https://www.foofighters.com/">Foo Fighters - Concrete and Gold</a></td>
+ </tr>
+ <tr>
+ <td class="ara"><a href="https://greenday.com/">Green Day - Revolution Radio</a></td>
+ <td class="aimg"><img src="images/albums/revolution_radio.jpg"/></td>
+ </tr>
+ <tr>
+ <td class="aimg"><img src="images/albums/aeon_core.jpg"/></td>
+ <td class="ala"><a href="https://perctrax.bandcamp.com/album/aeon-core">Scalameriya - Aeon Core</a></td>
+ </tr>
+ </table>
+</div> \ No newline at end of file
diff --git a/old/2/pages/stats.html b/old/2/pages/stats.html
new file mode 100644
index 0000000..041225a
--- /dev/null
+++ b/old/2/pages/stats.html
@@ -0,0 +1,95 @@
+
+
+<h1 id="header">Stats</h1>
+<div class="section">
+ <table id="statstable">
+ <tr>
+ <td>Height</td>
+ <td>191cm</td>
+ </tr>
+ <tr>
+ <td>Storage space</td>
+ <td>4.9TiB</td>
+ </tr>
+ <tr>
+ <td>Packages</td>
+ <td>1451</td>
+ </tr>
+ <tr>
+ <td>Desktop environment</td>
+ <td>KDE Plasma</td>
+ </tr>
+ <tr>
+ <td>CDs owned</td>
+ <td>6</td>
+ </tr>
+ <tr>
+ <td>Consoles modded</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>Computers upgraded</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>Computers downgraded</td>
+ <td><span class=hoverable>1<span class="tooltip">I upgraded my old laptop with a second hard drive, then transplanted the drive into my new PC later when I was building it. All my stuff was on the secondary drive, I figured why bother transferring it?</span></span></td>
+ </tr>
+ <tr>
+ <td>Websites</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>Talent</td>
+ <td style="font-family: monospace; color: red;">[Integer overflow error]</td>
+ </tr>
+ <tr>
+ <td>Bitches</td>
+ <td>0</td>
+ </tr>
+ <tr>
+ <td>Hotel</td>
+ <td>Trivago</td>
+ </tr>
+ <tr>
+ <td>Species</td>
+ <td><i>Bathynomus Giganteus</i></td>
+ </tr>
+ <tr>
+ <td>Pronouns</td>
+ <td>he/him</td>
+ </tr>
+ <tr>
+ <td>3.5mm headphone jack</td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td>Font family</td>
+ <td style="font-family: monospace;">monospace</td>
+ </tr>
+ <tr>
+ <td>Drop rates</td>
+ <td nowrap>1-3 bags of Doritos - 80%<br/>Wired earbuds - 10%<br/>Random Linux install media - 1%</td>
+ </tr>
+ <tr>
+ <td>Song</td>
+ <td style="padding-right: 0;"><audio controls="" style="width: 100%;"><source src="audio/bridges.mp3" type="audio/mpeg"></audio></td>
+ </tr>
+ <tr>
+ <td>Efficiency rating</td>
+ <td>80+ Gold</td>
+ </tr>
+ <tr>
+ <td>Home address</td>
+ <td>12h 28m 24.97s, +31° 28′ 37.7″</td>
+ </tr>
+ <tr>
+ <td>Time playing Space Engineers</td>
+ <td>587 hours</td>
+ </tr>
+ <tr>
+ <td>arch</td>
+ <td>btw</td>
+ </tr>
+ </table>
+</div>
diff --git a/old/2/script.js b/old/2/script.js
new file mode 100644
index 0000000..125b87c
--- /dev/null
+++ b/old/2/script.js
@@ -0,0 +1,102 @@
+function header(index) {
+ var rh = document.getElementById('randomheader');
+ var Title = document.getElementById('header').innerHTML;
+ if(rh != undefined) {
+ const titles = [
+ 'bruh moment',
+ 'Try reloading!',
+ 'Supports VPNs',
+ 'I use arch btw',
+ 'niceopod v2',
+ '<span class="rainbowtext">RGB Gaming Webpage</span>',
+ 'Stream deep twisty',
+ 'MySite.html',
+ 'Over Construction',
+ 'Real isopod hours',
+ 'Version 2.0: the Verbose Update',
+ 'depytwisty',
+ '[object Object]',
+ 'Uses cookies',
+ '* You found the [Moss]!',
+ 'Minceraft',
+ 'Best viewed with Firefox',
+ 'Isopod gaming',
+ 'Website of some guy',
+ 'your mom',
+ 'Badly programmed',
+ '<span class="flipped">Upside Down!</span>',
+ 'Fuck crypto',
+ 'Oh, you know ;)',
+ 'gamer (terminal)'
+ ];
+ if(index < 0 || index >= titles.length) {
+ index = Math.floor(Math.random() * titles.length);
+ }
+ var choice = titles[index];
+ Title = choice;
+ document.getElementById('randomheader').innerHTML = choice;
+ }
+ if(Title === "Stats") {
+ Title = `Stats: ${document.getElementsByTagName('tr').length}`;
+ document.getElementById('header').innerHTML = Title;
+ }
+ document.title = Title;
+ document.getElementById('header').style.animationName = 'happear';
+}
+function loadCafeStatus() {
+ statuscontainer = document.getElementById("status");
+ if(statuscontainer !== null) {
+ statuscontainer.innerHTML = '<div id="statuscafe"><div id="statuscafe-username"></div><div id="statuscafe-content"></div></div>';
+ fetch("https://status.cafe/users/niceopod/status.json")
+ .then( r => r.json() )
+ .then( r => {
+ if (!r.content.length) {
+ document.getElementById("statuscafe-content").innerHTML = "No status yet."
+ return
+ }
+ document.getElementById("statuscafe-username").innerHTML = '<a href="https://status.cafe/users/niceopod" target="_blank">' + r.author + '</a> ' + r.face + ' ' + r.timeAgo
+ document.getElementById("statuscafe-content").innerHTML = r.content
+ }
+ )
+ }
+}
+function getUrlVars() {
+ var vars = {};
+ var url = window.location.href;
+ if(window.location.hash !== "") {
+ url = url.substring(0, url.lastIndexOf('#'));
+ }
+ var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { //I copied this function from somewhere. I have no idea what this expression is doing. I'm scared of it
+ vars[key] = value;
+ });
+ return vars;
+}
+function page() {
+ var preferredTheme = window.localStorage.getItem("theme");
+ if(preferredTheme == undefined) {
+ preferredTheme = "default";
+ }
+ document.getElementById("theme").href = `themes/${preferredTheme}/style.css`;
+
+ document.getElementById("pretheme").remove();
+
+ var currentPage = getUrlVars()['page'];
+ if(currentPage == undefined) { currentPage = 'home'; }
+
+ if(currentPage.indexOf('#') > -1) {
+ currentPage = currentPage.substring(0, currentPage.lastIndexOf('#'));
+ }
+
+ fetch(`pages/${currentPage}.html`)
+ .then(response => response.text())
+ .then(data => { document.getElementById('centercolumn').innerHTML = data; if(document.getElementById('404') !== null) { window.location.replace('not_found.html'); } header(-69); loadCafeStatus(); scrollToHash();});
+}
+function switchTheme (theme) {
+ document.getElementById("theme").href = `themes/${theme}/style.css`;
+ window.localStorage.setItem("theme", theme);
+}
+function scrollToHash() {
+ if(window.location.hash !== "") {
+ document.getElementById(window.location.hash.substring(1)).scrollIntoView();
+ }
+} \ No newline at end of file
diff --git a/old/2/shared.css b/old/2/shared.css
new file mode 100644
index 0000000..c8db590
--- /dev/null
+++ b/old/2/shared.css
@@ -0,0 +1,224 @@
+body, html {
+ height: 100%;
+ font-family: var(--stdfont);
+}
+body {
+ margin: 0;
+ padding: 0;
+ color: var(--fontcolor);
+}
+#main {
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ margin: 0;
+ padding: 0;
+}
+#centercolumn {
+ min-height: 100%;
+ height: fit-content;
+ width: 80%;
+ max-width: 650px;
+}
+#header {
+ padding: 40px;
+ background-image: url("images/isopod_with_aviators.png");
+ background-size: 128px;
+ background-repeat: no-repeat;
+ background-position: 90% bottom;
+}
+#themeselector {
+ position: fixed;
+ left: -250px;
+ height: 100%;
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ animation-fill-mode: both;
+}
+#themeselector a {
+ cursor: pointer;
+}
+@keyframes tsappear {
+ from {left: -250px;}
+ to {left: 0px;}
+}
+@keyframes tsdisappear {
+ from {left: 0px;}
+ to {left: -250px;}
+}
+#nav {
+ position: fixed;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ height: 100%;
+ z-index: 2;
+}
+#nav a {
+ color: black;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ margin-left: 0;
+ margin-right: 0;
+ font-size: 0;
+ padding: 10px;
+ transition-duration: 0.2s;
+}
+#nav svg {
+ width: 32px;
+ height: 32px;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #nav {
+ flex-direction: row;
+ height: initial;
+ width: 100%;
+ }
+ #header {
+ margin-top: 60px;
+ }
+ #nav a {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 5px;
+ margin-right: 5px;
+ }
+}
+@media (max-width: 700px) {
+ #centercolumn {
+ width: 100%;
+ padding-left: 10%;
+ padding-right: 10%;
+ box-shadow: none;
+ }
+ body {
+ overflow-x: hidden;
+ }
+ #header {margin-left: auto; margin-right: auto;}
+}
+@media (max-width: 600px) {
+ .tdc {display: none;}
+}
+.hoverable {
+ color: var(--linkcolor);
+}
+.hoverable:hover {
+ color: var(--linkhovercolor);
+}
+.tooltip {
+ font-size: 14pt;
+ color: var(--fontcolor);
+ position: absolute;
+ display: none;
+ max-width: 600px;
+}
+.hoverable:hover .tooltip {
+ display: initial;
+}
+#buttons {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ font-size: 0;
+ margin-bottom: 16px;
+}
+#buttons img {
+ margin: 2px;
+}
+td:nth-child(2n) {
+ padding-left: 10px;
+}
+.rainbowtext {
+ animation-name: rainbow-text;
+ animation-duration: 20s;
+ animation-iteration-count: infinite;
+}
+.flipped {
+ display: inline-block;
+ transform: rotate(180deg);
+}
+#albums {
+ padding-top: 30px;
+ margin-bottom: 30px;
+}
+#albums img {
+ max-width: 100%;
+}
+#albums td {
+ padding: 0;
+ width: 50%;
+}
+#albums .ara {
+ text-align: right;
+ padding: 15px;
+}
+#albums .ala {
+ text-align: left;
+ padding: 15px;
+}
+#albums .aimg {
+ font-size: 0;
+}
+#linktable td {
+ padding: 10px 0;
+}
+.serif {
+ font-family: serif;
+}
+.centered {
+ text-align: center;
+}
+.spaced_on_hover, .spaced_on_hover a {
+ transition-duration: 0.5s;
+}
+.spaced_on_hover:hover {
+ letter-spacing: 0.4ch;
+}
+table {
+ border-collapse: collapse;
+}
+#chatbox {
+ position: fixed;
+ height: fit-content;
+ width: 18rem;
+ padding: 0;
+ bottom: calc(50% - 450px / 2);
+ right: -18rem;
+ transition-duration: 1s;
+}
+#chatbox:hover {
+ right: 0.5rem;
+}
+#chatboxpulltab {
+ min-width: 3rem;
+ min-height: 3rem;
+ position: absolute;
+ bottom: calc(50% - 1.5rem);
+ left: -3rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+#statstable {
+ width: 100%;
+}
+#statstable td {
+ padding: .5rem 1rem;
+}
+#statstable tr:nth-child(2n+1) {
+ background: rgba(255, 255, 255, 0.1);
+}
+#statuscafe-username {
+ font-size: 0.85em;
+ margin-bottom: 0.2rem;
+}
+#changelogwindow {
+ max-height: 15rem;
+ overflow-y: scroll;
+}
+#changelogwindow p:first-child {
+ margin-top: 0;
+} \ No newline at end of file
diff --git a/old/2/themes/alterra/bg.jpg b/old/2/themes/alterra/bg.jpg
new file mode 100644
index 0000000..56e94f2
--- /dev/null
+++ b/old/2/themes/alterra/bg.jpg
Binary files differ
diff --git a/old/2/themes/alterra/style.css b/old/2/themes/alterra/style.css
new file mode 100644
index 0000000..f046a8e
--- /dev/null
+++ b/old/2/themes/alterra/style.css
@@ -0,0 +1,193 @@
+:root {
+ --stdfont: 'Ubuntu', Century Gothic, CenturyGothic, AppleGothic, sans-serif;
+ --fontcolor: white;
+ --linkcolor: #35e0be;
+ --linkhovercolor: #64cdeb;
+}
+body {
+ background-image: url("bg.jpg");
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+ overflow-x: hidden;
+}
+#header {
+ font-family: 'Days One', var(--stdfont);
+ text-align: center;
+ font-size: 3.4em;
+ color: var(--fontcolor);
+ text-shadow: 4px 4px 4px black;
+ margin-bottom: 5px;
+ margin-top: 0;
+ animation-duration: 1s;
+ animation-fill-mode: both;
+ text-transform: uppercase;
+ opacity: 0;
+ max-width: 750px;
+ padding-left: 51px;
+ padding-right: 51px;
+ padding-top: 40px;
+ padding-bottom: 40px;
+}
+@keyframes happear {
+ from {
+ opacity: 0;
+ margin-left: -50px;
+ margin-right: -50px;
+ } to {
+ opacity: 1;
+ margin-left: -50px;
+ margin-right: -50px;
+ }
+}
+#centercolumn {
+ width: fit-content;
+ max-width: fit-content;
+ padding: 0;
+}
+.section {
+ font-size: 1.2em;
+ background-image: radial-gradient(#149489c7 2px, transparent 2px);
+ background-size: 100px 100px;
+ background-color: #0020289a;
+ padding: 20px 50px;
+ border-radius: 50px;
+ border: 2px solid rgb(152, 222, 255);
+ box-shadow: 0 0 45px blue inset, 0 0 10px blue;
+ margin-bottom: 35px;
+ width: 650px;
+}
+.section h2 {
+ color: #64cdeb;
+ border-bottom: 2px solid #cdd649;
+ width: fit-content;
+ font-family: 'Days One', var(--stdfont);
+}
+.section h3 {
+ color: #35e0be;
+ font-family: 'Days One', var(--stdfont);
+ font-weight: 400;
+ font-size: 0.8em;
+ margin-top: -20px;
+}
+.section h4 {
+ font-size: 1.1em;
+ color: #64cdeb;
+ border-bottom: 2px solid #cdd649;
+ width: fit-content;
+ font-family: 'Days One', var(--stdfont);
+}
+a {
+ color: var(--linkcolor);
+ text-decoration: none;
+ transition-duration: 0.2s;
+}
+a:hover {
+ color: var(--linkhovercolor);
+}
+#themeselector {
+ background-image: radial-gradient(#149489c7 2px, transparent 2px);
+ background-size: 100px 100px;
+ background-color: #0020284b;
+ border-right: 2px solid rgb(152, 222, 255);
+ box-shadow: -45px 0 45px -45px blue inset, 0 0 10px blue;
+ padding-left: 90px;
+ padding-right: 50px;
+ font-size: 1.2em;
+ animation-duration: 0.7s;
+}
+#nav a {
+ color: gainsboro;
+ border: 2px solid #10b0b3e3;
+ box-shadow: 0 0 14px #10b0b3e3 inset, 0 0 1px 6px #00202877;
+ border-radius: 50%;
+ background-color: #00202877;
+ margin-left: 6px;
+}
+#nav a:hover {
+ background-color: #ffffff1c;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+ #nav a {
+ margin-left: 0;
+ margin-top: 6px;
+ }
+}
+@media (max-width: 750px) {
+ #centercolumn {
+ width: 100%;
+ max-width: 100%;
+ }
+ .section {
+ width: 100%;
+ max-width: 100%;
+ padding: 20px 0;
+ border-radius: 0;
+ border-left: none;
+ border-right: none;
+ box-shadow: 0 -45px 45px -45px blue inset, 0 45px 45px -45px blue inset, 0 0 10px blue;
+ }
+}
+.hoverable {
+ transition-duration: 0.2s;
+}
+.tooltip {
+ background-image: radial-gradient(#149489c7 2px, transparent 2px);
+ background-size: 100px 100px;
+ background-color: #0020289a;
+ padding: 10px 20px;
+ border-radius: 25px;
+ border: 2px solid rgb(152, 222, 255);
+ box-shadow: 0 0 24px blue inset, 0 0 6px blue;
+ margin-left: -5px;
+}
+.emph {
+ font-style: italic;
+}
+@keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);;}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+}
+table {
+ margin-bottom: 30px;
+}
+#albums {
+ margin-top: 0;
+ padding: 50px;
+}
+#albums table {
+ margin-bottom: 0;
+}
+#statstable {
+ margin-bottom: 0;
+}
+#linktable {
+ margin-bottom: 15px;
+}
+#chatboxpulltab {
+ left: -5rem;
+ padding: 1rem;
+}
+#chatboxpulltab svg {
+ color: gainsboro;
+ border: 2px solid #10b0b3e3;
+ box-shadow: 0 0 14px #10b0b3e3 inset, 0 0 1px 6px #00202877;
+ border-radius: 50%;
+ background-color: #00202877;
+ padding: 10px;
+ height: 32px;
+ width: 32px;
+} \ No newline at end of file
diff --git a/old/2/themes/deeptwisty/bg.png b/old/2/themes/deeptwisty/bg.png
new file mode 100644
index 0000000..431a733
--- /dev/null
+++ b/old/2/themes/deeptwisty/bg.png
Binary files differ
diff --git a/old/2/themes/deeptwisty/style.css b/old/2/themes/deeptwisty/style.css
new file mode 100644
index 0000000..a99876d
--- /dev/null
+++ b/old/2/themes/deeptwisty/style.css
@@ -0,0 +1,127 @@
+:root {
+ --stdfont: 'Ubuntu', Century Gothic, CenturyGothic, AppleGothic, sans-serif;
+ --fontcolor: gainsboro;
+ --linkcolor: #226dff;
+ --linkhovercolor: #5cc3ff;
+}
+body {
+ background: black url("bg.png");
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+}
+#centercolumn {
+ background: #000000f2;;
+ margin-top: -20px;
+ padding-top: 20px;
+ box-shadow: 0 0px 45px 70px #000000f2;
+}
+#header {
+ text-align: center;
+ font-size: 3.4em;
+ color: transparent;
+ -webkit-text-stroke-color: var(--fontcolor);
+ -webkit-text-stroke-width: 2px;
+ text-shadow: 0 0 12px white;
+ margin-bottom: -10px;
+ margin-top: 0;
+ animation-duration: 2s;
+ animation-fill-mode: both;
+ opacity: 0;
+}
+@keyframes happear {
+ from {
+ opacity: 0;
+ } to {
+ opacity: 1;
+ }
+}
+.section {
+ width: 100%;
+ font-size: 1.2em;
+}
+.section h2 {
+ text-shadow: 0 0 7px white;
+}
+.section h3 {
+ text-shadow: 0 0 2px white;
+ font-weight: 400;
+ font-size: 0.8em;
+ margin-top: -20px;
+}
+.section h4 {
+ text-shadow: 0 0 4px white;
+ font-size: 1.2em;
+}
+a {
+ color: var(--linkcolor);
+ text-shadow: 0 0 3px var(--linkcolor);
+ text-decoration: none;
+ transition-duration: 0.2s;
+}
+a:hover {
+ color: var(--linkhovercolor);
+ text-shadow: 0 0 7px var(--linkhovercolor);
+}
+#themeselector {
+ background: #000000f2;
+ box-shadow: 0 0 20px 20px #000000f2;
+ padding-left: 90px;
+ padding-right: 20px;
+ font-size: 1.2em;
+ animation-duration: 0.7s;
+}
+#nav {
+ background: #000000f2;
+ box-shadow: 0 0 20px 20px #000000f2;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+}
+#nav a {
+ color: gainsboro;
+}
+#nav a:hover {
+ background-color: #ffffff10;
+ box-shadow: 0 0 6px 6px #ffffff10;
+}
+.hoverable {
+ text-shadow: 0 0 3px var(--linkcolor);
+ transition-duration: 0.2s;
+}
+.hoverable:hover {
+ text-shadow: 0 0 7px var(--linkhovercolor);
+}
+.tooltip {
+ background-color: #000000f2;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 8px;
+ padding-right: 8px;
+ box-shadow: 0 0 10px 10px #000000f2;
+}
+.hoverable:hover .tooltip {
+ text-shadow: none;
+}
+.emph {
+ font-style: italic;
+}
+@keyframes rainbow-text {
+ 100%,0%{-webkit-text-stroke-color: rgb(255,0,0); text-shadow: 0 0 12px rgb(216, 1, 1);}
+ 8%{-webkit-text-stroke-color: rgb(255,127,0); text-shadow: 0 0 12px rgb(211, 105, 0);}
+ 16%{-webkit-text-stroke-color: rgb(255,255,0); text-shadow: 0 0 12px rgb(214, 214, 0);}
+ 25%{-webkit-text-stroke-color: rgb(127,255,0); text-shadow: 0 0 12px rgb(105, 211, 0);}
+ 33%{-webkit-text-stroke-color: rgb(0,255,0); text-shadow: 0 0 12px rgb(0, 204, 0);;}
+ 41%{-webkit-text-stroke-color: rgb(0,255,127); text-shadow: 0 0 12px rgb(0, 209, 105);}
+ 50%{-webkit-text-stroke-color: rgb(0,255,255); text-shadow: 0 0 12px rgb(0, 202, 202);}
+ 58%{-webkit-text-stroke-color: rgb(0,127,255); text-shadow: 0 0 12px rgb(0, 103, 206);}
+ 66%{-webkit-text-stroke-color: rgb(0,0,255); text-shadow: 0 0 12px rgb(0, 0, 206);}
+ 75%{-webkit-text-stroke-color: rgb(127,0,255); text-shadow: 0 0 12px rgb(103, 0, 206);}
+ 83%{-webkit-text-stroke-color: rgb(255,0,255); text-shadow: 0 0 12px rgb(211, 0, 211);}
+ 91%{-webkit-text-stroke-color: rgb(255,0,127); text-shadow: 0 0 12px rgb(211, 0, 105);}
+}
+div#buttons {
+ margin-top: 2rem;
+} \ No newline at end of file
diff --git a/old/2/themes/default/bg.jpg b/old/2/themes/default/bg.jpg
new file mode 100644
index 0000000..feeaadb
--- /dev/null
+++ b/old/2/themes/default/bg.jpg
Binary files differ
diff --git a/old/2/themes/default/div-bg.png b/old/2/themes/default/div-bg.png
new file mode 100644
index 0000000..4d45b2c
--- /dev/null
+++ b/old/2/themes/default/div-bg.png
Binary files differ
diff --git a/old/2/themes/default/style.css b/old/2/themes/default/style.css
new file mode 100644
index 0000000..08bfef1
--- /dev/null
+++ b/old/2/themes/default/style.css
@@ -0,0 +1,127 @@
+:root {
+ --stdfont: 'Raleway', Century Gothic, CenturyGothic, AppleGothic, sans-serif;
+ --fontcolor: white;
+ --linkcolor: #df1955;
+ --linkhovercolor: #00ffd5;
+}
+body {
+ background-image: url("bg.jpg");
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+}
+#centercolumn {
+ background: #222222 url("div-bg.png");
+ padding-left: 50px;
+ padding-right: 50px;
+ margin-top: -20px;
+ padding-top: 20px;
+ box-shadow: 0 10px 8px 4px black inset;
+}
+#header {
+ text-align: center;
+ font-size: 3.4em;
+ color: var(--fontcolor);
+ margin-bottom: -10px;
+ margin-top: 0;
+ animation-duration: 1s;
+ animation-fill-mode: both;
+ opacity: 0;
+ text-shadow: 4px 4px 4px black;
+}
+@keyframes happear {
+ from {
+ opacity: 0;
+ letter-spacing: 0.2ch;
+ margin-left: -200px;
+ margin-right: -200px;
+ } to {
+ opacity: 1;
+ letter-spacing: normal;
+ margin-left: -50px;
+ margin-right: -50px;
+ }
+}
+.section {
+ width: 100%;
+ font-size: 1.2em;
+}
+.section h2 {
+ text-shadow: 2px 2px 3px black;
+}
+.section h3 {
+ text-shadow: 1px 1px 2px black;
+ font-weight: 400;
+ font-size: 0.8em;
+ margin-top: -20px;
+}
+.section h4 {
+ font-size: 1.2em;
+ text-shadow: 2px 2px 3px black;
+}
+a {
+ color: var(--linkcolor);
+ text-decoration: none;
+ transition-duration: 0.2s;
+}
+a:hover {
+ color: var(--linkhovercolor);
+}
+#themeselector {
+ background: #222222 url("div-bg.png");
+ box-shadow: 0 0 8px 4px black;
+ padding-left: 90px;
+ padding-right: 40px;
+ font-size: 1.2em;
+ animation-duration: 0.7s;
+}
+#nav {
+ background: #222222 url("div-bg.png");
+ box-shadow: 0 0 8px 4px black;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+}
+#nav a:hover {
+ background-color: #ffffff10;
+}
+#nav a {
+ color: gainsboro;
+}
+.hoverable {
+ transition-duration: 0.2s;
+}
+.tooltip {
+ background-color: #222222;
+ border: 2px outset gainsboro;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 8px;
+ padding-right: 8px;
+ box-shadow: 2px 2px 8px black;
+}
+.emph {
+ font-style: italic;
+}
+@keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+}
+#albums img {
+ box-shadow: 2px 2px 8px 2px black;
+}
+div#buttons {
+ margin-top: 2rem;
+} \ No newline at end of file
diff --git a/old/2/themes/geocities/beam.png b/old/2/themes/geocities/beam.png
new file mode 100644
index 0000000..839d2bc
--- /dev/null
+++ b/old/2/themes/geocities/beam.png
Binary files differ
diff --git a/old/2/themes/geocities/bg.gif b/old/2/themes/geocities/bg.gif
new file mode 100644
index 0000000..8471f83
--- /dev/null
+++ b/old/2/themes/geocities/bg.gif
Binary files differ
diff --git a/old/2/themes/geocities/butterfly.gif b/old/2/themes/geocities/butterfly.gif
new file mode 100644
index 0000000..baa965e
--- /dev/null
+++ b/old/2/themes/geocities/butterfly.gif
Binary files differ
diff --git a/old/2/themes/geocities/butterflyrockplant.gif b/old/2/themes/geocities/butterflyrockplant.gif
new file mode 100644
index 0000000..99d65a3
--- /dev/null
+++ b/old/2/themes/geocities/butterflyrockplant.gif
Binary files differ
diff --git a/old/2/themes/geocities/fire.gif b/old/2/themes/geocities/fire.gif
new file mode 100644
index 0000000..d8bf16b
--- /dev/null
+++ b/old/2/themes/geocities/fire.gif
Binary files differ
diff --git a/old/2/themes/geocities/ocean-div.gif b/old/2/themes/geocities/ocean-div.gif
new file mode 100644
index 0000000..b757786
--- /dev/null
+++ b/old/2/themes/geocities/ocean-div.gif
Binary files differ
diff --git a/old/2/themes/geocities/orb.gif b/old/2/themes/geocities/orb.gif
new file mode 100644
index 0000000..52e9182
--- /dev/null
+++ b/old/2/themes/geocities/orb.gif
Binary files differ
diff --git a/old/2/themes/geocities/rainbowball.gif b/old/2/themes/geocities/rainbowball.gif
new file mode 100644
index 0000000..9261df9
--- /dev/null
+++ b/old/2/themes/geocities/rainbowball.gif
Binary files differ
diff --git a/old/2/themes/geocities/rose.gif b/old/2/themes/geocities/rose.gif
new file mode 100644
index 0000000..3f12a4b
--- /dev/null
+++ b/old/2/themes/geocities/rose.gif
Binary files differ
diff --git a/old/2/themes/geocities/snail.gif b/old/2/themes/geocities/snail.gif
new file mode 100644
index 0000000..460f0e5
--- /dev/null
+++ b/old/2/themes/geocities/snail.gif
Binary files differ
diff --git a/old/2/themes/geocities/snake.gif b/old/2/themes/geocities/snake.gif
new file mode 100644
index 0000000..8e1330b
--- /dev/null
+++ b/old/2/themes/geocities/snake.gif
Binary files differ
diff --git a/old/2/themes/geocities/star.gif b/old/2/themes/geocities/star.gif
new file mode 100644
index 0000000..5f06739
--- /dev/null
+++ b/old/2/themes/geocities/star.gif
Binary files differ
diff --git a/old/2/themes/geocities/star2.gif b/old/2/themes/geocities/star2.gif
new file mode 100644
index 0000000..f8321d4
--- /dev/null
+++ b/old/2/themes/geocities/star2.gif
Binary files differ
diff --git a/old/2/themes/geocities/star3.gif b/old/2/themes/geocities/star3.gif
new file mode 100644
index 0000000..289f8b6
--- /dev/null
+++ b/old/2/themes/geocities/star3.gif
Binary files differ
diff --git a/old/2/themes/geocities/star4.gif b/old/2/themes/geocities/star4.gif
new file mode 100644
index 0000000..b50d808
--- /dev/null
+++ b/old/2/themes/geocities/star4.gif
Binary files differ
diff --git a/old/2/themes/geocities/style.css b/old/2/themes/geocities/style.css
new file mode 100644
index 0000000..a38d2ba
--- /dev/null
+++ b/old/2/themes/geocities/style.css
@@ -0,0 +1,138 @@
+:root {
+ --stdfont: sans-serif;
+ --headerfont: serif, var(--stdfont);
+}
+body {
+ background: url('snail.gif') no-repeat fixed bottom 0 left calc(50% - 750px), url('world.gif') no-repeat fixed top 200px left calc(50% + 550px), url('sun.gif') fixed no-repeat top 69px left 100px, url('torch.gif') no-repeat fixed bottom left calc(50% - 350px), url('butterflyrockplant.gif') no-repeat fixed bottom -10px left calc(50% + 500px), url('star4.gif') no-repeat fixed bottom 200px left calc(50% - 800px), url('star3.gif') no-repeat fixed top 69px left calc(50% + 800px), url('star2.gif') no-repeat fixed top 300px right calc(50% + 700px), url('rose.gif') bottom -20px left calc(50% - 600px) fixed no-repeat, url('star.gif') no-repeat fixed bottom 300px left calc(50% + 630px), url('fire.gif') no-repeat bottom left 10px fixed, url('butterfly.gif') no-repeat fixed bottom 150px left calc(50% - 500px), url('snake.gif') fixed no-repeat bottom left calc(50% + 840px), url('bg.gif') fixed;
+ font-family: var(--stdfont);
+ color: gainsboro;
+}
+#centercolumn {
+ background: url('rainbowball.gif') 52px 30px no-repeat, url('beam.png') repeat-y 75px 0;
+}
+.section {
+ width: 100%;
+ font-size: 1.1em;
+ background: #000000f9;
+ padding: 10px 30px;
+ border: 4px outset rgb(48, 4, 119);
+ margin-bottom: 40px;
+}
+.section:last-of-type {
+ background: #000000f9 url('ocean-div.gif') repeat-x bottom center;
+}
+#buttons {
+ padding-bottom: 30px;
+}
+a {
+ color: gold;
+}
+a:visited {
+ color: goldenrod;
+}
+#header {
+ font-family: 'Orbitron', sans-serif;
+ font-weight: 700;
+ text-align: center;
+ font-size: 2.5em;
+ width: 100%;
+}
+.section h2 {
+ background: url('orb.gif') no-repeat center right;
+ font-family: var(--headerfont);
+ font-size: 1.8em;
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+.section h3 {
+ font-family: var(--headerfont);
+ margin-top: -10px;
+ font-size: 0.8em;
+}
+.section h4 {
+ font-family: var(--headerfont);
+ font-size: 1.2em;
+}
+.section table {
+ margin-bottom: 20px;
+}
+#linktable {
+ margin-bottom: initial;
+}
+#nav a {
+ color: gainsboro;
+}
+#themeselector {
+ padding-left: 90px;
+ padding-right: 40px;
+ font-size: 1.1em;
+ animation-duration: 0.7s;
+ background-color: #000000f9;
+ border-right: 4px outset rgb(48, 4, 119);
+}
+#themeselector a {
+ color: gold;
+ text-decoration: underline;
+}
+#themeselector h3 {
+ font-family: var(--headerfont);
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+ #centercolumn {
+ padding: 0;
+ }
+ .section {
+ width: calc(100% - 68px);
+ }
+}
+.hoverable {
+ color: #0000EE;
+ text-decoration: underline;
+}
+.hoverable:hover {
+ color: #551A8B;
+}
+.tooltip {
+ color: black;
+ background-color: white;
+ border: 1px solid black;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+.emph {
+ font-style: italic;
+}
+.serif {
+ font-family: serif;
+}
+.hoverable {
+ color: gold;
+}
+.hoverable:hover {
+ color: goldenrod;
+}
+.hoverable .tooltip {
+ color: gainsboro;
+ padding: 6px 12px;
+ background-color: #000000f9;
+ border: 3px outset gold;
+}
+@keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);;}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+} \ No newline at end of file
diff --git a/old/2/themes/geocities/sun.gif b/old/2/themes/geocities/sun.gif
new file mode 100644
index 0000000..946b0e7
--- /dev/null
+++ b/old/2/themes/geocities/sun.gif
Binary files differ
diff --git a/old/2/themes/geocities/torch.gif b/old/2/themes/geocities/torch.gif
new file mode 100644
index 0000000..93e5e59
--- /dev/null
+++ b/old/2/themes/geocities/torch.gif
Binary files differ
diff --git a/old/2/themes/geocities/world.gif b/old/2/themes/geocities/world.gif
new file mode 100644
index 0000000..9cbe4c9
--- /dev/null
+++ b/old/2/themes/geocities/world.gif
Binary files differ
diff --git a/old/2/themes/gruvbox/bg.png b/old/2/themes/gruvbox/bg.png
new file mode 100644
index 0000000..528f35b
--- /dev/null
+++ b/old/2/themes/gruvbox/bg.png
Binary files differ
diff --git a/old/2/themes/gruvbox/style.css b/old/2/themes/gruvbox/style.css
new file mode 100644
index 0000000..3fee1a5
--- /dev/null
+++ b/old/2/themes/gruvbox/style.css
@@ -0,0 +1,121 @@
+:root {
+ --stdfont: 'Montserrat', Century Gothic, CenturyGothic, AppleGothic, sans-serif;
+ --fontcolor: #ebdbb2;
+ --linkcolor: #458488;
+ --linkhovercolor: #83a598;
+}
+body {
+ background: #282828 url('bg.png');
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+}
+#centercolumn {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+#header {
+ text-align: center;
+ font-size: 3.4em;
+ color: var(--fontcolor);
+ margin-bottom: 10px;
+ margin-top: 0;
+ animation-duration: 1s;
+ animation-fill-mode: both;
+ opacity: 0;
+ min-width: 100%;
+ margin-left: -1000px;
+ margin-right: -1000px;
+}
+@keyframes happear {
+ from {
+ opacity: 0;
+ letter-spacing: 0.2ch;
+ } to {
+ opacity: 1;
+ letter-spacing: normal;
+ }
+}
+.section {
+ padding: 30px;
+ border-radius: 16px;
+ background: #1d2021f1;
+ width: 100%;
+ font-size: 1.2em;
+ margin-bottom: 20px;
+}
+.section h2 {
+ margin-top: 0;
+}
+.section h3 {
+ font-weight: 400;
+ font-size: 0.8em;
+ margin-top: -20px;
+}
+.section h4 {
+ font-size: 1.2em;
+}
+.section p {
+ margin-bottom: 0;
+}
+a {
+ color: var(--linkcolor);
+ text-decoration: none;
+ transition-duration: 0.2s;
+}
+a:hover {
+ color: var(--linkhovercolor);
+}
+#themeselector {
+ background: #1d2021f1;
+ padding-left: 90px;
+ padding-right: 40px;
+ font-size: 1.2em;
+ animation-duration: 0.7s;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+ #header {
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%;
+ }
+}
+#nav a {
+ color: var(--fontcolor);
+ border-radius: 50%;
+}
+#nav a:hover {
+ transform: rotate(-6deg);
+ background-color: #ffffff10;
+}
+#nav svg {
+ width: 32px;
+ height: 32px;
+}
+.hoverable {
+ transition-duration: 0.2s;
+}
+.tooltip {
+ background-color: #1d2021f1;
+ border-radius: 16px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+ padding-left: 11px;
+ padding-right: 11px;
+ box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.267);
+}
+.emph {
+ font-style: italic;
+}
+@keyframes rainbow-text {
+ 100%,0%{color: #cc241d; text-shadow: 0 0 4px #cc241d;}
+ 8%{color: #fe8019; text-shadow: 0 0 4px #fe8019;}
+ 16%{color: #fabd2f; text-shadow: 0 0 4px #fabd2f;}
+ 33%{color: #b8bb26; text-shadow: 0 0 4px #b8bb26;}
+ 58%{color: #458588; text-shadow: 0 0 4px #458588;}
+ 75%{color: #b16286; text-shadow: 0 0 4px #b16286;}
+} \ No newline at end of file
diff --git a/old/2/themes/none/style.css b/old/2/themes/none/style.css
new file mode 100644
index 0000000..82ba913
--- /dev/null
+++ b/old/2/themes/none/style.css
@@ -0,0 +1,62 @@
+.section {
+ width: 100%;
+ font-size: 1.2em;
+}
+.section h3 {
+ margin-top: -10 px;
+}
+#themeselector {
+ padding-left: 90px;
+ padding-right: 40px;
+ font-size: 1.2em;
+ animation-duration: 0.7s;
+ background-color: white;
+}
+#themeselector a {
+ color: #0000EE;
+ text-decoration: underline;
+}
+@media (max-width: 900px) or (orientation: portrait) {
+ #themeselector {
+ padding-left: 40px;
+ }
+}
+.hoverable {
+ color: #0000EE;
+ text-decoration: underline;
+}
+.hoverable:hover {
+ color: #551A8B;
+}
+.tooltip {
+ color: black;
+ background-color: white;
+ border: 1px solid black;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+.emph {
+ font-style: italic;
+}
+.serif {
+ font-family: sans-serif;
+}
+@keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);;}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+}
+div#buttons {
+ margin-top: 2rem;
+} \ No newline at end of file
diff --git a/seasonal.php b/seasonal.php
new file mode 100644
index 0000000..9954795
--- /dev/null
+++ b/seasonal.php
@@ -0,0 +1,9 @@
+<?php
+if($_SERVER["REQUEST_URI"] == "/seasonal.php") {
+ http_response_code(403);
+ die();
+}
+if(date('m') == 10) {
+ echo '<style type="text/css">#bubblecolumn {display: none;} body {background-color: black;} a {color: orange;} a:hover {color: yellow;} #leftsidebg, #rightsidebg {filter: grayscale(100%);}</style>';
+}
+?> \ No newline at end of file
diff --git a/stats/bg.jpg b/stats/bg.jpg
new file mode 100644
index 0000000..80160c8
--- /dev/null
+++ b/stats/bg.jpg
Binary files differ
diff --git a/stats/bg.jxl b/stats/bg.jxl
new file mode 100644
index 0000000..33477c6
--- /dev/null
+++ b/stats/bg.jxl
Binary files differ
diff --git a/stats/index.php b/stats/index.php
new file mode 100644
index 0000000..eb17786
--- /dev/null
+++ b/stats/index.php
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Stats</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ #statstable {
+ width: 100%;
+ }
+ #statstable td:first-child {
+ padding-left: calc(var(--stdpadding) / 2);
+ }
+ #statstable tr:nth-child(2n+1) {
+ background-color: #ffffff11;
+ }
+ @media only screen and (hover: none) {
+ #statstable td:first-child {
+ font-weight: bold;
+ }
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(); ?>
+ <h1>stat tracker</h1>
+ <h2 id="caption">Powered by RealTrue&trade; StatAI&trade;</h2>
+ <table id="statstable">
+ <tbody><tr>
+ <td>Height</td>
+ <td>194cm</td>
+ </tr>
+ <tr>
+ <td>Storage space</td>
+ <td>47TiB</td>
+ </tr>
+ <tr>
+ <td>Desktop environment</td>
+ <td>GNOME (Wayland)</td>
+ </tr>
+ <tr>
+ <td>Layout</td>
+ <td>ANSI 75% + Knob + External numpad</td>
+ </tr>
+ <tr>
+ <td>Switches</td>
+ <td>Keychron K Pro Brown</td>
+ </tr>
+ <tr>
+ <td>Firmware</td>
+ <td>QMK</td>
+ </tr>
+ <tr>
+ <td>RGB</td>
+ <td>Yes</td>
+ </tr>
+ <tr>
+ <td>CDs owned</td>
+ <td>164</td>
+ </tr>
+ <tr>
+ <td>Consoles modded</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>Computers upgraded</td>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td>Computers downgraded</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>Domains owned</td>
+ <td title="deeptwisty.com, isopod.cool, isopod.zone, bathynomus.xyz, flatfuckfri.day, isopod.mov">6</td>
+ </tr>
+ <tr>
+ <td>Talent</td>
+ <td style="font-family: mono; color: red;">[Integer overflow error]</td>
+ </tr>
+ <tr>
+ <td>Bitches</td>
+ <td>0</td>
+ </tr>
+ <tr>
+ <td>Species</td>
+ <td><i>Bathynomus Giganteus</i></td>
+ </tr>
+ <tr>
+ <td>Gender</td>
+ <td><?php
+ $boogeraids = array(
+ 'Unclear',
+ '404 Not Found',
+ '502 Bad Gateway',
+ 'I dropped it behind the sofa, sorry',
+ 'invalid null pointer',
+ 'what does that mean',
+ 'You fuckin\' figure it out',
+ 'Not my problem lol',
+ '[]',
+ 'I lost it in the accident',
+ 'Listed <a href="https://genders.wtf">here</a>',
+ 'AMD Ryzen 7 5700G, 32GB DDR4-3600 RAM, AMD Radeon RX 6800XT GPU, 500GB NVMe SSD, 2TB NVMe SSD, 4TB HDD',
+ 'I forgor 💀',
+ '<i>Bathynomus Giganteus</i>',
+ 'I\'ll figure it out later',
+ 'gay',
+ '//TODO'
+ );
+ echo $boogeraids[array_rand($boogeraids)];
+ ?></td>
+ </tr>
+ <tr>
+ <td>3.5mm headphone jack</td>
+ <td>yes</td>
+ </tr>
+ <tr>
+ <td>Audio channels</td>
+ <td>mono</td>
+ </tr>
+ <tr>
+ <td>Font family</td>
+ <td style="font-family: b612_mono, mono, monospace;"><a href="https://b612-font.com/">mono</a></td>
+ </tr>
+ <tr>
+ <td>Sodium glutamate</td>
+ <td>7.1 surround</td>
+ </tr>
+ <tr>
+ <td>Drop rates</td>
+ <td style="white-space:nowrap;">1-3 bags of Doritos - 80% <br>Wired earbuds - 10% <br>Random Linux install media - 1%</td>
+ </tr>
+ <tr>
+ <td>Efficiency rating</td>
+ <td>80+ Gold</td>
+ </tr>
+ <tr>
+ <td>Wattage rating</td>
+ <td>1000W</td>
+ </tr>
+ <tr>
+ <td>Home address</td>
+ <td>12h 28m 24.97s, +31° 28′ 37.7″</td>
+ </tr>
+ <tr>
+ <td>Most played game (Steam)</td>
+ <td>Space Engineers (734 hours)</td>
+ </tr>
+ <tr>
+ <td>Most played game (in general)</td>
+ <td>Minecraft (Hours unknown but definitely high)</td>
+ </tr>
+ <tr>
+ <td>Best Hand</td>
+ <td>756,276,480</td>
+ </tr>
+ <tr>
+ <td title="Since this bit was added, anyway">Page views</td>
+ <td>
+ <?php
+ $num = (int) filter_var(file_get_contents("views.txt"), FILTER_SANITIZE_NUMBER_INT);
+ $num++;
+ file_put_contents("views.txt", $num);
+ echo $num;
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <?php
+ $booger = array(
+ "arch",
+ "bogos",
+ "Hotel",
+ "blood"
+ );
+ $aids = array(
+ "btw",
+ "binted",
+ "Trivago",
+ "inside (we think)"
+ );
+ $poopaids_copy = array_rand($booger);
+ $boogeraids = $booger[$poopaids_copy];
+ $aidsbooger = $aids[$poopaids_copy];
+ echo "<td>$boogeraids</td><td>$aidsbooger</td>";
+ ?>
+ </tr>
+ <tr>
+ <td>Number I'm thinking of</td>
+ <td><?php echo rand(0, 69421); ?></td>
+ </tr>
+ <tr>
+ <td>Personality</td>
+ <td><?php
+ $ei = array(
+ "E",
+ "I"
+ );
+ echo $ei[array_rand($ei)];
+ $sn = array(
+ "S",
+ "N"
+ );
+ echo $sn[array_rand($sn)];
+ $tf = array(
+ "T",
+ "F"
+ );
+ echo $tf[array_rand($tf)];
+ $jp = array(
+ "J",
+ "P"
+ );
+ echo $jp[array_rand($jp)];
+ ?></td>
+ </tr>
+ </tbody></table>
+ </body>
+</html>
diff --git a/stuff/EnchantedToolsPack_v1.zip b/stuff/EnchantedToolsPack_v1.zip
new file mode 100644
index 0000000..cc83984
--- /dev/null
+++ b/stuff/EnchantedToolsPack_v1.zip
Binary files differ
diff --git a/stuff/beat/digital.css b/stuff/beat/digital.css
new file mode 100644
index 0000000..553d078
--- /dev/null
+++ b/stuff/beat/digital.css
@@ -0,0 +1,10 @@
+@font-face {
+ font-family: beat;
+ src: url("../fonts/DS-DIGI.ttf");
+}
+body {
+ font-family: beat, monospace;
+ color: lime;
+ text-shadow: 0 0 3px #5ff508;
+ background: black;
+} \ No newline at end of file
diff --git a/stuff/beat/frame.php b/stuff/beat/frame.php
new file mode 100644
index 0000000..5143943
--- /dev/null
+++ b/stuff/beat/frame.php
@@ -0,0 +1,41 @@
+<?php
+ function beat() {
+ return '@'.date("B");
+ }
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <title><?php echo beat(); ?></title>
+ <?php
+ $theme = $_GET['theme'];
+ echo "<link href='$theme.css' rel='stylesheet' type='text/css' media='all'>";
+ ?>
+ <style>
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ }
+ body {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 25px;
+ }
+ a {
+ text-decoration: inherit;
+ color: inherit;
+ }
+ </style>
+</head>
+
+<body>
+ <main>
+ <a target="_blank" href="/stuff/beat/"><?php echo beat(); ?></a>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/stuff/beat/index.php b/stuff/beat/index.php
new file mode 100644
index 0000000..16b7054
--- /dev/null
+++ b/stuff/beat/index.php
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title><?php echo '@'.date("B"); ?></title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ <style>
+ .beatframe {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ margin: .5rem 0;
+ }
+ </style>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); ?>
+ <h1 style="background-image: unset;">.beat</h1>
+ <h2 id="caption"><?php echo '@'.date("B"); ?></h2>
+ <nav>
+ <a href="https://en.wikipedia.org/wiki/Swatch_Internet_Time">Swatch Internet Time (Wikipedia)</a>
+ </nav>
+ <h2>88x31 Embeds</h2>
+ <div class="beatframe">
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=digital" style="width: 84px; height: 27px;"></iframe>
+ </div>
+ <pre><code>&lt;iframe src="https://isopod.cool/stuff/beat/frame.php?theme=digital" style="width: 84px; height: 27px;"&gt;&lt;/iframe&gt;</code></pre>
+ <div class="beatframe">
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=pixel" style="width: 84px; height: 27px;"></iframe>
+ </div>
+ <pre><code>&lt;iframe src="https://isopod.cool/stuff/beat/frame.php?theme=pixel" style="width: 84px; height: 27px;"&gt;&lt;/iframe&gt;</code></pre>
+ <div class="beatframe">
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=sketch" style="width: 84px; height: 27px;"></iframe>
+ </div>
+ <pre><code>&lt;iframe src="https://isopod.cool/stuff/beat/frame.php?theme=sketch" style="width: 84px; height: 27px;"&gt;&lt;/iframe&gt;</code></pre>
+ </body>
+</html>
diff --git a/stuff/beat/pixel.css b/stuff/beat/pixel.css
new file mode 100644
index 0000000..20f3f37
--- /dev/null
+++ b/stuff/beat/pixel.css
@@ -0,0 +1,10 @@
+@font-face {
+ font-family: beat;
+ src: url("../fonts/slkscr.ttf");
+}
+body {
+ font-family: beat, monospace;
+ color: gainsboro;
+ background: rgb(255,0,178);
+ background: linear-gradient(27deg, rgba(255,0,178,1) 0%, rgba(53,0,182,1) 81%);
+} \ No newline at end of file
diff --git a/stuff/beat/sketch.css b/stuff/beat/sketch.css
new file mode 100644
index 0000000..34b7b87
--- /dev/null
+++ b/stuff/beat/sketch.css
@@ -0,0 +1,13 @@
+@font-face {
+ font-family: beat;
+ src: url("../fonts/firsttimewriting.ttf");
+}
+body {
+ font-family: beat, sans-serif;
+ font-weight: bold;
+ color: black;
+ background-image: repeating-linear-gradient(0deg, #a2ddee, #a2ddee 1px, transparent 1px, transparent);
+ background-size: 23px 23px;
+ background-color: #f7f7f7;
+ background-position: 5px 5px;
+} \ No newline at end of file
diff --git a/stuff/beat/time.php b/stuff/beat/time.php
new file mode 100644
index 0000000..e3e9596
--- /dev/null
+++ b/stuff/beat/time.php
@@ -0,0 +1,4 @@
+<?php
+header('Content-Type:text/plain');
+echo '@'.date("B");
+?> \ No newline at end of file
diff --git a/stuff/bg.jpg b/stuff/bg.jpg
new file mode 100644
index 0000000..cac00e8
--- /dev/null
+++ b/stuff/bg.jpg
Binary files differ
diff --git a/stuff/bg.jxl b/stuff/bg.jxl
new file mode 100644
index 0000000..2377a2b
--- /dev/null
+++ b/stuff/bg.jxl
Binary files differ
diff --git a/stuff/dirtomp3.sh b/stuff/dirtomp3.sh
new file mode 100644
index 0000000..ac75c20
--- /dev/null
+++ b/stuff/dirtomp3.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# This is a simple script I wrote to convert my entire music library to mp3s for putting on my phone.
+# You need to have ffmpeg installed with support for all relevant formats for this to work.
+
+# HOW TO USE:
+# Place this script in the directory that your library's root directory is in, i.e. if your music
+# library is in ~/Music/Library, this script should be located at ~/Music/dirtomp3.sh
+# Set the variable "root" to the name of your library's root directory
+# Set "newroot" to the desired root directory of the output. This will be created if it doesn't exist.
+# The script should take care of the rest.
+
+root="Library"
+newroot="Library_mp3"
+mvcount=0
+tdcount=$(($(find "$root" -type f -not -path '*/.*' | wc -l)))
+
+printf "\x1b[s"
+echo ".00% done ($mvcount/$tdcount files processed)"
+
+recurse() {
+ path="$1"
+ for f in "$path/"*; do
+ nf=$(echo "$f" | sed "s/^$root/$newroot/;s/\.flac\|\.wav\|\.ogg$/.mp3/")
+ if [[ "$f" != $root* ]]; then
+ echo "Script attempted to access item $f outside designated operating area, aborting"
+ exit
+ fi
+ if [[ "$nf" != $newroot* ]]; then
+ echo "Script attempted to access item $nf outside designated operating area, aborting"
+ exit
+ fi
+ if [[ -d "$f" ]]; then
+ mkdir -p "$nf"
+ recurse "$f"
+ elif [[ -f $f ]]; then
+ printf "\x1b[2K%s" "$(echo "$f" | head -c $(tput cols))"
+ if [[ "$f" == *.flac ]] || [[ "$f" == *.wav ]] || [[ "$f" == *.ogg ]]; then
+ if [[ ! -f $nf ]] || [[ $f -nt $nf ]]; then
+ ffmpeg -i "$f" "$nf" -loglevel 0
+ if [[ $? -gt 0 ]]; then
+ exit
+ fi
+ fi
+ elif [[ "$f" == *.mp3 ]]; then
+ cp -u "$f" "$nf"
+ elif [[ "$f" == *.png ]] || [[ "$f" == *.jpg ]] || [[ "$f" == *.jxl ]] || [[ "$f" == *.gif ]]; then
+ cp -u "$f" "$nf"
+ fi
+ mvcount=$((mvcount+1))
+ printf "\x1b[u%s%% done (%d/%g files processed)\n" "$(echo "scale=2; $(echo "$mvcount/$tdcount*100" | bc -l)/1" | bc)" "$mvcount" "$tdcount"
+ fi
+ done
+}
+
+mkdir -p $newroot
+recurse "$root"
+printf "\x1b[2K"
diff --git a/stuff/firefoxrss/feed.php b/stuff/firefoxrss/feed.php
new file mode 100644
index 0000000..0f7cb17
--- /dev/null
+++ b/stuff/firefoxrss/feed.php
@@ -0,0 +1,62 @@
+<?php
+// This is a simple RSS bridge type script intended to generate a basic RSS feed for Firefox releases by scraping https://mozilla.org/firefox/notes/
+// TODO: Add the contents of the page to the RSS entry
+
+if($_GET['downloadsource'] == 'yes') { // just serve the source code as plain text and exit
+ header('Content-Type: text/plain');
+ echo file_get_contents('feed.php');
+ die();
+}
+
+// In order to reduce the load this puts on both Mozilla's servers and mine, I cache the output of this script for 1 hour. (3600 seconds)
+// I could cache it for longer, say a day, but that would significantly increase my chances of updating my browser before
+// the release notes appear in my RSS reader, which is simply unacceptable.
+$fname = "feed_cached.xml";
+$cacheperiod = 3600;
+$cache_too_old = (time() - filemtime($fname) > $cacheperiod);
+
+if($cache_too_old) {
+ $url = "https://mozilla.org/firefox/notes/";
+ if(function_exists('curl_init')) {
+ $ch = curl_init($url);
+
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+
+ $str = curl_exec($ch);
+ if(curl_error($ch)) {
+ echo curl_error($ch);
+ die();
+ }
+ curl_close($ch);
+ } else { // If the cURL library isn't installed, just use file_get_contents()
+ $str = file_get_contents($url);
+ }
+
+ preg_match('/(<div class="c-release-version">([0-9]|\.)+<\/div>)/', $str, $rcs); // extract the element containing the version number
+ preg_match('/([0-9]|\.)+/', $rcs[0], $rs); // extract the version number from that
+ $rel = $rs[0];
+
+ $link = "https://www.mozilla.org/en-US/firefox/".$rel."/releasenotes"; // construct a permalink to the patch notes for the current latest release in particular
+
+ preg_match('/(<p class="c-release-date">.+<\/p>)/', $str, $odcs); // extract the element containing the release date
+ $origdate = str_replace('</p>', "", str_replace('<p class="c-release-date">', "", $odcs[0])); // extract the date string
+ $udate = strtotime($origdate) + 43200; // convert said date string to the unix timestamp for noon GMT on that date
+ $rssdate = "D, d M Y H:i:s";
+ $date = date($rssdate, $udate); // convert unix timestamp to the date format RSS uses
+
+ $updatetime = date($rssdate, filemtime($fname)); // generating some data to fill out optional elements of the RSS feed.
+ $ttl = $cacheperiod / 60; // This is the sole reason why a few variables exist.
+
+ $output = "<rss version=\"2.0\"><channel><title>Firefox Release Notes</title><link>https://www.mozilla.org/firefox/releases/</link><description>Release notes for new versions of Firefox, updated every $ttl minutes</description><language>en-us</language><pubDate>$date</pubDate><lastBuildDate>$updatetime</lastBuildDate><docs>https://www.rssboard.org/rss-specification</docs><generator>niceopod's Firefox release notes RSS feed bridge</generator><ttl>$ttl</ttl><image><url>https://upload.wikimedia.org/wikipedia/commons/8/84/Mozilla_Firefox_3.5_logo.png</url><title>Firefox Release Notes</title><link>https://www.mozilla.org/firefox/releases/</link></image><item><title>Firefox $rel</title><pubDate>$date</pubDate><description>Release $rel of Firefox, from $origdate</description><link>$link</link><guid>$link</guid></item></channel></rss>";
+ // Outputs an RSS feed with one entry. I wanted to do the latest ten, but the releases weren't in
+ // chronological order on the release list page and I couldn't be bothered trying to reorder them,
+ // plus I would have had to scrape all those pages for the release date too and fuck that lol
+ file_put_contents($fname, $output);
+} else {
+ $output = file_get_contents($fname);
+}
+
+header('Content-Type: text/xml'); // Not sure if this is necessary but it feels like good practice and it gets Chromium to display it all pretty
+echo $output; \ No newline at end of file
diff --git a/stuff/index.php b/stuff/index.php
new file mode 100644
index 0000000..89acd3b
--- /dev/null
+++ b/stuff/index.php
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Items</title>
+ <link href="../style.css" rel="stylesheet" type="text/css" media="all">
+ <style>
+ details[open] > summary {
+ margin-bottom: .5rem;
+ }
+ details ul {
+ margin: 0;
+ padding-left: 1.5rem;
+ }
+ </style>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true, -15, "Pictured: The level of code quality you can expect if you use this stuff") ?>
+ <h1>stuff</h1>
+ <h2 id="caption">things too!</h2>
+ <h2>Utilities</h2>
+ <table>
+ <tr>
+ <td><a href="rssfilter.php">rssfilter.php</a></td>
+ <td>Basic RSS and Atom feed filtering utility. Accepts regex.</td>
+ </tr>
+ <tr>
+ <td><a href="firefoxrss/feed.php">firefoxrss</a></td>
+ <td>RSS bridge for Firefox release notes.</td>
+ </tr>
+ </table>
+ <h2>Downloads</h2>
+ <table>
+ <tr>
+ <td nowrap><a href="EnchantedToolsPack_v1.zip">EnchantedToolsPack_v1.zip</a></td>
+ <td>Custom resourcepack for Minecraft that uses functionality from <a href="https://optifine.net/home">Optifine</a> to add custom textures for enchanted tools and weapons. Confirmed working with 1.19.</td>
+ </tr>
+ </table>
+ <h2>Scripts</h2>
+ <table>
+ <tr>
+ <td>webpkiller/</td>
+ <td><details><summary>Automatic .webp converters</summary>Various scripts intended for use as the default program for opening .webp files. They automatically replace the .webp image with a .png one and open that instead. Incompatible with animated .webp images.</details></td>
+ </tr>
+ <tr class="indent-1">
+ <td><a href="webpkiller/webpkiller.sh">webpkiller.sh</a></td>
+ <td>
+ <details>
+ <summary>Bash script for Linux.</summary>
+ <ul>
+ <li>Only works on .webp files.</li>
+ <li>Requires <a href="https://imagemagick.org/">ImageMagick</a> to be installed.</li>
+ </ul>
+ </details>
+ </td>
+ </tr>
+ <tr class="indent-1">
+ <td><a href="webpkiller/webpkiller.cmd">webpkiller.cmd</a></td>
+ <td>
+ <details>
+ <summary>Batch script for Windows.</summary>
+ <ul>
+ <li>Only works on .webp files.</li>
+ <li>Requires <a href="https://imagemagick.org/">ImageMagick</a>.</li>
+ <li>Replaces <i>every</i> instance of ".webp" in the filepath because Windows batch language is hard.</li>
+ </ul>
+ </details>
+ </td>
+ </tr>
+ <tr class="indent-1">
+ <td><a href="webpkiller/webpkiller.py">webpkiller.py</a></td>
+ <td>
+ <details>
+ <summary>Platform-agnostic Python script.</summary>
+ <ul>
+ <li>Works on anything supported by pillow.</li>
+ <li>Requires <a href="https://www.python.org/">Python 3</a> and the <a href="https://python-pillow.org/">pillow</a> library.</li>
+ </ul>
+ </details>
+ </td>
+ </tr>
+ <tr class="indent-1">
+ <td><a href="webpkiller/webpkiller_win.zip">webpkiller_win.zip</a></td>
+ <td><details><summary>Windows webpkiller.py build.</summary>webpkiller.py, but compiled for Windows with <a href="https://pypi.org/project/pyinstaller/">pyinstaller</a>.</td>
+ </tr>
+ <tr>
+ <td><a href="dirtomp3.sh">dirtomp3.sh</a></td>
+ <td>Bash script that uses ffmpeg to convert a music library to mp3s.</td>
+ </tr>
+ </table>
+ <h2>Other</h2>
+ <table>
+ <tr>
+ <td><a href="neon_boost_times.html">neon_boost_times.html</a></td>
+ <td>A table of my level times in Neon Boost.</td>
+ </tr>
+ <tr>
+ <td><a href="https://userstyles.world/style/5238/status-cafe-latte">userstyles.world/style/5238<br/>/status-cafe-latte</a></td>
+ <td>Stylus theme I made for <a href="https://status.cafe/">status.cafe</a> and the attached forum.</td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/stuff/neon_boost_times.html b/stuff/neon_boost_times.html
new file mode 100644
index 0000000..e00af8c
--- /dev/null
+++ b/stuff/neon_boost_times.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>My level times in Neon Boost</title>
+ <style type="text/css">
+ html, body {
+ height: 100%;
+ overflow-y: hidden;
+ }
+ body {
+ font-family: 'Orbitron', sans-serif;
+ font-size: 1.2em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-image: linear-gradient(#5d0081 2px, transparent 2px), linear-gradient(to right, #5d0081 2px, transparent 2px);
+ background-size: 150px 150px;
+ background-color: #000000;
+ background-repeat: repeat;
+ animation-name: bganim;
+ animation-duration: 6s;
+ animation-iteration-count: infinite;
+ animation-timing-function: linear;
+ margin: 0;
+ }
+ @keyframes bganim {
+ 0% { background-position: 0px 0px; }
+ 100% { background-position: 150px 150px; }
+ }
+ div#main {
+ border: 5px solid #f82a6a;
+ padding: 35px;
+ color: #0dff00;
+ background-image: repeating-linear-gradient(0deg, #041c07, #041c07 3px, transparent 3px, transparent);
+ background-size: 6px 6px;
+ background-color: #041807;
+ box-shadow: 0 0 30px #c21a4fdc inset, 0 0 100px 100px black inset, 0 0 30px #c21a4fee;
+ max-width: 95%;
+ box-sizing: border-box;
+ }
+ div#tablediv {
+ width: 100%;
+ overflow-x: scroll;
+ }
+ table {
+ width: 100%;
+ overflow-x: scroll;
+ }
+ td {
+ padding: 5px;
+ }
+ .highlighted {
+ background-color: #eeffee0c;
+ }
+ p {
+ margin-bottom: 0;
+ font-size: 0.8em;
+ }
+ a {
+ color: #f82a6a;
+ text-decoration: none;
+ }
+ .c0 {
+ color: gold;
+ }
+ </style>
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap" rel="stylesheet">
+ </head>
+ <body>
+ <div id="main">
+ <div id="tablediv">
+ <table>
+ <tr>
+ <td>Level</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td>
+ </tr>
+ <tr class="highlighted">
+ <td>Laser City</td><td class="c0">4.219</td><td class="c0">3.939</td><td>3.899</td><td>6.359</td><td class="c0">3.959</td><td class="c0">3.259</td><td>6.139</td><td>7.159</td><td>2.419</td><td>8.32</td><td class="c0">5.419</td><td class="c0">17</td>
+ </tr>
+ <tr>
+ <td>Laser City<br/>(Lights Off)</td><td class="c0">4.439</td><td class="c0">4.119</td><td>4.179</td><td>7.079</td><td class="c0">5.799</td><td class="c0">3.419</td><td>5.859</td><td>7.299</td><td>2.519</td><td>8.46</td><td class="c0">5.859</td><td>20.02</td>
+ </tr>
+ <tr class="highlighted">
+ <td>Tesla Factory</td><td>3.999</td><td>5.219</td><td>6.359</td><td>3.359</td><td>5.959</td><td>4.719</td><td>6.839</td><td>1.999</td><td>6.259</td><td>4.779</td><td class="c0">7.219</td><td class="c0">16.44</td>
+ </tr>
+ <tr>
+ <td>Tesla Factory<br/>(Lights Off)</td><td>4.159</td><td>5.679</td><td>6.519</td><td>3.619</td><td>5.719</td><td>5.639</td><td>6.799</td><td>2.039</td><td>6.319</td><td>5.519</td><td class="c0">7.019</td><td class="c0">16.92</td>
+ </tr>
+ <tr class="highlighted">
+ <td>Cosmic Highway</td><td>9.14</td><td>6.279</td><td>6.979</td><td>11.02</td><td>5.439</td><td>9.58</td><td>7.199</td><td>11.24</td><td>17.8</td><td>4.679</td><td>25.06</td><td>40.78</td>
+ </tr>
+ <tr>
+ <td nowrap>Cosmic Highway<br/>(Lights Off)</td><td>10.46</td><td>6.699</td><td>6.859</td><td>12.8</td><td>5.779</td><td>10.32</td><td>7.839</td><td>13.28</td><td>19.02</td><td>4.779</td><td>29.36</td><td>42.56</td>
+ </tr>
+ </table>
+ </div>
+ <p>Times are in seconds, truncated to the millisecond because the in-game timer is rife with rounding errors.<br/>Times in <span class="c0">yellow</span> are from levels I can effectively "skip", or beat without triggering the timer to start.<br/>Read the blog post I made this for <a href="https://isopod.cool/old/2/?page=blog#Second">here</a>. Get Neon Boost <a href="https://store.steampowered.com/app/1057850/Neon_Boost/">here</a>.</p>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/stuff/rssfilter.php b/stuff/rssfilter.php
new file mode 100644
index 0000000..ea749cd
--- /dev/null
+++ b/stuff/rssfilter.php
@@ -0,0 +1,288 @@
+<?php
+
+// Here's my embarrassing ass source code. It is public domain, do with it what you will
+
+/*ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);*/
+
+if($_GET['downloadsource'] == 'yes') { // just serve the source code as plain text and exit
+ header('Content-Type: text/plain');
+ echo file_get_contents('rssfilter.php');
+ die();
+}
+
+$feed = $_GET['feed'];
+$filter = $_GET['filter'];
+$filtertype = $_GET['type'];
+$useregex = false;
+if($_GET['regex'] == 'yes' or $_GET['regex'] == 'y') {
+ $useregex = true;
+}
+
+function rss_testforfilter($item) { // I wrote two different functions for filtering RSS and Atom feeds under the assumption that they would be radically different
+ // in some way. The only real difference ended up being how the categories are stored within the category tags. I could probably
+ // consolidate them into one function, but these boolean expressions are big and complicated and I'm too scared to touch it now.
+
+ global $useregex; // PHP is silly and makes you re-declare global variables if you want to use them inside functions.
+ global $filter;
+ foreach($item->category as $category) { // loops through all the <category> tags and returns true if any of them contain the filter string
+ if(
+ (!$useregex and strpos($category, $filter) !== false) or // Don't use regex and filter string is found
+ ($useregex and preg_match($filter, $category)) // DO use regex and filter expression is found
+ ) {
+ return true;
+ }
+ }
+ if(
+ (!$useregex and (strpos($item->description, $filter) !== false or strpos($item->title, $filter) !== false)) or // Don't use regex and filter string is found
+ ($useregex and (preg_match($filter, $item->description) or preg_match($filter, $item->title))) // DO use regex and filter expression is found
+ ) {
+ return true;
+ }
+ return false;
+}
+
+function atom_testforfilter($entry) {
+ global $useregex;
+ global $filter;
+ foreach($entry->category as $category) { // loops through all the <category> tags and returns true if any of them contain the filter string
+ if(
+ (!$useregex and strpos($category['term'], $filter) !== false) or // Don't use regex and filter string is found
+ ($useregex and preg_match($filter, $category['term'])) // DO use regex and filter expression is found
+ ) {
+ return true;
+ }
+ }
+ if(
+ (!$useregex and (strpos($entry->description, $filter) !== false or strpos($entry->title, $filter) !== false)) or // Don't use regex and filter string is found
+ ($useregex and (preg_match($filter, $entry->description) or preg_match($filter, $entry->title))) // DO use regex and filter expression is found
+ ) {
+ return true;
+ }
+ return false;
+}
+
+if($feed // A basic check to make sure the URL is formed properly. It doesn't actually check for a valid URL or valid regex.
+ and $filter // If this check fails, the HTML document below this gets served.
+ and ($filtertype === "white" or $filtertype === "black")
+){
+ header('Content-Type: text/xml'); // Not sure if I actually need to do this, but it seems like good practice and it makes Chromium display the XML tree all nice.
+
+ $content = simplexml_load_string(file_get_contents($feed)); // I've encountered a problem where something between the server this command pulls from and this script seems to
+ // be caching the result. I'm guessing it's some kind of Nginx configuration error, but I'm not sure. Maybe I
+ // should be using a different function to do this? rss-bridge uses the cURL library, which I know because I had
+ // to install it myself.
+
+ if($content->getName() == 'rss') { // Here I just assume everything not explicitly an RSS feed is an Atom feed. I am 100% certain there is an edge case I'm missing here.
+
+ echo '<rss version="2.0"><channel>'; // This is the most embarrassing part of this code by far. I wanted to do this by looping over all the entries
+ echo $content->channel->title->asXML(); // in the XML object and specifically removing the ones that didn't pass the filter *from* the object, but
+ echo $content->channel->link->asXML(); // I couldn't for the life of me get that to work, so I settled for the next best thing: just echoing all the
+ echo $content->channel->description->asXML(); // fields that are part of the spec out to a brand new XML document and then adding all the entries that did
+ echo $content->channel->language->asXML(); // pass. I mean, if it works it works, but sorry to anyone that was using some nonstandard feature here.
+ echo $content->channel->pubDate->asXML();
+ echo $content->channel->lastBuildDate->asXML();
+ echo $content->channel->docs->asXML();
+ echo "<generator>will's RSS filter script</generator>";
+ echo $content->channel->managingEditor->asXML();
+ echo $content->channel->webMaster->asXML();
+
+ foreach($content->channel->item as $item) {
+
+ $found = rss_testforfilter($item, $filter);
+
+ if(($found and $filtertype == 'white') or (!$found and $filtertype == 'black')) {
+ echo $item->asXML();
+ }
+
+ }
+
+ echo '</channel></rss>';
+
+ die();
+ } else {
+
+ echo '<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom">';
+ echo $content->title->asXML();
+ echo $content->link->asXML();
+ echo $content->updated->asXML();
+ echo $content->author->asXML();
+ echo $content->id->asXML();
+ foreach($content->category as $category) {
+ echo $category->asXML();
+ }
+ foreach($content->contributor as $contributor) {
+ echo $contributor->asXML();
+ }
+ echo "<generator>will's Atom filter script</generator>";
+ echo $content->icon->asXML();
+ echo $content->logo->asXML();
+ echo $content->rights->asXML();
+ echo $content->subtitle->asXML();
+
+ foreach($content->entry as $entry) {
+
+ $found = atom_testforfilter($entry, $filter);
+
+ if(($found and $filtertype == 'white') or (!$found and $filtertype == 'black')) {
+ echo $entry->asXML();
+ }
+
+ }
+
+ echo '</feed>';
+
+ die();
+ }
+}
+
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>RSS Filter</title>
+ <style type="text/css">
+ html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ }
+ body {
+ margin: auto;
+ width: fit-content;
+ max-width: 32rem;
+ background-color: #222222;
+ font-family: monospace;
+ color: white;
+ display: flex;
+ align-items: center;
+ font-size: 1rem;
+ flex-direction: column;
+ justify-content: center;
+ text-shadow: 1px 1px 3px black;
+ }
+ td:first-child {
+ padding-right: 1em;
+ font-weight: bold;
+ }
+ input[type="text"] {
+ width: 100%;
+ }
+ code {
+ font-size: initial;
+ background-color: #101010;
+ padding: 1em;
+ border-radius: 1em;
+ display: block;
+ text-align: center;
+ margin: auto;
+ box-shadow: 2px 2px 4px black;
+ }
+ code span {
+ color: #ccc;
+ }
+ table {
+ font-size: 0.9rem;
+ }
+ a {
+ color: #df1955;
+ }
+ a:hover {
+ color: #00ffd5;
+ }
+ @media only screen and (orientation: portrait) {
+ td {
+ display: block;
+ padding-top: 0.5rem;
+ }
+ body {
+ max-width: 20rem;
+ }
+ }
+ </style>
+ </head>
+ <body>
+ <h1 style="margin: 0;">RSS Filter</h1>
+ <hr style="width: 30%; margin: 1.25rem;">
+ <table>
+ <noscript>
+ <tr>
+ <td colspan="2">You need to have Javascript enabled for this generator to work, sorry.</td>
+ </tr>
+ </noscript>
+ <tr>
+ <td>Feed URL</td>
+ <td><input type="text" placeholder="https://example.com/rss" id="feed" value=""></input></td>
+ </tr>
+ <tr>
+ <td>Filter String</td>
+ <td><input type="text" placeholder="foobar" id="filter" value=""></input></td>
+ </tr>
+ <tr>
+ <td>Filter Type</td>
+ <td>
+ <input type="radio" id="whitelist" name="filtertype" value="white" checked>
+ <label for="whitelist">Whitelist</label>
+ <input type="radio" id="blacklist" name="filtertype" value="black">
+ <label for="blacklist">Blacklist</label>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="regex">Use Regex</label></td>
+ <td><input type="checkbox" id="regex"></td>
+ </tr>
+ </table>
+ <p>
+ <code><a id="generatedlink" href=""></a></code>
+ </p>
+ <p style="position: absolute; bottom: 1em; margin: 0; text-align: center;">
+ Made by <a href="https://isopod.cool/">an isopod</a><br>
+ <a href="?downloadsource=yes">Download source code</a>
+ </p>
+ <script>
+
+ let feedURL = "https://example.com/rss";
+ let filter = "foobar";
+ let type = "white";
+ let regex = "";
+
+ function updateLink() {
+ let link = `${window.location.href}?feed=${feedURL}&filter=${filter}&type=${type}${regex}`;
+ document.getElementById('generatedlink').href = link;
+ document.getElementById('generatedlink').innerHTML = link.replace(/&/g, "&amp;");
+ }
+
+ updateLink();
+
+ document.getElementById('feed').addEventListener('input', function(evt) {
+ feedURL = encodeURI(this.value);
+ updateLink();
+ });
+ document.getElementById('filter').addEventListener('input', function(evt) {
+ filter = encodeURI(this.value);
+ updateLink();
+ });
+ document.getElementById('whitelist').addEventListener('input', function(evt) {
+ type = "white";
+ updateLink();
+ });
+ document.getElementById('blacklist').addEventListener('input', function(evt) {
+ type = "black";
+ updateLink();
+ });
+ document.getElementById('regex').addEventListener('change', function(evt) {
+ if(this.checked) {
+ regex = "&regex=yes";
+ document.getElementById('filter').placeholder = "/foobar/";
+ } else {
+ regex = "";
+ document.getElementById('filter').placeholder = "foobar";
+ }
+ updateLink();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/stuff/spotifycdnsilly/ip.php b/stuff/spotifycdnsilly/ip.php
new file mode 100644
index 0000000..e8332ff
--- /dev/null
+++ b/stuff/spotifycdnsilly/ip.php
@@ -0,0 +1,21 @@
+<?php
+
+$addr = $_SERVER['REMOTE_ADDR'];
+$url = "https://seed-mix-image.spotifycdn.com/v6/img/desc/$addr/sv/large";
+$img = "<img src='$url' alt='Spotify: $addr'>";
+
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title><?php echo($addr); ?></title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php echo("<meta property='og:image' content='$url'>"); ?>
+ </head>
+ <body style="display: flex; align-items: center; justify-content: center;">
+ <?php echo($img); ?>
+ </body>
+</html>
diff --git a/stuff/webgarden/image1.html b/stuff/webgarden/image1.html
new file mode 100644
index 0000000..4c1d559
--- /dev/null
+++ b/stuff/webgarden/image1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Image1</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ a {
+ color: white;
+ text-decoration: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="plant" style="background-image: url('images/image1.png');">
+ <a id="back" href="index.php" style="font-size: 2em; position: absolute; left: 4px; top: 218px;">&lt;</a>
+ <a id="forward" href="image2.html" style="font-size: 2em; position: absolute; left: 228px; top: 218px;">&gt;</a>
+ </div>
+ </body>
+</html>
diff --git a/stuff/webgarden/image2.html b/stuff/webgarden/image2.html
new file mode 100644
index 0000000..3ac0aa5
--- /dev/null
+++ b/stuff/webgarden/image2.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Image2</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ a {
+ color: white;
+ text-decoration: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="plant" style="background-image: url('images/image2.png');">
+ <a id="back" href="image1.html" style="font-size: 2em; position: absolute; left: 4px; top: 218px;">&lt;</a>
+ <a id="forward" href="image3.html" style="font-size: 2em; position: absolute; left: 228px; top: 218px;">&gt;</a>
+ </div>
+ </body>
+</html>
diff --git a/stuff/webgarden/image3.html b/stuff/webgarden/image3.html
new file mode 100644
index 0000000..00e8417
--- /dev/null
+++ b/stuff/webgarden/image3.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Image3</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ a {
+ color: white;
+ text-decoration: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="plant" style="background-image: url('images/image3.png');">
+ <a id="back" href="image2.html" style="font-size: 2em; position: absolute; left: 4px; top: 218px;">&lt;</a>
+ <a id="forward" href="image4.html" style="font-size: 2em; position: absolute; left: 228px; top: 218px;">&gt;</a>
+ </div>
+ </body>
+</html>
diff --git a/stuff/webgarden/image4.html b/stuff/webgarden/image4.html
new file mode 100644
index 0000000..f2e2a77
--- /dev/null
+++ b/stuff/webgarden/image4.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Image4</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ a {
+ color: white;
+ text-decoration: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="plant" style="background-image: url('images/image4.png');">
+ <a id="back" href="image3.html" style="font-size: 2em; position: absolute; left: 4px; top: 218px;">&lt;</a>
+ <a id="forward" href="index.php" style="font-size: 2em; position: absolute; left: 228px; top: 218px;">&gt;</a>
+ </div>
+ </body>
+</html>
diff --git a/stuff/webgarden/images/bubblecolumn1.gif b/stuff/webgarden/images/bubblecolumn1.gif
new file mode 100644
index 0000000..ad31eb1
--- /dev/null
+++ b/stuff/webgarden/images/bubblecolumn1.gif
Binary files differ
diff --git a/stuff/webgarden/images/image1.png b/stuff/webgarden/images/image1.png
new file mode 100644
index 0000000..825d878
--- /dev/null
+++ b/stuff/webgarden/images/image1.png
Binary files differ
diff --git a/stuff/webgarden/images/image2.png b/stuff/webgarden/images/image2.png
new file mode 100644
index 0000000..cd9e273
--- /dev/null
+++ b/stuff/webgarden/images/image2.png
Binary files differ
diff --git a/stuff/webgarden/images/image3.png b/stuff/webgarden/images/image3.png
new file mode 100644
index 0000000..9de4975
--- /dev/null
+++ b/stuff/webgarden/images/image3.png
Binary files differ
diff --git a/stuff/webgarden/images/image4.png b/stuff/webgarden/images/image4.png
new file mode 100644
index 0000000..3562e48
--- /dev/null
+++ b/stuff/webgarden/images/image4.png
Binary files differ
diff --git a/stuff/webgarden/images/isopod_with_aviators_small.png b/stuff/webgarden/images/isopod_with_aviators_small.png
new file mode 100644
index 0000000..27ae5b7
--- /dev/null
+++ b/stuff/webgarden/images/isopod_with_aviators_small.png
Binary files differ
diff --git a/stuff/webgarden/images/webgarden-bg.png b/stuff/webgarden/images/webgarden-bg.png
new file mode 100644
index 0000000..f6052e8
--- /dev/null
+++ b/stuff/webgarden/images/webgarden-bg.png
Binary files differ
diff --git a/stuff/webgarden/index.php b/stuff/webgarden/index.php
new file mode 100644
index 0000000..af88805
--- /dev/null
+++ b/stuff/webgarden/index.php
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang="en">
+ <?php
+ $captions = array(
+ 'bruh moment',
+ 'Try reloading!',
+ 'Supports VPNs',
+ 'I use arch btw',
+ 'MySite.html',
+ 'Over Construction',
+ 'Real isopod hours',
+ '[object Object]',
+ '* You found the [Moss]!',
+ 'Minceraft',
+ 'Isopod gaming',
+ 'Website of some girl',
+ 'your mom',
+ 'Badly programmed',
+ 'Oh, you know ;)',
+ 'assholes DNI',
+ 'swag',
+ '\'\'',
+ '<span class="minecraftsplash">Kind of dragon free!</span>',
+ 'your gay',
+ 'the fuck is a gender',
+ 'The Only Website',
+ '𝓘𝓷𝓪𝓬𝓬𝓮𝓼𝓼𝓲𝓫𝓵𝓮!',
+ 'Follow me on Google+!',
+ '404: caption not found',
+ 'Web π compliant!',
+ 'cringe',
+ 'real life isopod',
+ 'holy fucking bingle',
+ 'crubge',
+ 'Tested in prod!',
+ 'pwetty epic B)',
+ 'Semi-modular!',
+ 'Did you know?',
+ 'shrimps is bugs',
+ 'Delicious!',
+ 'trnasgener',
+ 'Opinionated!',
+ 'Eurorack compatible!',
+ 'Hackable!',
+ 'HiDPI!',
+ '&amp;mdash; addict',
+ '3D printed!',
+ 'Federated!',
+ 'Chitinous!',
+ 'is this a bedbuge?',
+ 'Now in HD!',
+ 'Water me!'
+ );
+ $cap = $captions[array_rand($captions)];
+ ?>
+ <head>
+ <meta charset="utf-8">
+ <title>Pot</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ :root {
+ --top-header-gap: 90px;
+ --menuwidth: 140px;
+ }
+ html, body {
+ padding: 0;
+ margin: 0;
+ }
+ h1 {
+ width: 250px;
+ position: absolute;
+ top: var(--top-header-gap);
+ text-align: center;
+ }
+ h2 {
+ width: 238px;
+ position: absolute;
+ top: calc(34px + var(--top-header-gap));
+ text-align: right;
+ font-size: 1.1em;
+ }
+ #mainmenu {
+ background: #222222;
+ transition-duration: 0.6s;
+ height: 250px;
+ width: var(--menuwidth);
+ position: absolute;
+ top: 0;
+ left: 250px;
+ z-index: 2;
+ box-shadow: 0 0 0 black;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ }
+ body:hover #mainmenu {
+ left: calc(250px - var(--menuwidth));
+ box-shadow: 0 0 20px black;
+ }
+ a {
+ color: white;
+ }
+ #mainmenu a {
+ color: #df1955;
+ }
+ #mainmenu a:hover {
+ color: #00ffd5;
+ }
+
+ .flipped {
+ display: inline-block;
+ transform: rotate(180deg);
+ }
+ .rainbowtext {
+ animation-name: rainbow-text;
+ animation-duration: 20s;
+ animation-iteration-count: infinite;
+ }
+ .blinking {
+ animation-name: opacityblink;
+ animation-duration: 2s;
+ animation-iteration-count: infinite;
+ }
+ .minecraftsplash {
+ animation-name: growshrink;
+ animation-duration: 1.5s;
+ animation-iteration-count: infinite;
+ color: yellow;
+ display: inline-block;
+ }
+
+ @keyframes growshrink {
+ 0%, 100% { transform: scale(1) /*rotate(-10deg)*/; }
+ 50% { transform: scale(1.2) /*rotate(-10deg)*/; }
+ }
+ @keyframes opacityblink {
+ 0%, 50% {opacity: 0;}
+ 50.001%, 100% {opacity: 1;}
+ }
+ @keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+ }
+ @keyframes arrowwiggle {
+ 0%,90%,100% {left: 235px;}
+ 92% {left: 231px;}
+ }
+ audio {
+ display: none;
+ }
+ #mus:checked ~ audio {
+ display: initial;
+ }
+ </style>
+ </head>
+ <body>
+ <a target="_blank" href="../../">
+ <div id="plant" style="background: url('images/webgarden-bg.png');">
+ <h1>isopod.cool</h1>
+ <h2><?php echo $cap; ?></h2>
+ <img src="../../images/autoisopod_small.png" style="width: 70px; position: absolute; transform: scaleX(-1) rotate(-30deg); top: 188px; left: 170px;" />
+ <img src="images/bubblecolumn1.gif" style="height: 250px; position: absolute; left: 20px; top: 0;" />
+ <span id="hoverme">&lt;<span>
+ </div>
+ </a>
+ <input type="checkbox" id="mus" name="mus" style="display: none;"></input>
+ <div id="mainmenu">
+ <a target="_blank" href="../../">homepage</a>
+ <!--a target="_blank" href="../../desktop.html">$login<span class="blinking">_</span></a-->
+ <hr style="width: 30px;">
+ <a href="image1.html">images</a>
+ <a href="status.php">status</a>
+ <label for="mus"><a style="text-decoration: underline; cursor: pointer;">play music</a></label>
+ <hr style="width: 30px;">
+ <iframe src="https://isopod.cool/stuff/beat/frame.php?theme=pixel" style="width: 84px; height: 27px;"></iframe>
+ <img src="/etc/buttons/isopodhours.png" alt="isopod hours"/>
+ <img src="/etc/buttons/trans.png" alt="nonbinary"/>
+ </div>
+ <audio controls style="position: absolute; width: calc(100% - 0.4rem); top: 0.2rem; left: 0.2rem; z-index: 5;"><source src="music.mp3" type="audio/mp3"></audio>
+ </body>
+</html>
diff --git a/stuff/webgarden/music.mp3 b/stuff/webgarden/music.mp3
new file mode 100644
index 0000000..12f0400
--- /dev/null
+++ b/stuff/webgarden/music.mp3
Binary files differ
diff --git a/stuff/webgarden/status.php b/stuff/webgarden/status.php
new file mode 100644
index 0000000..4330d31
--- /dev/null
+++ b/stuff/webgarden/status.php
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Status</title>
+ <link href="style.css" rel="stylesheet" type="text/css" media="all">
+ <style type="text/css">
+ body {
+ background: #222222;
+ }
+ #statuscafe a {
+ color: #df1955;
+ }
+ #statuscafe a:hover {
+ color: #00ffd5;
+ }
+ #statuscafe {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ left: 10px;
+ top: 10px;
+ height: 230px;
+ width: 230px;
+ justify-content: center;
+ align-items: center;
+ }
+ #statuscafe-content {
+ margin-top: 10px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="plant">
+ <?php
+ $username = "niceopod"; // Your username here!
+ $status_data = json_decode(file_get_contents("https://status.cafe/users/$username/status.json"), true);
+ $content = $status_data["content"];
+ $face = $status_data["face"];
+ $timeago = str_replace(" ","&nbsp;",$status_data["timeAgo"]);
+ if(strlen($content) < 1) {
+ $content = "No status yet.";
+ }
+ echo "<div id='statuscafe'><div id='statuscafe-username'><a href='https://status.cafe/users/$username' target='_blank'>$username</a> $face $timeago</div><div id='statuscafe-content'>$content</div></div>";
+ ?>
+ <a id="back" href="index.php" style="font-size: 2em; position: absolute; left: 4px; top: 218px;">&lt;</a>
+ </div>
+ </body>
+</html>
diff --git a/stuff/webgarden/style.css b/stuff/webgarden/style.css
new file mode 100644
index 0000000..13c5320
--- /dev/null
+++ b/stuff/webgarden/style.css
@@ -0,0 +1,54 @@
+@font-face {
+ font-family: 'Silkscreen';
+ src: url('../fonts/slkscr.ttf');
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Regular.ttf);
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Bold.ttf);
+ font-weight: bold;
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Italic.ttf);
+ font-style: italic;
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf);
+ font-weight: bold;
+ font-style: italic;
+}
+html, body {
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+}
+body {
+ font-family: b612_mono, mono, monospace;
+ color: white;
+ background: #101010;
+ text-shadow: 1px 1px 4px black;
+}
+#plant {
+ height: 250px;
+ width: 250px;
+}
+a#forward, a#back, h1, h2, #hoverme {
+ font-family: 'Silkscreen';
+ color: white;
+ text-decoration: none;
+}
+#hoverme {
+ position: absolute;
+ top: 4px;
+ left: 235px;
+ animation-name: arrowwiggle;
+ animation-duration: 6s;
+ animation-iteration-count: infinite;
+ width: fit-content;
+ text-align: right;
+} \ No newline at end of file
diff --git a/stuff/webpkiller/webpkiller.cmd b/stuff/webpkiller/webpkiller.cmd
new file mode 100644
index 0000000..382e048
--- /dev/null
+++ b/stuff/webpkiller/webpkiller.cmd
@@ -0,0 +1,31 @@
+@echo off
+
+::Set variable filepath to the first argument
+SET filepath=%~f1
+
+::Abort if the given file doesn't exist
+IF NOT EXIST "%filepath%" (
+ ECHO %~n0: file not found - %filepath% >&2
+ EXIT /B 1
+)
+
+::Replace all instances of .webp with .png in the filename. kind of banking on the user not putting the extension anywhere else in the file or folder names for this to work properly...
+::I should be finding the last period in the filename and replacing everything AFTER it with the extension I want, but can't figure out how to do that because Windows batch is a nightmare language
+::You can replace this with "SET outfile=%filepath%.png" (no quotes) if that bothers you more than double file extensions
+::You can replace these two file extensions with any two image types you want to do this with
+SET outfile=%filepath:.webp=.png%
+
+::Abort if filename.png already exists
+IF EXIST "%outfile%" (
+ ECHO %~n0: %outfile% already exists. Aborting...
+ EXIT /B 2
+)
+
+::Use ImageMagick's command line tools to generate the converted file
+magick "%filepath%" "%outfile%"
+
+::Delete the original file (optional, this can be removed if for some reason you want to keep the shitty gross webp)
+del "%filepath%"
+
+::Open the new, fixed image like nothing ever happened
+%outfile%
diff --git a/stuff/webpkiller/webpkiller.py b/stuff/webpkiller/webpkiller.py
new file mode 100644
index 0000000..0153ff7
--- /dev/null
+++ b/stuff/webpkiller/webpkiller.py
@@ -0,0 +1,27 @@
+import PIL as pillow
+from PIL import Image
+import subprocess, os, platform, sys
+
+infile = sys.argv[len(sys.argv)-1]
+outfile = infile[:infile.rfind('.')] + ".png"
+
+if(os.path.exists(infile) == False):
+ print("File %s not found. Aborting..." %infile)
+ exit()
+
+if(os.path.exists(outfile)):
+ print("File %s already exists. Aborting..." %outfile)
+ exit()
+
+im = Image.open(infile)
+
+im.save(outfile)
+
+os.remove(infile)
+
+if(platform.system() == 'Darwin'): # macOS
+ subprocess.call(('open', outfile))
+elif(platform.system() == 'Windows'): # Windows
+ os.startfile(outfile)
+else: # linux variants
+ subprocess.call(('xdg-open', outfile)) \ No newline at end of file
diff --git a/stuff/webpkiller/webpkiller.sh b/stuff/webpkiller/webpkiller.sh
new file mode 100644
index 0000000..017fba0
--- /dev/null
+++ b/stuff/webpkiller/webpkiller.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+if [ ! -f "$1" ]; then
+ echo "File $1 does not exist. Aborting..."
+ exit
+fi
+
+suffix=".webp"
+filename=${1%"$suffix"}
+outfile="$filename.png"
+
+if [ -f "$outfile" ]; then
+ echo "File $outfile already exists. Aborting..."
+ notify-send --app-name=webpkiller "File $outfile already exists. Aborting..."
+ exit
+fi
+
+magick $1 $outfile
+rm -rf $1
+
+xdg-open $outfile
diff --git a/stuff/webpkiller/webpkiller_win.zip b/stuff/webpkiller/webpkiller_win.zip
new file mode 100644
index 0000000..5d54054
--- /dev/null
+++ b/stuff/webpkiller/webpkiller_win.zip
Binary files differ
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..4d36472
--- /dev/null
+++ b/style.css
@@ -0,0 +1,444 @@
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Regular.ttf);
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Bold.ttf);
+ font-weight: bold;
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-Italic.ttf);
+ font-style: italic;
+}
+@font-face {
+ font-family: b612_mono;
+ src: url(stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf);
+ font-weight: bold;
+ font-style: italic;
+}
+
+
+:root {
+ --stdfont: b612_mono, mono, monospace;
+ --bgcolor: #222222;
+ --fontcolor: #dcdcdc;
+ --linkcolor: #df1955;
+ --linkhover: #00ffd5;
+ --blockbg: #fff1;
+ --blockbghover: #fff2;
+ --stdshadow: #000;
+ /* ALL colors should be defined here.
+ If there's a color value somewhere else, move it here so it can be responsive */
+
+ --stdaccentborder: 3px solid var(--fontcolor);
+ --bodywidth: min(90vw, 80ch);
+ --stddropshadow: 4px 4px 8px black;
+ --stdpadding: 1rem;
+ --navbarheight: calc(var(--stdpadding) * 2.5);
+ --h1-image: url('images/isopod.php');
+ --shadowsize: 3rem;
+}
+html, body {
+ height: 100%;
+}
+
+body {
+ color: var(--fontcolor);
+ font-family: var(--stdfont);
+ text-shadow: 1px 1px 3px var(--stdshadow);
+
+ max-width: var(--bodywidth);
+ margin: auto;
+ background-color: var(--bgcolor);
+ box-sizing: border-box;
+}
+
+/* Headings */
+body > h1:first-of-type, body > main:first-of-type > div > h1:first-of-type {
+ margin-top: calc(var(--navbarheight) + var(--stdpadding));
+ font-size: 3em;
+ background-image: var(--h1-image);
+ background-size: contain;
+ background-position: right;
+ background-repeat: no-repeat;
+ padding-bottom: calc(var(--stdpadding) * 2);
+ margin-bottom: calc(var(--stdpadding) * -2);
+}
+h1 + h2#caption {
+ font-weight: normal;
+ padding-top: 0;
+ margin-top: -1.4em;
+}
+h1, h2, h3, h4, h5, h6 {
+ border-left: var(--stdaccentborder);
+ padding-left: var(--stdpadding);
+}
+
+/* Links */
+a {
+ color: var(--linkcolor);
+}
+a:hover {
+ color: var(--linkhover);
+}
+
+/* Nav */
+nav {
+ display: flex;
+ flex-wrap: wrap;
+ max-width: 100%;
+ align-items: center;
+ justify-content: center;
+}
+nav#main-nav {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: var(--navbarheight);
+}
+nav a, nav span, body > a{
+ padding: calc(var(--stdpadding) / 2) calc(var(--stdpadding) / 4 * 3);
+ margin: calc(var(--stdpadding) / 2) calc(var(--stdpadding) / 4);
+}
+nav a, body > a {
+ border-left: var(--stdaccentborder);
+ border-color: #0000;
+ background: linear-gradient(var(--blockbghover) 0 0) 0 / var(--bgpos, 0) no-repeat;
+ transition: background .3s, border .3s;
+}
+nav a:hover, body > a:hover {
+ --bgpos: 100%;
+ border-left: var(--stdaccentborder);
+}
+body > a {
+ display: block;
+ margin-left: 0;
+ padding-left: 1rem;
+ font-weight: bold;
+ font-size: 1.25em;
+ border-left: var(--stdaccentborder);
+}
+
+/* Background image type beat */
+#leftsidebg, #rightsidebg {
+ --bgimg: url(images/bg.jxl), url(images/bg.jpg);
+ background-image: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06)), var(--bgimg), url(images/bg.jxl), url(images/bg.jpg);
+ background-size: 100% 2px, 3px 100%, cover, cover, cover, cover;
+ background-repeat: repeat;
+ background-position: center;
+ position: fixed;
+ z-index: -10;
+ bottom: 0;
+ top: 0;
+ --distancefromcenter: calc((var(--bodywidth) / -2) - (var(--stdpadding) * 3));
+}
+#leftsidebg {
+ right: calc(50% - var(--distancefromcenter));
+ left: 0;
+ box-shadow: calc(0rem - var(--shadowsize)) 0 var(--shadowsize) calc(0rem - var(--shadowsize)) black inset;
+}
+#rightsidebg {
+ right: 0;
+ left: calc(50% - var(--distancefromcenter));
+ box-shadow: var(--shadowsize) 0 var(--shadowsize) calc(0rem - var(--shadowsize)) black inset;
+}
+
+/* 88x31 button container */
+.buttons {
+ text-align: center;
+ font-size: 0;
+}
+.buttons > * {
+ display: inline-block;
+ margin: 0.1rem;
+ font-size: 0;
+}
+.buttons > a > img {
+ transition-duration: .5s;
+ box-shadow: none;
+ display: inline-block;
+ transform: translate(0, 0);
+}
+.buttons > a > img:hover {
+ box-shadow: 2px 2px 4px black;
+ z-index: 5;
+ transform: translate(-2px, -2px);
+}
+
+/* Code snippets */
+code {
+ padding: 0.15rem;
+}
+pre > code {
+ display: block;
+ margin-bottom: 1rem;
+ overflow-x: auto;
+}
+code, .codetitle {
+ background-color: black;
+ font-size: .8rem;
+}
+pre > code, .codetitle {
+ width: 75%;
+ margin: auto;
+ border: 1px solid #00ffd5;
+ padding: 0.7rem;
+}
+.codetitle {
+ margin-bottom: 0;
+ border-bottom: none;
+ text-align: center;
+}
+.codetitle + pre {
+ margin-top: 0;
+}
+
+/* Tables */
+table {
+ border-collapse: collapse;
+}
+td {
+ padding: calc(var(--stdpadding) / 2);
+}
+tr > td:first-child {
+ padding-left: 0;
+}
+tr.indent-1 td {
+ padding-left: calc(var(--stdpadding));
+}
+tr.indent-1 td:first-child {
+ border-left: var(--stdaccentborder);
+}
+
+/* Quotations */
+figure.quote {
+ padding: calc(var(--stdpadding) * 1.5);
+ margin: 0;
+ margin-bottom: initial;
+ border-left: var(--stdaccentborder);
+ background-color: var(--blockbg);
+ margin-bottom: var(--stdpadding);
+}
+figure.quote blockquote {
+ margin: 0;
+}
+figure.quote figcaption {
+ margin-left: calc(var(--stdpadding) * 3);
+ margin-top: var(--stdpadding);
+}
+
+/* Media, plus captions thereof */
+img, picture, video {
+ max-width: 100%;
+ max-height: 50rem;
+ min-width: 0;
+}
+:is(body, p, picture) > img, picture, video, figure.media {
+ margin: auto;
+ display: block;
+}
+
+.gallery {
+ display: flex;
+ max-width: 100%;
+}
+figure.media {
+ width: fit-content;
+ max-width: 100%;
+}
+figure.media > div {
+ display: inline-block;
+}
+figure.media > div > figcaption {
+ width: min-content;
+ min-width: 100%;
+ font-size: 0.9em;
+ padding: calc(var(--stdpadding) * 0.9);
+ margin: 0;
+ margin-bottom: initial;
+ margin-top: -4px;
+ border-left: var(--stdaccentborder);
+ background-color: var(--blockbg);
+ box-sizing: border-box;
+}
+
+/* Misc */
+summary:hover {
+ cursor: pointer;
+}
+[title] {
+ text-decoration: underline;
+}
+[title]:hover {
+ cursor: help;
+}
+hr {
+ width: 30%;
+}
+
+/* Funsies */
+.serif {
+ font-family: serif;
+}
+.flipped {
+ display: inline-block;
+ transform: rotate(180deg);
+}
+.rainbowtext {
+ animation-name: rainbow-text;
+ animation-duration: 20s;
+ animation-iteration-count: infinite;
+}
+.blinking {
+ animation-name: opacityblink;
+ animation-duration: 2s;
+ animation-iteration-count: infinite;
+}
+.minecraftsplash {
+ animation-name: growshrink;
+ animation-duration: 1.5s;
+ animation-iteration-count: infinite;
+ color: yellow;
+ float: right;
+}
+.house {
+ color: cornflowerblue;
+}
+@keyframes growshrink {
+ 0%, 100% { transform: scale(0.9) rotate(-10deg); }
+ 50% { transform: scale(1.1) rotate(-10deg); }
+}
+@keyframes opacityblink {
+ 0%, 50% {opacity: 0;}
+ 50.001%, 100% {opacity: 1;}
+}
+@keyframes rainbow-text {
+ 100%,0%{color: rgb(255,0,0); text-shadow: 0 0 4px rgb(216, 1, 1);}
+ 8%{color: rgb(255,127,0); text-shadow: 0 0 4px rgb(211, 105, 0);}
+ 16%{color: rgb(255,255,0); text-shadow: 0 0 4px rgb(214, 214, 0);}
+ 25%{color: rgb(127,255,0); text-shadow: 0 0 4px rgb(105, 211, 0);}
+ 33%{color: rgb(0,255,0); text-shadow: 0 0 4px rgb(0, 204, 0);}
+ 41%{color: rgb(0,255,127); text-shadow: 0 0 4px rgb(0, 209, 105);}
+ 50%{color: rgb(0,255,255); text-shadow: 0 0 4px rgb(0, 202, 202);}
+ 58%{color: rgb(0,127,255); text-shadow: 0 0 4px rgb(0, 103, 206);}
+ 66%{color: rgb(0,0,255); text-shadow: 0 0 4px rgb(0, 0, 206);}
+ 75%{color: rgb(127,0,255); text-shadow: 0 0 4px rgb(103, 0, 206);}
+ 83%{color: rgb(255,0,255); text-shadow: 0 0 4px rgb(211, 0, 211);}
+ 91%{color: rgb(255,0,127); text-shadow: 0 0 4px rgb(211, 0, 105);}
+}
+
+/* If user is on mobile */
+@media only screen and (hover: none) {
+
+ nav#main-nav {
+ position: initial;
+ top: initial;
+ left: initial;
+ right: initial;
+ height: initial;
+ margin-top: calc(var(--stdpadding) / 2);
+ }
+ body > h1:first-of-type {
+ margin-top: var(--stdpadding);
+ }
+ nav a, nav span {
+ flex-grow: 1;
+ }
+ nav a, body > a {
+ border-left: 3px solid var(--fontcolor);
+ background-color: var(--blockbg);
+ }
+ nav a, body > a, nav span {
+ padding: calc(var(--stdpadding) / 2) calc(var(--stdpadding) / 4 * 3);
+ margin: 0 0 calc(var(--stdpadding) / 2) 0;
+ }
+ body > a {
+ margin-left: 0;
+ }
+ pre > code, .codetitle {
+ border-width: .1rem;
+ width: initial;
+ }
+ @media (max-width: 43rem) {
+ .buttons > * {
+ width: 24%;
+ }
+ .buttons > a > img {
+ width: 100%;
+ }
+ }
+ #leftsidebg, #rightsidebg {
+ top: 0; left: 0; right: 0; bottom: 0;
+ box-shadow: 100vw 0 0 #000000bb inset;
+ }
+ tr:hover {
+ background-color: initial;
+ }
+ td {
+ display: block;
+ }
+ @media (prefers-contrast: more) {
+ #leftsidebg, #rightsidebg {
+ display: none;
+ }
+ }
+}
+
+@media screen and (orientation:portrait) {
+ .gallery {
+ flex-direction: column;
+ }
+}
+
+/* TODO: Light theme
+@media (prefers-color-scheme: light) {
+ :root {
+ --bgcolor: #dffffa;
+ --fontcolor: #222222;
+ --blockbg: #0001;
+ --blockbghover: #00000022;
+ --stdshadow: #19191977;
+ }
+}
+*/
+
+@media (prefers-contrast: more) {
+ body {
+ color: white;
+ background-color:#111111;
+ }
+ #leftsidebg, #rightsidebg {
+ display: none;
+ /*box-shadow: 100vw 0 0 #000000ee inset;*/
+ }
+ a {
+ color: #00ffd5;
+ }
+}
+
+/* TODO: Low contrast theme */
+/*@media (prefers-contrast: less) {
+
+}*/
+
+@media (prefers-reduced-motion) {
+ * {
+ transition-duration: 0s !important;
+ }
+}
+
+@media print {
+ body {
+ text-shadow: none;
+ color: black;
+ }
+ h1 {
+ margin-top: initial;
+ }
+ nav, form {
+ display: none;
+ }
+} \ No newline at end of file
diff --git a/uses/bg.jpg b/uses/bg.jpg
new file mode 100644
index 0000000..6207c5a
--- /dev/null
+++ b/uses/bg.jpg
Binary files differ
diff --git a/uses/bg.jxl b/uses/bg.jxl
new file mode 100644
index 0000000..c6da977
--- /dev/null
+++ b/uses/bg.jxl
Binary files differ
diff --git a/uses/compier/bg.jpg b/uses/compier/bg.jpg
new file mode 100644
index 0000000..f9bf6a3
--- /dev/null
+++ b/uses/compier/bg.jpg
Binary files differ
diff --git a/uses/compier/images/cans.jpg b/uses/compier/images/cans.jpg
new file mode 100644
index 0000000..9cd76c0
--- /dev/null
+++ b/uses/compier/images/cans.jpg
Binary files differ
diff --git a/uses/compier/images/cans.jxl b/uses/compier/images/cans.jxl
new file mode 100644
index 0000000..ac9e92b
--- /dev/null
+++ b/uses/compier/images/cans.jxl
Binary files differ
diff --git a/uses/compier/images/pc1.jpg b/uses/compier/images/pc1.jpg
new file mode 100644
index 0000000..9e942c6
--- /dev/null
+++ b/uses/compier/images/pc1.jpg
Binary files differ
diff --git a/uses/compier/images/pc1.jxl b/uses/compier/images/pc1.jxl
new file mode 100644
index 0000000..cdd6ca7
--- /dev/null
+++ b/uses/compier/images/pc1.jxl
Binary files differ
diff --git a/uses/compier/images/pc2.jpg b/uses/compier/images/pc2.jpg
new file mode 100644
index 0000000..018cee1
--- /dev/null
+++ b/uses/compier/images/pc2.jpg
Binary files differ
diff --git a/uses/compier/images/pc2.jxl b/uses/compier/images/pc2.jxl
new file mode 100644
index 0000000..10a84be
--- /dev/null
+++ b/uses/compier/images/pc2.jxl
Binary files differ
diff --git a/uses/compier/index.php b/uses/compier/index.php
new file mode 100644
index 0000000..65aa3ee
--- /dev/null
+++ b/uses/compier/index.php
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>My Computer</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true); ?>
+ <h1>the comp<em title="Is that a Homestar Runner reference?">ier</em></h1>
+ <h2 id="caption">my main computer</h2>
+ <p>My main PC is an ever-shifting, questionably arranged agglomeration of components selected as if at random, initially designed and assembled by yours truly circa March of '22. Apparently, I have a lot to say about it.</p>
+ <div class="gallery">
+ <figure class="media">
+ <div>
+ <picture>
+ <source srcset="images/pc1.jxl" type="image/jxl">
+ <img src="images/pc1.jpg" alt="Front view of my computer tower. It's black, with solid metal side panels and a mostly grey front panel. It has four 5.25&quot; expansion bays and two 3.25&quot; external expansion bays. The top 5.25&quot; bay contains an optical drive and the rest are filled with a 3D-printed vent for an extra fan. One of the 3.25&quot; bays is occupied by an aftermarket front I/O panel with two USB 3 ports and headphone and mic jacks. Below that is the power and reset buttons and power and hard drive LEDs, and then the stock intake vent. The very bottom piece of said vent has a USB logo printed on it. There's also a Pentium 4 sticker.">
+ </picture>
+ <figcaption style="margin-top: 0;">"Intel Inside" technically isn't a lie &mdash; the motherboard has an Intel wi-fi controller.</figcaption>
+ </div>
+ </figure>
+ <figure class="media">
+ <div>
+ <picture>
+ <source srcset="images/pc2.jxl" type="image/jxl">
+ <img src="images/pc2.jpg" alt="The inside of my computer. All of the components are promintently visible. Two intake fans are mounted on the bottom, directly below the GPU. My cable management is serviceable, with a lot of extra length crammed in the dead space between the top-mounted PSU and the optical drive. Also visible from this angle are the abnormally large feet.">
+ </picture>
+ <figcaption style="margin-top: 0;">Yes, I had to cut holes in the bottom for those fans. I also had to get a right angle adapter for the USB 3.0 header since these fans actually block the big dumb cable that hooks up there. Totally worth it &mdash; this is actually a <em>better</em> airflow situation for the GPU than the old case.</figcaption>
+ </div>
+ </figure>
+ </div>
+ <h2>Internals</h2>
+ <h3>CPU &mdash; AMD Ryzen 7 5700G</h3>
+ <p>The Ryzen 7 5700G is basically the 5800 except cheaper and you trade PCIe gen 4 support for an integrated GPU. This was important to me in case my dedicated GPU died or otherwise became unavailable. This has come in useful occasionally.</p>
+ <h3>CPU Cooler &mdash; Noctua NH-U12A</h3>
+ <p>Admittedly, a bit overkill for the 65-watt chip it's attached to. I bought it because I was getting thermal throttling with the stock cooler, but when I took it off to put the new cooler on I discovered I hadn't mounted the stock cooler properly to begin with. The stock cooler, mounted correctly, would probably have sufficed, but frankly that mounting system was dogshit anyway. SecuFirm&trade; gang 4 lyfe.</p>
+ <p>Now that I have it, this cooler is great. Nothing specific to say, it just works and works <em>very</em> well. I wouldn't be surprised if this was the first and last CPU cooler I ever buy. My one complaint is that the fan clips are kind of annoying to deal with.</p>
+ <h3>Motherboard &mdash; Gigabyte B550 AORUS PRO AC</h3>
+ <p>Nothing much to say here that you couldn't get from the product page on Newegg. Plenty of external I/O, though internal I/O has proven limited, and has yet to cause any problems with operation. I chose it partly for the included wireless functionality, which now mostly gets used for my bluetooth Xbox controller ever since I upgraded to a wired connection.</p>
+ <p>I recommend this motherboard if for some reason you're building an AM4 gaming system in $CURRENT_YEAR, but be warned that the screws holding the M.2 heatsinks down are made of cheese and <em>will</em> snap off if over-torqued. Don't ask me how I know. Also, the included Wi-Fi antenna is fugly and has an absolutely pathetic mounting magnet.</p>
+ <h3>RAM &mdash; G.Skill Ripjaws V 2x16GB DDR4-3600 CL18</h3>
+ <p>Good RAM. No complaints. I thought for a while that the XMP profiles weren't compatible with my CPU or something, but an update to my motherboard's BIOS solved that.</p>
+ <h3>Boot SSD &mdash; Samsung 980 500GB (NVMe)</h3>
+ <p>Used solely to store my OS and programs. Far bigger than necessary for that purpose, but no issues so far. Plenty fast and all that. I initially assumed it had DRAM, then I learned it didn't, <em>then</em> I learned that it's one of those drives that leeches off of your system memory instead of having an onboard cache, so make of that what you will.</p>
+ <h3>Secondary SSD &mdash; WD Blue 2TB (NVMe)</h3>
+ <p>This drive is mounted as /home, for convenient OS reinstalls and such-like. Also nice and zippy, but I suspect I'm not actually doing anything that would hit this thing hard enough to noticeably differentiate its performance from that of any other NVMe SSD. This one also uses your system memory as a cache, but that's fine. I've got plenty to go around.</p>
+ <p>The drive that used to fill this role was a WD Blue 1TB SATA SSD that started off serving the same purpose as an aftermarket upgrade to my old laptop, but got transplanted wholesale when I upgraded to the new system. That drive still functions, but since it holds all my most sensitive and irreplacable files, I elected to replace it for Peace Of Mind&trade; after my PSU exploded, and opted for a cheeky capacity upgrade while I was at it. Plus, this one was on sale for like, $90 off!</p>
+ <h3>HDD &mdash; WD Black 4TB (7200RPM)</h3>
+ <p>This drive is here as an overcorrection following years of gaming on laptops with tiny little SSDs in them. I mostly fill it with Legally Obtained Content&trade; and the dregs of my Steam library that I don't play very often. Absolutely no complaints thus far.</p>
+ <h3>Case &mdash; Dynex DX-350CC</h3>
+ <p>I seem to have accidentally gotten into building sleeper PCs. I promise I didn't mean to &mdash; I was drawn to this case for its superior expandability, greater ease of working-on, and massively increased piezo-buzzer-havingitude compared to the Corsair 110R this machine used to reside in. It just so happens to also be from 2004, back when "Pentium" was the name for Intel's flagship line of CPUs instead of their worst ones and I was learning to walk.</p>
+ <p>For all those reasons plus its absolutely charming aesthetic character, I really like this case. Unlike the last guy, I can actually get at the modular PSU without yanking it out and scratching all the paint off. It even constitutes an upgrade in terms of front I/O and airflow, after some aftermarket mods.</p>
+ <p>See, this case came with mounts for two 92mm fans, which is better than some of its contemporaries, but not nearly enough for several hundred watts of glistening, sinewy computing muscle. In order to bring it up to modern snuff, I cut a couple slightly sketchy speed holes in the bottom and 3D-printed a bracket and vent for the front drive bays, and mounted the 120mm fans out of my old case in those places. I also fitted some slightly goofy-looking aftermarket rubber feet to give the case more ground clearance to get better airflow from the bottom. Since I now have two entire fans blowing directly onto the GPU, I'd guess that it's actually getting <em>better</em> airflow than in the old case.</p>
+ <h3>Power Supply &mdash; EVGA SuperNOVA G6 1000W</h3>
+ <p>This power supply is a tad bit overkill for the system it's in &mdash; in spite of my new video card, I'm still running a 65-watt CPU. I've got so much headroom I could probably fit a second of the same GPU in here. I could probably get away with a 750-watt unit, but I've got good &mdash; or at least understandable &mdash; reasons for going this crazy.</p>
+ <p>I originally specced out this system with a much more sensible Seasonic Focus GX-650 rated for 650 watts, but despite being, by all accounts, the correct power supply for my use case at the time, it still died suddenly with a loud POP two and a half years into Seasonic's 10-year Worry-Free Warranty&trade;. The RMA process was good, at least.</p>
+ <p>I wanted to get something less likely to suffer the same fate this time around, but having just lost a well-reviewed unit from a reputable brand with a good efficiency rating and a generous yet sensible rated wattage to nothing but bad luck, the only thing I could really do to maybe accomplish this other than just getting luckier was to buy something so overbuilt that it no longer regards my machine running at full bore as a significant load, hence this absolute goliath of a PSU. The original plan was to get a slightly more reasonable 850 watt unit instead, but this one was on a really good sale. I basically paid 850-watt money for it.</p>
+ <p>As of writing a few months after installing it in my system, my plan has yet to backfire. Time will tell if I made the right call.</p>
+ <h3>Optical Drive &mdash; LG WH16NS40 Blu-Ray Burner</h3>
+ <p>It's really important to me that my computer have a disc drive, and this was the cheapest unit available that supported all the major formats. Like most of the parts in my computer, it functions reliably as advertised without significant issue and I don't have much to say on the matter. This thing isn't just for the Aesthetic&trade; &mdash; I have a decently large collection of CDs that I've ripped using my computer.</p>
+ <p>I used to have a WH<em>14</em>NS40, which is basically the same save for slightly worse performance in certain specific contexts and a weird firmware issue to do with ripping 4K blu-rays. I had no problems with it, but I had to cannibalize it from my main rig for a different build and ended up replacing it with this, the closest thing available to the exact same unit.</p>
+ <h3>Case Fans &mdash; Arctic P12 (x3) + Noctua NF-A9 (x2)</h3>
+ <p>All perfectly fine fans. The 120mm Arctic P12s are good value at a good noise level, but in my experience the same cannot be said for their smaller fans, hence the premium Noctuas for the 92mm fan mounts.</p>
+ <p>I've also got random generic dust filters on all the intakes in a desperate attempt to sort of control the dust buildup inside my machine. It kind of works.</p>
+ <h3>GPU &mdash; AMD Radeon RX 6800 XT</h3>
+ <p>Fine, enough edging. Here's the part you're probably actually interested in, you filthy gamer.</p>
+ <p>I got this card used in late 2024 for circa half of its launch MSRP &mdash; I would not have been able to justify something this high-end brand new, especially at scalper prices when I was initially building this machine. I used to run an RX 6600 XT, but I had a project going which urgently required a quality video card and I'd been looking for an excuse to upgrade the one in my machine for a while, so out it came and a-scouring the eBay listings I went.</p>
+ <p>Gaming wise, the 6600 XT was about all I really needed. Frankly, I could probably get by on the integrated graphics in my CPU, but I quite like having two display outputs to complement my second monitor. This new GPU is ludicrous overkill for me in this department; it's marketed towards playing the latest triple-A titles at maxed-out settings in 4K, which means it completely pulverizes every PSX-graphics indie title I can throw at it with the overwhelming force and ruthless efficiency of the Chicxulub impactor.</p>
+ <p>The real reason I wanted this orbital nuke of a graphics processor was for Blender. If Blender Open Data is to be believed, this thing represents a more than doubling of the performance available to me in the Cycles rendering engine, which translates to a substantial improvement in render times. Of course, a mid-range Nvidia product would be better here than anything AMD is capable of, but as a known Linux user that was a no-go for me; I've heard nothing but horror stories about Nvidia GPUs and desktop Linux, and my personal experience frankly corroborates them. The venerable Mr. Torvalds said it best: <a href="https://youtu.be/iYWzMvlj2RQ">fuck 'em</a>.</p>
+ <p>There were a handful of GPUs in this performance class and approximate price bracket that I was considering &mdash; in fact, my original upgrade plan was a 7700 XT. I went with the 6800 XT because I deduced through the awesome power of spreadsheets that, with the current state of the used market, it had all the others beat in price-to-performance ratio, and it wasn't even close. I specifically went for the AMD reference model, since it was the only version with a short enough heatsink that I was confident it would fit in my case without any modifications.</p>
+ <p>I want it on record here that if I ever drop north of a grand on a 4090 or whatever the biggest baddest new this-or-a-used-car AAA-cruncher is and I haven't won the lottery, I am to be taken out back and shot like a lame horse. Frankly, I probably need some sense beaten into me if I'm buying lottery tickets to begin with.</p>
+ <h2>Peripherals</h2>
+ <h3>Mouse &mdash; Logitech G602</h3>
+ <p>This is my forever mouse. Excellent build quality, more than good enough performance for my casual gamer ass, and it takes AAs. I recently took it apart to replace the first component to start failing, the switch for the left mouse button. I intend to keep using this mouse until I can't get replacement parts for it, or I get carpal tunnel and have to upgrade to something with better ergonomics.</p>
+ <p>I generally prefer wired peripherals where possible, but the RF dongle this mouse uses has been rock-solid for me, as long as I don't keep it behind a bunch of EMI-blocking metal panels. My only real issue with this mouse is that the software for it doesn't work on Linux, but I only need that to configure the side buttons.</p>
+ <h3>Keyboard &mdash; Keychron V3 and Q0</h3>
+ <p>I would have just gotten a 100% keyboard, but they didn't have it in the chassis colour I wanted so I ended up with a TKL and separate numpad instead. I'm a huge fan of both, what with the open-source firmware and hot-swappable switches and all. I especially like the extra included keycaps for use with a Mac, not because I intend to use it with a mac, but because it lets me finally get rid of the fucking Windows logo on my keyboard.</p>
+ <p>Unless I lose them in a house fire or something, I think these units probably constitute my "endgame", as keyboard enthusiasts say. They have every feature I care about and every upgrade or change I can see myself caring to make is maximally easy. This is one of those things that I shelled out for with the intent of never, ever replacing it.</p>
+ <h3>Gamepad &mdash; Xbox One wireless controller</h3>
+ <p>I bought this several years ago when I was still running Windows because I wanted maximum compatibility for minimum effort. It still works now that I'm on Linux, using bluetooth and with xpadneo installed. It's decent, no complaints, I'm sure it could be better but I don't use it enough to justify caring.</p>
+ <h3>Monitors &mdash; MSI MAG274QRFW 27" 1440p 180Hz (2x)</h3>
+ <p>Another "endgame" purchase. Very good monitors, if I replace them it'll be because they broke. (Speak of the devil, one of them has been replaced under warranty since I originally wrote this section.) I truly don't care for OLEDs &mdash; they get burn-in, for god's sake, I thought we moved on from that in the early 2000's when LCDs became commonplace.</p>
+ <p>These are mounted on a cheap, AmazonBasics-tier VESA monitor stand that came with a huge metal foot that kind of defeated the purpose, but that I have since replaced with a much more compact combination of 3D-printed brackets and wood screws.</p>
+ <h3>Headphones &mdash; Beyerdynamic DT 770 Pro (Modified)</h3>
+ <p>After a lifetime of losing headphones to frayed cables and the inevitable failure of poor quality materials, my top priority when getting my next nice pair of cans was durability, and Beyerdynamic's products fit the bill nicely. As a bonus, they also have excellent sound quality and are supremely comfortable.</p>
+ <p>The only issue with these headphones is the non-removable cable, which is an automatic deal-breaker for me. I purchased mine through a modding company that replaced that cable with a 4-pin mini XLR jack, which has proven to be a bit of a double-edged sword as finding sanely priced replacement cables for it is nigh impossible.</p>
+ <p>I'm also rocking aftermarket cat ears. I just don't trust the quality on the cheap novelty headphones that come with them built in.</p>
+ <picture>
+ <source srcset="images/cans.jxl" type="image/jxl">
+ <img src="images/cans.jpg" alt="A pair of Beyerdynamic DT 770 Pro headphones with a removable mini XLR cable plugged in, a custom green headband wire, and aftermarket cat ears.">
+ </picture>
+ <h3>Drawing Tablet &mdash; HUION Kamvas Pro 12</h3>
+ <p>Perfectly cromulent 12-inch display tablet. It doesn't completely work out of the box, but the proprietary driver program is at least available for Linux. I like that the stylus is completely passive and doesn't need to be charged, which is frankly an absurd thing for a stylus to require.</p>
+ <h3>Webcam &mdash; Logitech C925e</h3>
+ <p>It's a USB webcam. The picture is good enough &mdash; better than most laptops &mdash; but it does some annoying auto-adjustment stuff that makes chroma-key shenanigans difficult at times. Standout features are the privacy shutter, indicator light when the camera is in use, and screw mount. I'm sure the microphone is adequate in a pinch, but I have no reason to use it.</p>
+ <h3>Microphone &mdash; Audio-Technica AT2020 USB+</h3>
+ <p>Very good microphone. Probably as good as I'll ever need. Superb sound quality; my friends in voice chat complain whenever they hear me on anything else. I'd have gotten the XLR version but I did not yet own an audio interface and didn't want to shell out for one just for this.</p>
+ <p>In what is becoming a running theme, it sits on a perhaps unbefitting $20 no-name mic arm from Amazon, with matching cheap shock mount and pop filter. They work, though. The springs on the arm are loud and, as my friends are keen to point out every time, quite audible through the mic.</p>
+ <h3>Audio Interface &mdash; Arturia Minifuse 2</h3>
+ <p>Nothing to write home about for the most part. It's a good quality audio interface with the amount of I/O I presently need, which is to say two mono inputs, and it mostly works fine on Linux. Bizarrely, though, between this and my Benhringer Model D, the only device with a MIDI interface that's recognized by my computer is the analog synthesizer.</p>
+ </body>
+</html>
diff --git a/uses/cumulonimbus/bg.jpg b/uses/cumulonimbus/bg.jpg
new file mode 100644
index 0000000..27a1ed4
--- /dev/null
+++ b/uses/cumulonimbus/bg.jpg
Binary files differ
diff --git a/uses/cumulonimbus/bg.jxl b/uses/cumulonimbus/bg.jxl
new file mode 100644
index 0000000..1882e7d
--- /dev/null
+++ b/uses/cumulonimbus/bg.jxl
Binary files differ
diff --git a/uses/cumulonimbus/index.php b/uses/cumulonimbus/index.php
new file mode 100644
index 0000000..b0d8b5a
--- /dev/null
+++ b/uses/cumulonimbus/index.php
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>cumulonimbus</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true); ?>
+
+ <h1>cumulonimbus</h1>
+ <h2 id="caption">get it? 'cause it's in da cloud</h2>
+ <p><code>cumulonimbus</code> is an OVH KS-1 dedicated server and the larger, more intimidating successor to <code>cumulus</code>, the DigitalOcean VPS that I used to use. Its specs are as follows:</p>
+ <ul>
+ <li>CPU: 4c/8t Intel Xeon-D 1520</li>
+ <li>RAM: 32GB DDR4-2133 ECC</li>
+ <li>SSD: 480GB Mirrored RAID</li>
+ <li>OS: Ubuntu Server 24.04 LTS</li>
+ <li>Bandwidth: 300Mbps symmetrical</li>
+ </ul>
+ <p>As appears to be a pattern for me, it's massive overkill for what I need it for, but as I expand on <a href="/blog/posts/renting_an_unremarkable_server/">here</a>, it's actually close to half the price of the much wimpier old VPS. Pretty crazy.</p>
+ <h2>Software</h2>
+ <h3>OS - <a href="https://ubuntu.com/server">Ubuntu Server 24.04</a></h3>
+ <p>Canonical isn't my favourite company, but Ubuntu server is fine enough and it's what I'm used to for servers. I have never once had any major problems with this.</p>
+ <h3>Web Server/Reverse Proxy - <a href="https://caddyserver.com/">Caddy</a></h3>
+ <p>This is the software that makes all my websites (of which there are now several) and other services available to the internet. I used to use Nginx for this, and both programs do this job quite well, but I like Caddy because it's much simpler to configure and handles HTTPS automatically for you.</p>
+ <h3><a href="https://radicale.org/v3.html">Radicale</a></h3>
+ <p>A fairly basic and extremely reliable solution for hosting synced calendars and contacts lists. It even tolerates my abuse of symlinks to create a shared calendar for my family, a feature it does not support by default.</p>
+ <p>This isn't really a reflection on Radicale, but I really appreciate that somehow, Apple has decided to build CalDAV support directly into iOS. Even Android needs a third-party app for that.</p>
+ <h3><a href="https://activitypub.software/TransFem-org/Sharkey">Sharkey</a></h3>
+ <p>When it became clear that Firefish was a dead project, my choices for migrating my fedi instance were a burgeoning hate-fork of Firefish and a fork of upstream Misskey that required directly tinkering with the instance database in order to migrate. Apparently I preferred the latter.</p>
+ <p>It's a pretty damn good user experience by my estimation, and it has a lot of nice features I use and a hell of a lot of nice features that I don't. It's kind of a miracle it works as well as it does with all this stuff in it. The frontend is pretty heavy, but that's obviously not an issue for me.</p>
+ <p>If you're going to install any Misskey derivative, I'd strongly recommend just using the Docker image. Installing it natively requires you to essentially download the source code and compile it yourself, and if you're not used to the Node.js ecosystem it's really more trouble than it's worth.</p>
+ <h3><a href="https://forgejo.org/">Forgejo</a></h3>
+ <p>My needs aren't really comprehensive enough to speak on the quality of Forgejo as a git forge beyond that it seems pretty good and does everything I need. I do like how easy it is to update.</p>
+ <h3><a href="https://freshrss.org/">FreshRSS</a></h3>
+ <p>I ended up with this because I elected to ditch Nextcloud in the process of migrating hosting providers, and this was the first RSS reader that I managed to get working on the new server. I swear, it's like the RSS 2.0 spec states that your self-hosted RSS reader has to have installation instructions that don't work.</p>
+ <p>I've yet to find an RSS reader with a user experience I like, but this one is tolerable enough that I don't think "I should really find a replacement for this" every time I use it like I did when I was using Whatever Nextcloud Has&trade;, plus it supports a couple common APIs so I can replace the frontend if I decide I hate it.</p>
+ <p>Speaking of which, I'm currently using a mobile app called Capy Reader to access this on my phone since the mobile web UI kind of sucks.</p>
+ <h3><a href="https://github.com/RSS-Bridge/rss-bridge">rss-bridge</a></h3>
+ <p>Extracts RSS feeds from a genuinely kind of shocking number of websites that don't otherwise have them. I make generous use of this. Feel free to use <a href="https://rss-bridge.bathynomus.xyz/">my instance</a> if you want.</p>
+ <h3><a href="https://docs.searxng.org/">SearXNG</a></h3>
+ <p>Aggregates search results from various other search engines. Does that job well and has like, a lot of options to customize where it pulls results from. I wish it had more powerful image result filtering tools, though.</p>
+ <h3><a href="https://github.com/dani-garcia/vaultwarden">VaultWarden</a></h3>
+ <p>My password manager. Before this I used KeepassXC in conjunction with Syncthing to get it onto my phone, which was a pretty good solution, with the one downside that I could only add passwords from my PC because I didn't completely trust Syncthing not to disappear one of my passwords in a syncing conflict. My primary motivation for switching to this was that it eliminates that concern. It's also just good in general.</p>
+ <p>This makes two services I'm self-hosting even though my paid Protonmail account also has them.</p>
+ <h3><a href="https://zadzmo.org/code/nepenthes/">Nepenthes</a></h3>
+ <p>A tarpit for AI scrapers. Self-explanatory at this point.</p>
+ </body>
+</html>
diff --git a/uses/images/switchback.jpg b/uses/images/switchback.jpg
new file mode 100644
index 0000000..ad388d8
--- /dev/null
+++ b/uses/images/switchback.jpg
Binary files differ
diff --git a/uses/images/switchfront.jpg b/uses/images/switchfront.jpg
new file mode 100644
index 0000000..29cd7c4
--- /dev/null
+++ b/uses/images/switchfront.jpg
Binary files differ
diff --git a/uses/index.php b/uses/index.php
new file mode 100644
index 0000000..72423a3
--- /dev/null
+++ b/uses/index.php
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>My setup</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+</head>
+
+<body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(); ?>
+ <h1>my setup</h1>
+ <h2 id="caption">If yours is different you're objectively stupid</h2>
+ <h2>Computers</h2>
+ <a href="compier/" id="compier">comp<em title="Is that a Homestar Runner reference?">ier</em></a>
+ <p>My main PC, a mid-tower desktop "designed" and built by me, boasting a Ryzen 5700G, 32 gigs of DDR4, something like 6 terabytes of storage, a comically overbuilt PSU, and a graphics card. It runs <a href="#eos">arch, btw</a>.</p>
+ <a href="servy586/" id="servy586">Servy 586</a>
+ <p>A home-built TrueNAS box assembled from used gaming parts that could pass for a high-end, if a little dated, gaming rig if not for the preponderance of hard drives I put in it in place of a competent GPU. Much more stable than the <a href="/blog/posts/building_a_normal_server/">old one</a>.</p>
+ <p>Read about its conception and construction <a href="/blog/posts/building_a_sensible_server">here</a>.</p>
+ <h3>Libre Computing Le Potato</h3>
+ <p>A Raspberry Pi clone that I use to run Pi-hole, and that's it. I wanted a machine that was isolated from my incessant tinkering with the big boy server.</p>
+ <a href="cumulonimbus" id="cumulonimbus">cumulonimbus</a>
+ <p>The cloud server that runs this website and almost everything else I self-host that's accessible from the public internet, because paying two <span title="An Imperial Netflix Subscription, sometimes abbreviated to INS, is an approximate unit of cashflow based on the price of a Standard tier Netflix subscription in the mid-2010s. It generally refers to a window of anywhere from $10 to $14 per month depending on context. One Metric Netflix Subscriptionne, or MNS, is equal to exactly €10 per month.">Imperial Netflix Subscriptions</span> is better than dealing with the endless maze of headaches that is pointing your DNS records to a machine on a residential connection at a shared dwelling.</p>
+ <p><a href="/blog/posts/renting_an_unremarkable_server">I wrote a blog post about it!</a></p>
+ <h3 id="phone">Google Pixel 8a</h3>
+ <p>This counts as a personal computer.</p>
+ <p>Chosen solely because it was the most recent Pixel at a sane price, I was pushed to upgrade to this from my old 4a by the impending end of software support for 5th generation and older Pixels. Turns out, buying a used Android is a good way to not get security updates for most of the device's useful life, and if I'm gonna bother with <a href="#graphene">GrapheneOS</a> it would behoove me to make sure I'm up to date on those.</p>
+ <p>Seeing for myself the difference that four years of iteration has made to the a-series Pixels has only solidified my perception that smartphones are as good as they'll ever need to be and have been for quite some time. The faster processor, nicer screen, and better camera in this year's model don't make a difference for the things I do with my phone, and the lack of a headphone jack has already proven inconvenient.</p>
+ <p>That said, the loss of the headphone jack did not come without its benefits in exchange. The 8a is broadly a nicer and more premium-feeling device than the 4a, and I specifically appreciate the wireless charging and faster cellular data connection more than I was expecting to. Bizarrely, even my 4G LTE speeds in areas without 5G service seem to be drastically improved.</p>
+ <p>I also like some of the new features in newer versions of Android that never released for the 4a, chief among them the "Charging Optimization" switch that limits the battery to 80% charge to preserve its health long-term, which I'll be needing since I plan to keep this sucker for the entire <em>seven years</em> that it's slated to keep getting security updates. Extraordinarily rare Google W.</p>
+ <h2>Consoles</h2>
+ <h3>New 2DS XL (Hacked)</h3>
+ <p>Did you know it's surprisingly easy to hack your 3DS? <a href="https://3ds.hacks.guide/">Do it now!</a></p>
+ <p>I also used to have a Switch, but I've sold it on account of I never really use the thing anyway. I still wanna show off the dope clear shell mod I did to it though, so here's that:</p>
+ <details>
+ <summary>dope awesome nintendo pictures</summary>
+ <img src="images/switchfront.jpg" alt="Front view of a Nintendo Switch with clear plastic shells on the joycons" />
+ <img src="images/switchback.jpg" alt="Back view of a Nintendo Switch with clear plastic shells on the joycons and console" />
+ </details>
+ <h2>Other Hardware</h2>
+ <h3>Prusa MINI+</h3>
+ <p>I bought a Prusa because their printers have a reputation for quality, which this unit has certainly lived up to. It's been quite reliable, and when it fails, it's usually my fault in a really obvious way. It automates a lot of features that I suspect would have been pain points on a cheaper printer, up to and including uploading gcode to it directly over the network. This thing's easier to use than a regular 2D printer!</p>
+ <p>My one major issue is that the cantilevered gantry results in a slight inaccuracy in the Z axis, meaning the first layer is too high on one side of the bed and too low on the other. I suspect that this is why they didn't make it bigger, although it could also just be my fault for going and ordering the un-assembled kit version to save money on assembly.</p>
+ <p>I run mine with Prusa's satin textured bed plate for easier removal of PETG parts (I managed to damage the included smooth plate printing big stuff in PETG) and a 0.6mm Diamondback nozzle for printing with filaments with abrasive additives. It's expensive for a nozzle, but I think for the last nozzle I'll ever need to buy on an already 700 Canadian Victory Point printer it makes sense. I used to run an E3D Nozzle X, but I think I wrecked the coating trying to clean it with a brass wire brush.</p>
+ <h3>CyberPower CP1500PFCLCD</h3>
+ <p>A UPS that powers my computer, server, and related paraphernalia. I got it for all the normal reasons you get a UPS (power outage protection and such-like) and it has thus far performed as advertised. I wouldn't try to game off of the thing, but it's proven more than sufficient to keep my machines on long enough for a graceful shutdown in the event of a power outage. Highly recommend getting one.</p>
+ <h3>Netgear GS308</h3>
+ <p>It's a gigabit network switch. It has 8 ports. It performs as advertised. What else is there to say?</p>
+ <h3>CMF Watch Pro 2</h3>
+ <p>I used to be the kind of unconditional tech enthusiast who thought smartwatches as a premise were really cool, but that was when I was like 13, and the novelty of my Moto 360 and its adorable little WearOS videogames honestly wore off pretty quick. I'm not so Tiktok-brained that grabbing my phone out of my pocket to check the time or my notifications or whatever registers as an inconvenience, let alone to the extent that I would want to buy a smartwatch about it.</p>
+ <p>So why'd I buy this then? For me, it's about the biometric sensors. Primarily I just wanted some hard data to assuage some anxiety I was having about the state of my heart, and a device that costs as much as a dedicated heart monitor while doing all the other smartwatch stuff <em>and</em> not making me feel like a paranoid weirdo for owning it seemed like a pretty damn good deal to me.</p>
+ <p>The smartwatch itself is fine. The custom OS it runs is a little more basic than even circa-2016 WearOS in terms of software features, but I honestly don't care about any of that stuff anyway, and it's actually really nice for the hundred Canadian Zero-Calorie Sugar-Free Diet Dollars and free shipping that they're charging, although I wish the app reported more detailed biometric data, said the undisputed queen of run-on sentences.</p>
+ <p>The one problem I'm having so far is that after like a month the included pleather wristband is starting to discolor and flake off and generally do Pleather Things&trade;, but frankly this is a very cheap smartwatch and I'd rather them cut costs on the one part I can easily replace than on, like, the battery or the CPU or some shit. Hopefully this isn't indicative of the long-term endurance of the actual device.</p>
+ <h2>Software</h2>
+ <h3 id="eos"><a href="compier">Desktop</a> Operating System - <a href="https://endeavouros.com/" target="_blank">EndeavourOS</a> (Linux)</h3>
+ <p>My <a href="#compier">main computer</a> runs EndeavourOS with the GNOME desktop environment. I chose it mostly to get the AUR, which has occasionally proved useful, but at this point I'm kind of stuck here because all the config files for my programs are in standard locations, god forbid, and everyone else is on flatpaks now, which fuck that all up for no good reason. I once <a href="https://isopod.cool/blog/posts/my_terrible_distro_hop/">failed to switch to Fedora</a> because of this.</p>
+ <p>I have a long history with Linux, dating back to 2015 with the first computer I ever owned: a <a href="../blog/posts/toshiba_chromebook/">Chromebook</a> that I put Linux on to play Minecraft, which ChromeOS couldn't do in any meaningful capacity at the time. It took me all of nine months to blow it up doing that because it was passively cooled with a plastic shell and not designed to ever go above ~30% usage on the dinky little Celeron that was its excuse for a CPU. After that I got a real PC running Windows, which solved the Minecraft problem so I mostly stuck to that for the next six years, although I did make intermittent attempts to switch to Linux again.</p>
+ <p>I pulled it off for real in 2021, when I took a combination of upsetting news about the upcoming Windows 11 and an SSD upgrade to my laptop as an opportunity to swap out my operating system as well. It went pretty well, all told; I wasn't using much Windows-exclusive software other than Paint.NET and some games, the latter of which now run great on Linux anyway thanks to Valve's efforts with Proton. Shame I can't play all my Epic Games Store freebies anymore, though.</p>
+ <p>My current desktop environment of choice, as previously mentioned, is GNOME. I used to run XFCE, and KDE before that, but I got sick of all my stuff occasionally breaking on me and wanted to see if GNOME would be sufficiently UX-designed that it would Just Work&trade; and Not Get In My Way&trade; and all that. So far so mostly good. I was worried about how well Wayland would work, but it's basically fine, with the exception of Discord not playing nice with regards to screensharing.</p>
+ <h3 id="graphene">Mobile Operating System - <a href="https://grapheneos.org/">Graphene OS</a> (Android)</h3>
+ <p>On top of the bordering on iPhone-grade support lifetime, this here is the other reason I'm so brand-loyal to Google's first-party <a href="#phone">hardware</a>.</p>
+ <p>GrapheneOS is a fork of Android that's been security-hardened and de-googled, two of my favourite things for an operating system to be. It's dedicated to privacy and security above all else, almost to a fault. I'm told it's only available on the Pixel line because those phones have security hardware in them no other OEM on the planet can be bothered with.</p>
+ <p>GrapheneOS provides a few user-facing privacy features that I quite like, such as the ability to deny network and sensor access to apps in the permission settings, and a bunch of under-the-hood security improvements I'm woefully underqualified to explain short of just pasting stuff wholesale from their website.</p>
+ <p>Do I need this level of security? Probably not. Would I enjoy some of the features GrapheneOS strips out in the name of security? Possibly. But I like the peace of mind knowing that if cops ever get a hold of my phone they'll at least be kind of frustrated trying to access it.</p>
+ <h3>Web Browser - <a href="https://www.mozilla.org/en-US/firefox/new/" target="_blank">Firefox</a></h3>
+ <p>I quite like Firefox. It's extremely customizable (especially if you know where to look), the devtools are better, and there's a wealth of privacy tools available that just kind of don't exist in Chrome (including <a href="https://arstechnica.com/gadgets/2024/05/google-starts-deprecating-older-more-capable-chrome-extensions-next-week/">adblockers</a> as of late). It can also edit PDFs now!</p>
+ <p>On top of being generally superior, I also use Firefox on principle. It's currently the only major browser outside of the Apple-exclusive Safari that isn't built atop Google's <a href="https://chrome.bathynomus.xyz">Chromium</a>, and I don't like the idea of Google having total monopolistic control over all web browsers.</p>
+ <p>Firefox is one of the only pieces of software I'll actively advocate switching to, so go do it. Do it now. It, like essentially all other browsers, can <a href="https://support.mozilla.org/en-US/kb/import-bookmarks-google-chrome">import your data</a> from its competition, and I'd also recommend using this <a href="https://ffprofile.com/">profile generator</a> to fortify it for maximum privacy while you're at it.</p>
+ <p>All that said, Mozilla is under questionable management at the moment and kind of in Google's pocket anyway, so maybe we shouldn't be relying completely on them to champion the free web. Maybe throw some money in the general direction of the <a href="https://servo.org/">Servo</a> project.</p>
+ <p>I use the <a href="https://f-droid.org/packages/org.mozilla.fennec_fdroid/">Fennec</a> fork of Firefox on mobile, and <a href="https://github.com/ungoogled-software/ungoogled-chromium">Ungoogled Chromium</a> for the occasional poorly-built website (usually streaming services, work stuff, or banks) that doesn't want to run in my weird paranoid Firefox config.</p>
+ <h3>IDE - <a href="https://vscodium.com/">VSCodium</a></h3>
+ <p>Microsoft's Visual Studio Code is, loathe though I may be to admit it, my favourite IDE I've ever used, which is why I use VSCodium, an open-source build of VSCode with all the telemetry and shit stripped out.</p>
+ <h3>3D Graphics - <a href="https://www.blender.org/">Blender</a></h3>
+ <p>Lucky that the only 3D graphics program available on Linux just so happens to also be the best one. I use this sucker for just about everything it can theoretically do, from CAD to video editing, and even some things that it's actually good at!</p>
+ <h3>Photo Editor - <a href="https://www.gimp.org/">GIMP</a></h3>
+ <p>Honestly, what were you expecting? If you want to edit raster graphics on Linux, GIMP is more or less the be-all-end-all, unless you want to do everything in the terminal with ImageMagick. I'd prefer to use Paint.NET or even my Legally Obtained DRM-free copy of Photoshop CS6, but somehow photo editors are one of the only things that are consistently incompatible with WINE. I've been meaning to give <a href="https://www.photopea.com/">Photopea</a> a shot.</p>
+ <h3>DAW - <a href="https://www.reaper.fm/">REAPER</a></h3>
+ <p>My primary motivation for choosing REAPER is that it's available for Linux. My secondary motivation is that it has a lot less of the bizarre idiosyncracies and feature omissions that I found limiting when I was using LMMS. It's also cheaper for a perpetual license than even the shittiest most artificially-limited versions of most of the other major DAWs, although it's not like I can run any of them anyway.</p>
+ <h3>Media Players - <a href="https://wiki.gnome.org/Apps/Rhythmbox">Rhythmbox</a>, <a href="https://mpv.io/">MPV</a>, <a href="https://www.videolan.org/vlc/">VLC</a></h3>
+ <p>I use Rhythmbox for music, MPV for video, and VLC for anything that doesn't open one of the other two when I click on it. All three are very boringly good at what they do, and all three are varying levels of fugly.</p>
+ <h3>Torrent Client - <a href="https://www.qbittorrent.org/">qBittorrent</a></h3>
+ <p>This is the program I use to download my, uh, Linux ISOs. And local copies of Wikipedia. At least one of those is actually true. I've got it configured to only work through my VPN. I don't know if my ISP would actually get on my case if I torrented anything... unscrupulous without it, but I'd rather not risk it.</p>
+ <h3><a href="https://syncthing.net/">Syncthing</a></h3>
+ <p>Syncthing is a peer-to-peer automatic file syncing program that I use to automatically sync files between my various devices, peer-to-peer style. It works really well and I really like it. Among other things, I use it to get photos from my phone onto my PC, my music library from my PC onto my phone, and for automatic backups of both to my server.</p>
+ <h3>Notes - <a href="https://obsidian.md/">Obsidian</a></h3>
+ <p>The best user experience I've seen in a notes program since the Notes app on my iPhone 4S. The thing that sold me on it is that it saves your notes as markdown files in a user-defined folder, so I can point Syncthing to it. This beats out my previous solution of Whatever Nextcloud Has&trade; by a country mile. Let me know if you know of an RSS reader that works like this.</p>
+ <h3>Shell - <a href="https://www.zsh.org/">zsh</a></h3>
+ <p>I switched to zsh largely due to ambient peer pressure from the wider Linux community, and I doubt I'm taking full advantage of its many advanced features, whatever those are, but I do quite like how conducive it is to customization with such programs as <a href="https://ohmyz.sh/">Oh My Zsh</a> and <a href="https://github.com/romkatv/powerlevel10k">Powerlevel10k</a>, and I miss its improved tab completion and command history functionality whenever I'm ssh'd into one of my servers.</p>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/uses/servy586/4k_in_more_ways_than_one.png b/uses/servy586/4k_in_more_ways_than_one.png
new file mode 100644
index 0000000..3248da8
--- /dev/null
+++ b/uses/servy586/4k_in_more_ways_than_one.png
Binary files differ
diff --git a/uses/servy586/bg.jpg b/uses/servy586/bg.jpg
new file mode 100644
index 0000000..f909b63
--- /dev/null
+++ b/uses/servy586/bg.jpg
Binary files differ
diff --git a/uses/servy586/index.php b/uses/servy586/index.php
new file mode 100644
index 0000000..19fa1d5
--- /dev/null
+++ b/uses/servy586/index.php
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>My Home Server</title>
+ <link href="/style.css" rel="stylesheet" type="text/css" media="all">
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/seasonal.php'); ?>
+ </head>
+ <body>
+ <?php include($_SERVER['DOCUMENT_ROOT'] . '/nav.php'); bg(true); ?>
+ <h1>servy <span title="Are you perhaps detecting a pattern with how I name these?">586</span></h1>
+ <h2 id="caption">my home server</h2>
+ <p>Assembled from mostly used parts that range from vaguely sensible to <em>wildly</em> overspecced for my use case, my home server seems to have ended up as my personal exercise in gratuitous computing overkill, for the sort of peasant that can't afford <a href="4k_in_more_ways_than_one.png">4 grand for an RTX 4090</a>.</p>
+ <p>It got that way because I was trying to build a machine of a similar level of performance to the old gaming laptop that used to be my home server, before I <a href="/blog/posts/building_a_normal_server/">vivisected it and grafted on a NAS</a>, only to find that it didn't seem to like my doing that very much. Believe it or not, the point of this monster was to get away from the unusably bad stability issues the old server was having, and it seems to have worked. You can read more about how I justified it all to myself <a href="https://isopod.cool/blog/posts/building_a_sensible_server/">here</a>.</p>
+ <h2>Hardware</h2>
+ <h3>CPU - AMD Ryzen 7 3700X</h3>
+ <p>When I said "gratuitous computing overkill", this is primarily what I meant. For a home server, this high-end, albiet 5-year-old, gaming CPU is admittedly a little bit ridiculous. An Intel N100 Chromebook chip would be more than capable of most of the things this server is doing, but I had a good reason to go for something this fast: I knew I wanted to run Minecraft servers on this machine, possibly more than one, and with Minecraft, single-core performance is king. Even professional Minecraft hosting providers use chips like this, because enterprise-grade server hardware is worse than the consumer stuff for this task.</p>
+ <p>My line of reasoning for choosing this CPU was as follows: my currect machine has an i7-9750H in it, so I'll get the desktop version of that, the i7-9700K, for similar performance, except wait, the corresponding Ryzen chip from the same generation is a <em>way</em> better value on the used market, let's get that. And that's how I ended up <a href="https://www.cpubenchmark.net/compare/3425vs3485/Intel-i7-9750H-vs-AMD-Ryzen-7-3700X">accidentally doubling my multi-threaded performance</a> despite specifically setting out <em>not</em> to get a major upgrade. Realistically, though, I wouldn't have saved a ton of money going for something more in line with my stated goal anyway.</p>
+ <h3>CPU Cooler - Thermalright Peerless Assassin 120</h3>
+ <p>In what is becoming something of a theme here, I'm well aware that this cooler is ludicrously overbuilt for the chip I'm asking it to cool, but that's the point. This thing provides more than ample headroom for me to set a nice, relaxed, quiet curve on the machine's case fans, which is important since it's currently sitting right next to my desk.</p>
+ <h3>Motherboard - ASUS ROG CROSSHAIR VI HERO X370</h3>
+ <p>Also a bit of a silly motherboard for a home server, what with all the built-in Gaming Lights&trade; and fancy overclocking features. I need it though, because this is the only thing with all the expandability I need. It has eight whole SATA ports, exactly enough for all my drives, which saves me having to burn a PCIe slot on a SATA controller. This particular board also has another helpful feature: if add-in cards are installed in both the first and second PCIe x16 slots, it shares the bandwidth evenly between them for two x8 connections instead of having one x16 and one x4. This gives me enough lanes for the specific 10 gig network card I'm using.</p>
+ <p>Buying used components is always a bit of a risky play, and I initially thought this board, or the CPU, was dead on arrival when it failed to POST with a cryptic CPU error. Fortunately, I was able to fix it with the BIOS flashback feature. I may or may not have updated the BIOS, but it gives you so little feedback I don't know. I just inserted the USB drive, hit the flashback button and waited until it stopped blinking. Either way, it works now.</p>
+ <h3>RAM - Corsair Vengeance LPX 2x16GB DDR4-3200 CL16</h3>
+ <p>It's RAM. What can I say? I picked this particular kit because it was the cheapest one available from a brand I actually trusted. I bought this stuff new, since used DDR4 prices at the time were exactly the same anyway.</p>
+ <h3>GPU - Nvidia Quadro P400</h3>
+ <p>A bit of an anemic video card for gaming, but I'm not gaming on this machine, at least not like that. This card was both dirt cheap used and has the two features I was actually looking for and nothing more: literally any video output at all for first-time setup, and good transcoding performance for Jellyfin.</p>
+ <h3>Network Card - Dell Intel X540-T2 10GbE</h3>
+ <p>These old server NICs allow for 10 gigabit ethernet connectivity at rock-bottom prices. I originally bought two so I could put one each in the server and my main PC and direct-attach them, but limitations of my B550 motherboard killed that plan. This one still went in the server so it will be ready when I eventually upgrade to something that can accept the other card.</p>
+ <p>The one downside of these cheap old network cards is that the fans on them are pretty much always dying and tend to be very loud. I solved this problem by splicing a replacement fan onto the connector from the original, and mounting it to the card's heatsink with a zip-tie that's screwed into one of the original fan mounting holes.</p>
+ <div style="display: flex;">
+ <img style="width: 50%;" src="nictua.jpg" alt="A 40mm wide, 10mm thick Noctua fan zip-tied to the heatsink on a PCIe Ethernet card.">
+ <img style="width: 50%;"src="ziptiemount.jpg" alt="The zip-tie is screwed into one of the original fan mounting holes on the heatsink. As in, the screw is going through the zip-tie.">
+ </div>
+ <p>Lucky me the original fan is a standard 12 volt one and doesn't take, like, 19 volts or something stupid like that. I wouldn't put it past Dell.</p>
+ <h3>Power Supply - Seasonic GX-650 650W</h3>
+ <p>I originally bought a GX-650 for my main PC, then it blew up out of nowhere and I RMA'd it, but still bought a beefier replacement anyway out of both an abundance of caution and a desire for more GPU upgrade headroom. When this unit arrived, it ended up in my server. Again, it's overkill for what I need, but that's now my official strategy for PSUs.</p>
+ <h3>Case - Enlight 7237 (?)</h3>
+ <p>This Pentium 3-era case was among the first I found that could accommodate my needs for this machine, although I admit my search strategy was flawed. Still, I was enamoured with this case and, frankly, building in it was a pleasure compared to my experiences with modern cases. I can actually get to the modular PSU cables without removing anything! Imagine that! And in a case that <em>predates the concept of modular power supplies by fully half a decade</em>. In spite of its objectively dogshit airflow, this case makes me resent the modern Corsair box I originally built my main rig in.</p>
+ <p>Since this case appears to have been whitelabeled by a system integrator called Touch Computer before being emptied out and sold to me, there's no indication of what model it is, but it closely resembles the Enlight 7237, so I suspect it's either that or something closely related. Apparently these were very common back in the day, and I can see why.</p>
+ <figure class="media">
+ <div>
+ <div style="display: flex;">
+ <img style="width: 50%;" src="servercase.jpg" alt="A beige PC tower with four 5.25&quot; bays and two external 3.5&quot; bays, populated with an optical drive and a floppy drive respectively. The only visible branding is a Pentium III sticker and a badge that reads &quot;TOUCH&quot;.">
+ <img style="width: 50%;"src="servercaseinside.jpg" alt="The inside of the same old PC case. Its layout is extremely pragmatic: motherboard in the very bottom corner, PSU in the top corner above it, and all the drive bay mounts are in a cage lining the front side. In other words, it looks like an old PC case.">
+ </div>
+ <figcaption style="margin-top: 0;">These photos are from the case's Ebay listing. It did, in fact, ship with all that stuff, including the IDE cable.</figcaption>
+ </div>
+ </figure>
+ <p>The "586" in this machine's name is derived from the Pentium sticker on the front of the case.</p>
+ <h2>Drives</h2>
+ <h3>Boot Drive - Samsung 870 EVO 250GB (2x) (Mirrored)</h3>
+ <p>I run two boot disks in a mirrored array for increased reliability. It's not strictly necessary, but it's one more thing I can rule out if the thing ever fails to boot.</p>
+ <p>I bought these drives for the original laptop server build, but they didn't make the cut after I hit some weird laptop-BIOS-ass limitations on my SATA connectivity.</p>
+ <h3>Apps Storage - Crucial BX500 1TB + WD Blue 1TB (Mirrored)</h3>
+ <p>I like my redundancy, especially since both of these drives are technically used. The BX500 was used for the same purpose in the old server, and the WD Blue was originally a storage upgrade for that laptop when it was still my daily driver, before being transplanted into my shiny new desktop rig, before then being replaced for peace of mind when my PSU a-sploded.</p>
+ <p>These are the drives I install programs to and such-like. There's no reason I couldn't use the giant HDD pool for this, but the performance hit just wouldn't be worth the savings, especially since I only had to buy one of these drives for home-server purposes anyway.</p>
+ <h3>Game Server Storage - Samsung OEM 256GB NVMe</h3>
+ <p>Not redundant, unfortunately, since I only had one of these laying around and there was only one remaining drive slot in the system when I decided to add it. This is the original boot drive from the old laptop, meaning it's over four years old, so it arguably needs redundancy the most, but frequent automated backups should mitigate that issue.</p>
+ <p>I install my game server(s) to this drive for maximum performance. By now the pattern must have emerged that I'm going all out on speed for anything that's going to affect that in particular. Only the best for the half a dozen or so friends who are gonna ever actually play on this thing. I think we've all dealt with enough poorly-performing shit-tier Minecraft servers in our time.</p>
+ <h3>Bulk Storage - Seagate Exos 16TB 7200RPM (x4) (RAIDZ1)</h3>
+ <p>A patently insane amount of storage. Even configured such that one of them is used up entirely on redundancy, that's still well north of 40TB of usable space. It's enough for my entire life, and that's the idea. These drives hold automated backups of all my other devices, my entire library of Legally Obtained media, and a good amount of other stuff, too. The NAS is to minimize the chances I ever lose any of it, and the massive HDD array is to minimize the chances I have to delete any myself.</p>
+ <p>I absolutely could not afford drives like this new &mdash; I got these drives Manufacturer Recertified&trade; from <a href="https://serverpartdeals.com/">serverpartdeals.com</a>. This makes them ever-so-slightly less trustworthy than new drives, but that's what the RAID is for, and the recertified ones are <em>half</em> the price of brand new. I chose the specific drives I did because they were the best available in terms of cost-per-terabyte at the time I bought them.</p>
+ <h2>Software</h2>
+ <h3>OS - <a href="https://www.truenas.com/">TrueNAS Scale</a></h3>
+ <p>I could probably recreate my elaborate configuration on like, baseline debian or something, but I don't want to. Between four ZFS pools, virtual machines, a slightly convoluted system of SMB shares, and various other services, the slick web GUI TrueNAS provides makes everything far more convenient. Its configuration export feature was also very handy when migrating to the new machine.</p>
+ <p>It's got some idiosyncracies to it, but in general TrueNAS smooths out the experience of running this server enough that I'm doing a lot of things I probably couldn't be bothered to otherwise.</p>
+ <h3><a href="https://jellyfin.org/">Jellyfin</a></h3>
+ <p>Let's be real, this is what home servers are for. This is why you get one, to make watching your, uh, totally legally obtained movies on your phone more convenient. Jellyfin does a great job of this. It fetches metadata reliably and plays nice with my GPU for transcoding. I also use it to host my music library, now that the Finamp beta lets you transcode your downloads to OPUS.</p>
+ <h3><a href="https://gethomepage.dev/">Homepage</a></h3>
+ <p>I mostly keep this around because there's no way to point your Firefox new tab page to a local file on your computer, but it's got some nice features. Namely, it can display stats from your various services.</p>
+ <h3><a href="https://syncthing.net/">Syncthing</a></h3>
+ <p>I fucking love Syncthing. I've got all my favourite files from my PC and my phone backing up to my server, automatically and with zero effort. If I could only run one thing on my server, it'd be this.</p>
+ <h3><a href="https://filebrowser.org/">Filebrowser</a></h3>
+ <p>A Google Drive-style web file browser for my network shares. I can access them over SMB, of course, but this provides the same functionality with a lot less friction for devices and people that aren't super compatible with that level of nerd shit.</p>
+ <h3>OS - <a href="https://www.debian.org/">Debian Linux</a></h3>
+ <p>Wait, what? Didn't I just say I was running TrueNAS? I am, but I also have a virtual machine under TrueNAS for my game servers, and this is the OS I use for that. There's a learning curve here compared to Ubuntu Server, which I'm more used to, but at the end of the day Linux is Linux.</p>
+ <h3><a href="https://craftycontrol.com/">Crafty Controller</a></h3>
+ <p>A convenient admin panel for my Minecraft servers. Getting my old server imported was an Experience, but after that it's been smooth. Highly recommend. I especially like the automated backup system.</p>
+ <h3><a href="https://www.wireguard.com/">WireGuard</a></h3>
+ <p>I run a WireGuard client in the VM with a server on my VPS to make my game servers accessible from outside the <span class="house">house</span> without giving out my IP address, worrying about dynamic DNS, or trying to port forward on the solid lump of concentrated ISP malice that passes for my router. I had to write a couple configuration files by hand, god forbid, but otherwise this was much easier.</p>
+ </body>
+</html>
diff --git a/uses/servy586/nictua.jpg b/uses/servy586/nictua.jpg
new file mode 100644
index 0000000..c692bf8
--- /dev/null
+++ b/uses/servy586/nictua.jpg
Binary files differ
diff --git a/uses/servy586/servercase.jpg b/uses/servy586/servercase.jpg
new file mode 100644
index 0000000..bbd1006
--- /dev/null
+++ b/uses/servy586/servercase.jpg
Binary files differ
diff --git a/uses/servy586/servercaseinside.jpg b/uses/servy586/servercaseinside.jpg
new file mode 100644
index 0000000..038f65d
--- /dev/null
+++ b/uses/servy586/servercaseinside.jpg
Binary files differ
diff --git a/uses/servy586/ziptiemount.jpg b/uses/servy586/ziptiemount.jpg
new file mode 100644
index 0000000..ea00cb1
--- /dev/null
+++ b/uses/servy586/ziptiemount.jpg
Binary files differ
diff --git a/wimpod.js b/wimpod.js
new file mode 100644
index 0000000..a0af339
--- /dev/null
+++ b/wimpod.js
@@ -0,0 +1,198 @@
+// Pokéneko v0.3 by https://james.nekoweb.org/
+// https://jamesschoch.github.io/Pokeneko/
+
+// Pokéneko is built using sprites from PDMCollab's Sprite Repository.
+// https://sprites.pmdcollab.org
+
+// This snippet uses sprites from https://sprites.pmdcollab.org/#/0767
+
+var pokemon = {"pokedex":"0767","shiny":false,"animData":{"Walk":{"$":{},"Name":"Walk","Index":"0","FrameWidth":"40","FrameHeight":"32","Durations":{"$":{},"Duration":["8","8","8","8"]},"animURL":"https://jamesschoch.github.io/Pokeneko/sprite/0767/Walk-Anim.png"},"Idle":{"$":{},"Name":"Idle","Index":"7","FrameWidth":"40","FrameHeight":"32","Durations":{"$":{},"Duration":["8","14","8","40"]},"animURL":"https://jamesschoch.github.io/Pokeneko/sprite/0767/Idle-Anim.png"}}};
+var trackerjson;
+ pokemon.state = "none";
+ var walkAnimInterval, idleAnimInterval;
+ var dirlisting;
+ var distancePx = 0;
+ var CurrentMouseXPostion;
+ var CurrentMouseYPostion;
+ var scale = 2;
+ var rotation = 0;
+ var rotations = 8;
+ var state;
+ var laststate;
+ var frameCounter;
+ var animPlaying = false;
+ var mouseIdleTime = 0;
+ var anglevar;
+
+ var sprite = document.createElement("div");
+ sprite.id = "sprite";
+ sprite.style.position = "fixed";
+ sprite.style.zIndex = "1000000";
+ sprite.style.width = "64px";
+ sprite.style.height = "64px";
+ sprite.style.pointerEvents = "none";
+ sprite.style.top = "50%";
+ sprite.style.left = "50%";
+
+ document.body.appendChild(sprite);
+
+ function getOffset(element) {
+ if (!element.getClientRects().length) {
+ return { top: 0, left: 0 };
+ }
+
+ var rect = element.getBoundingClientRect();
+ var win = element.ownerDocument.defaultView;
+ return (
+ {
+ top: rect.top + win.pageYOffset,
+ left: rect.left + win.pageXOffset
+ });
+ }
+
+ function timerIncrement() {
+ mouseIdleTime = mouseIdleTime + 1;
+ }
+
+ function updateDistanceRotation() {
+ var spriteX = getOffset(document.getElementById("sprite")).left + 32;
+ var spriteY = getOffset(document.getElementById("sprite")).top + 32;
+ distancePx = distance(spriteX, spriteY, CurrentMouseXPostion, CurrentMouseYPostion);
+ anglevar = angle360(spriteX, spriteY, CurrentMouseXPostion, CurrentMouseYPostion);
+ if (anglevar > 67.5 && anglevar < 112.5) {
+ rotation = 0;
+ } else if (anglevar > 22.5 && anglevar < 67.5) {
+ rotation = 1;
+ } else if (anglevar > 337.5 || anglevar < 22.5) {
+ rotation = 2;
+ } else if (anglevar > 292.5 && anglevar < 337.5) {
+ rotation = 3;
+ } else if (anglevar > 247.5 && anglevar < 292.5) {
+ rotation = 4;
+ } else if (anglevar > 202.5 && anglevar < 247.5) {
+ rotation = 5;
+ } else if (anglevar > 157.5 && anglevar < 202.5) {
+ rotation = 6;
+ } else if (anglevar > 112.5 && anglevar < 157.5) {
+ rotation = 7;
+ }
+ }
+
+ function addEvent(elm, evType, fn, useCapture) {
+ if (elm.addEventListener) {
+ elm.addEventListener(evType, fn, useCapture);
+ return true;
+ }
+ else if (elm.attachEvent) {
+ var r = elm.attachEvent('on' + evType, fn);
+ return r;
+ }
+ else {
+ elm['on' + evType] = fn;
+ }
+ }
+
+ document.onmousemove = function (event) {
+ CurrentMouseXPostion = event.pageX;
+ CurrentMouseYPostion = event.pageY;
+ updateDistanceRotation();
+ mouseIdleTime = 0;
+ }
+
+ function angle(cx, cy, ex, ey) {
+ var dy = ey - cy;
+ var dx = ex - cx;
+ var theta = Math.atan2(dy, dx);
+ theta *= 180 / Math.PI;
+
+ return theta;
+ }
+
+ function distance(cx, cy, ex, ey) {
+ var dx = cx - ex;
+ var dy = cy - ey;
+ return Math.sqrt(dx * dx + dy * dy);
+ }
+
+ function angle360(cx, cy, ex, ey) {
+ var theta = angle(cx, cy, ex, ey);
+ if (theta < 0) theta = 360 + theta;
+ return theta;
+ }
+
+ function setSprite(animName, frame) {
+ var animData = pokemon.animData[animName];
+ var sprite = document.getElementById("sprite");
+ if (animName !== "Sleep") {
+ var rotations = 8;
+ } else {
+ var rotations = 1;
+ }
+ sprite.style.backgroundImage = "url(" + animData.animURL + ")";
+ sprite.style.backgroundSize = (animData.FrameWidth * scale * animData.Durations.Duration.length) + "px " + (animData.FrameHeight * scale * rotations) + "px";
+ sprite.style.width = animData.FrameWidth * scale + "px";
+ sprite.style.height = animData.FrameHeight * scale + "px";
+ sprite.style.backgroundPosition = (0 - ((animData.FrameWidth * (frame % animData.Durations.Duration.length)) * scale)) + "px " + (0 - ((rotation * animData.FrameHeight) * scale)) + "px";
+ sprite.style.imageRendering = "pixelated";
+
+ }
+
+ var runningAnim;
+ var runningAnimName = "";
+
+ function runAnim(animName) {
+ if (pokemon.pokedex) {
+ if (runningAnimName === animName) {
+ return;
+ } else {
+ clearInterval(runningAnim);
+ var frames = [];
+ for (var i = 0; i < pokemon.animData[animName].Durations.Duration.length; i++) {
+ for (var j = 0; j < pokemon.animData[animName].Durations.Duration[i]; j++) {
+ frames.push(i);
+ }
+ }
+
+ runningAnimName = animName;
+ var i = 0;
+ runningAnim = setInterval(function () {
+ setSprite(animName, frames[i]);
+ i++;
+ if (i == frames.length) {
+ setSprite(animName, frames[i]);
+ i = 0;
+ }
+ }, 33);
+ }
+ }
+ }
+
+ var moveSprite = setInterval(function () {
+
+ if (pokemon.pokedex) {
+ if (distancePx >= 55) {
+ state = "Walk";
+ runAnim("Walk");
+
+ } else {
+ state = "Idle";
+ runAnim("Idle");
+ }
+ if (state == "Walk") {
+
+ var sprite = document.getElementById("sprite");
+ var spriteX = getOffset(document.getElementById("sprite")).left;
+ var spriteY = getOffset(document.getElementById("sprite")).top;
+
+ var angle = angle360(spriteX, spriteY, CurrentMouseXPostion, CurrentMouseYPostion);
+ var dx = Math.cos(angle * Math.PI / 180) * 4;
+ var dy = Math.sin(angle * Math.PI / 180) * 4;
+ sprite.style.left = spriteX + dx + "px";
+ sprite.style.top = spriteY + dy + "px";
+
+ }
+ updateDistanceRotation();
+
+ laststate = state;
+ }
+ }, 33); \ No newline at end of file