on master help sign in
578 files changed+13131−2863
since splitsnapshots
unifiedsplit
.nova/Configuration.json−3 components/BasicPage.js+1−1 components/ContentArea.js+1−1 components/CopyLink.js+1−1 components/DocsSidebar.js+2−2 components/EventPreview.js+3−4 components/GrantPreview.js+2−1 components/GrantProgramOverview.js+1−1 components/Header.js+7−5 components/HighlightCard.js+22 components/JoinGroup.js+2−2 components/MenuTray.js−108 components/Meta.js+21−2 components/Search.js−405 components/Sidebar.js+1−1 components/Sigil.js−36 components/ecosystem/Badge.js+20 components/ecosystem/BasicPage.js+47−9 components/ecosystem/EcosystemSidebar.js+86 components/ecosystem/IndexCard.js+13−29 components/ecosystem/MetadataBlock.js+7 components/ecosystem/Post.js+33−22 components/ecosystem/SpotlightArchive.js+66 components/gateway/Description.js−1 components/gateway/Image.js+5−6 components/gateway/ResourceCard.js+14−3 content/applications/~bacwyl-samweg/templeochess.md+22 content/applications/~datder-sonnet/hodl.md+16 content/applications/~disreb-winner-mittec/urbit-go.md+12 content/applications/~dister-dister-datryn-ribdun/campfire.md+12 content/applications/~dister-dister-sidnym-ladrut/quorum.md+17 content/applications/~dister-dozzod-bacdun/uqbar-suite.md+20 content/applications/~dister-dozzod-dalten/books.md+20 content/applications/~dalten/gora.md → content/applications/~dister-dozzod-dalten/gora.md+1 content/applications/~dister-dozzod-dalten/keep.md+13 content/applications/~magped-magped-rabsef-bicrym/orca.md → content/applications/~dister-dozzod-dalten/orca.md+5−3 content/applications/~dister-dozzod-dalten/peat.md+36 content/applications/~magped-magped-rabsef-bicrym/wrdu.md → content/applications/~dister-dozzod-dalten/wrdu.md+3−3 content/applications/~donpub-datdux/forms.md+14 content/applications/~fabnev-hinmur/escape.md+3−5 content/applications/~fabnev-hinmur/handshake.md+1−1 content/applications/~finmep-lanteb/chess.md+5−3 content/applications/~hanfel-dovned/board.md+14 content/applications/~hanfel-dovned/pony.md+12 content/applications/~hanfel-dovned/slam.md+1 content/applications/~hanrut-sillet-dachus-tiprel/blog.md+16 content/applications/~lander-dister-dozzod-dozzod/groups.md−31 content/applications/~larryx-woldyr/osmosis.md+12 content/applications/~larryx-woldyr/safe.md+12 content/applications/~larryx-woldyr/uniswap.md+12 content/applications/~larryx-woldyr/urbhue.md+18 content/applications/~lomder-librun/realm.md+18 content/applications/~migmeg-fidlen-sillus-mallus/kenning.md+17 content/applications/~niblyx-malnus/gol-cli.md+15 content/applications/~nocsyx-lassul/sphinx.md+1 content/applications/~nodmyn-dosrux/basket.md+34 content/applications/~nodmyn-dosrux/houston.md+1−1 content/applications/~nodmyn-dosrux/radio.md+15 content/applications/~nodmyn-dosrux/vita.md+20 content/applications/~paldev/scooore.md+14 content/applications/~pocwet/straw.md+13 content/applications/~sogryp-dister-dozzod-dozzod/groups.md+40 content/applications/~sogryp-dister-dozzod-dozzod/talk.md+21 content/applications/~sortug/gate.md+27 content/applications/~sortug/trill.md+27 content/applications/~sortug/ufa.md+27 content/applications/~tiller-tolbus/membrane.md+14 content/applications/~tirrel/scene.md+14 content/applications/~tirrel/studio.md+1−1 content/applications/~worpet-bildet/portal.md+16 content/apprenticeships.md+14−15 content/articles/2022-09-24_urbit-courts-daos-crypto.md+10 content/articles/2022-09-24_urbit-is-web3-weird-and-wonderful.md+10 content/articles/2022-09-28_college-course-on-urbit.md+10 content/articles/2022-09-29_assembly-miami-dispatch.md+11 content/articles/2022-09-29_the-dream-of-digital-homesteading.md+10 content/articles/2022-10-04_a-more-beautiful-computer.md+11 content/articles/2022-10-13_my-weekend-with-the-martians.md+10 content/articles/2022-10-23_three-things.md+10 content/articles/2023-02-20_trailblazing-urbit-startup-makes-earth-shaking-acquisition.md+10 content/articles/2023-05-10_urbit-a-network-older-and-weirder-than-bitcoin.md+10 content/bitcoin.md+125 content/blog/aesthetic-culture-1.md+1−1 content/blog/agency-daos.md+110 content/blog/ares.md+51 content/blog/august-2022-grants-program.md+73 content/blog/foss-1.md+64 content/blog/foss-2.md+59 content/blog/hoon-4-lispers.md+764 content/blog/interplanetary_commerce.md+2−1 content/blog/io-in-hoon.md+2−2 content/blog/pin-the-face-that-launches-a-thousand-ships.md+146 content/blog/urbit-and-bitcoin.md+1−1 content/blog/urbit-creator-daos.md+74 content/blog/using-urbit-in-2023.md+55 content/bounties.md+18−12 content/campus/_index.md+37 content/campus/blockchain-enthusiasts.md+35 content/campus/creatives.md+21 content/communities/urbit-austin.md+11 content/communities/urbit-berlin.md+16 content/communities/urbit-christchurch.md+13 content/communities/urbit-cph.md+11 content/communities/urbit-dc.md+19 content/communities/urbit-denver.md+19 content/communities/urbit-london.md+15 content/communities/urbit-mst.md+13 content/communities/urbit-ny.md+11 content/communities/urbit-paris.md+23 content/communities/urbit-seattle.md+14 content/communities/urbit-sf.md+15 content/community/_index.md−5 content/community/community-grants.md−14 content/community/governance.md−25 content/community/hosting-a-meetup.md−82 content/community/meetups.md−47 content/ecosystem/spotlight/july-2022.md → content/ecosystem/spotlight/2022-august.md+1−1 content/ecosystem/spotlight/2022-december.md+40 content/ecosystem/spotlight/2022-november.md+42 content/ecosystem/spotlight/2022-october.md+41 content/ecosystem/spotlight/2022-september.md+45 content/ecosystem/spotlight/2023-february.md+48 content/ecosystem/spotlight/2023-june.md+40 content/ecosystem/spotlight/2023-may.md+50 content/events/2021-04-27-bitcoin-launch.md+2−1 content/events/2022-09-15-developer-call-IoT.md+27 content/events/2022-09-22-assembly.md+2−4 content/events/2022-10-13-devcon-bogotá-urbit-meetup-22.md+36 content/events/2022-11-01-developer-week.md+75 content/events/2022-11-19-urbit-irl.md+18 content/events/2022-19-10-developer-call-herd-dependency.md+25 content/events/2023-01-28-urbit-meetup-christchurch.md+21 content/events/2023-01-31-urbit-meetup-krakow.md+26 content/events/2023-02-23-urbit-meetup-berlin.md+27 content/events/2023-03-05-meetup-el-salvador.md+24 content/events/2023-03-25-urbit-meetup-christchurch.md+21 content/events/2023-04-18-urbit-lisbon.md+19 content/events/2023-04-27-urbit-meetup-berlin.md+27 content/events/2023-04-27_urbit-austin-meetup-consensus.md+16 content/events/2023-05-10_urbit-meetup-berlin.md+25 content/events/2023-05-14_urbit-meetup-london.md+23 content/events/2023-05-18_urbit-denver-meetup.md+19 content/events/2023-05-18_urbit-miami-meetup.md+20 content/events/2023-05-27_urbit-meetup-london.md+21 content/events/2023-05-27_urbit-meetup-mst.md+20 content/events/2023-06-03-urbit-meetup-christchurch.md+24 content/events/2023-06-08_urbit-meetup-berlin.md+25 content/events/2023-06-08_urbit-meetup-prague.md+39 content/events/2023-06-12-developer-week.md+95 content/events/2023-06-15_urbit-denver-meetup.md+19 content/events/2023-06-24-urbit-meetup-christchurch.md+24 content/events/2023-06-29-Urbit-Paris-Meetup-1.md+30 content/events/2023-07-01_urbit-meetup-mst.md+23 content/events/2023-07-20-Urbit-Paris-Meetup-ethcc.md+53 content/events/2023-08-16_reassembly.md+22 content/events/2023-10-28_urbit-assembly-lisboa.md+24 content/faq.md+1−1 content/getting-started/_index.md+19−16 content/getting-started/cli.md+116−57 content/getting-started/cloud-hosting.md+468 content/getting-started/desktop.md+5−70 content/getting-started/get-planet.md → content/getting-started/get-id.md+29−40 content/getting-started/getting-around.md+24−48 content/getting-started/home-servers.md+27 content/getting-started/hosted.md+19−12 content/getting-started/hosting-providers.md+24 content/getting-started/installing-applications.md+17−19 content/getting-started/interfaces.md+10 content/getting-started/joining-groups.md+24−28 content/getting-started/self-host.md+33 content/grants/bitcoin-node-json-rpc-api-part-1.md → content/grants/2019/bitcoin-node-json-rpc-api-part-1.md+2−1 content/grants/bitcoin-node-json-rpc-api-part-2.md → content/grants/2019/bitcoin-node-json-rpc-api-part-2.md+2−1 content/grants/bitcoin-node-json-rpc-api-part-3.md → content/grants/2019/bitcoin-node-json-rpc-api-part-3.md+2−1 content/grants/bitcoin-node-json-rpc-api-part-4.md → content/grants/2019/bitcoin-node-json-rpc-api-part-4.md+2−1 content/grants/bitcoin-wallet-on-bridge.md → content/grants/2019/bitcoin-wallet-on-bridge.md+2−1 content/grants/escape.md → content/grants/2019/escape.md content/grants/gall-api-documentation.md → content/grants/2019/gall-api-documentation.md content/grants/host-two-urbit-meetups-1.md → content/grants/2019/host-two-urbit-meetups-1.md+1−1 content/grants/host-two-urbit-meetups-10.md → content/grants/2019/host-two-urbit-meetups-10.md content/grants/host-two-urbit-meetups-2.md → content/grants/2019/host-two-urbit-meetups-2.md+1−1 content/grants/host-two-urbit-meetups-3.md → content/grants/2019/host-two-urbit-meetups-3.md content/grants/host-two-urbit-meetups-4.md → content/grants/2019/host-two-urbit-meetups-4.md content/grants/host-two-urbit-meetups-5.md → content/grants/2019/host-two-urbit-meetups-5.md content/grants/host-two-urbit-meetups-6.md → content/grants/2019/host-two-urbit-meetups-6.md content/grants/host-two-urbit-meetups-7.md → content/grants/2019/host-two-urbit-meetups-7.md content/grants/host-two-urbit-meetups-8.md → content/grants/2019/host-two-urbit-meetups-8.md content/grants/host-two-urbit-meetups-9.md → content/grants/2019/host-two-urbit-meetups-9.md content/grants/ragnarok-online-on-urbit.md → content/grants/2019/ragnarok-online-on-urbit.md content/grants/udon-syntax-highlighter.md → content/grants/2019/udon-syntax-highlighter.md content/grants/unit-tests-for-json-parsing.md → content/grants/2019/unit-tests-for-json-parsing.md content/grants/unit-tests-for-pure-algorithms.md → content/grants/2019/unit-tests-for-pure-algorithms.md content/grants/unit-tests-for-sha-functions.md → content/grants/2019/unit-tests-for-sha-functions.md content/grants/unit-tests-for-zuse-cryptographic-functions.md → content/grants/2019/unit-tests-for-zuse-cryptographic-functions.md+1−1 content/grants/a-book-about-urbit.md → content/grants/2020/a-book-about-urbit.md content/grants/a-network-enabled-spatial-database-and-demonstration-app.md → content/grants/2020/a-network-enabled-spatial-database-and-demonstration-app.md+2−2 content/grants/antechamber.md → content/grants/2020/antechamber.md content/grants/art-by-urbit.md → content/grants/2020/art-by-urbit.md content/grants/bart-train-tracker-landscape-tile.md → content/grants/2020/bart-train-tracker-landscape-tile.md content/grants/bitcoin-full-node-provider-and-wallet.md → content/grants/2020/bitcoin-full-node-provider-and-wallet.md+2−1 content/grants/bitcoin-key-derivation.md → content/grants/2020/bitcoin-key-derivation.md+2−1 content/grants/boston-t-train-tracker-landscape-tile.md → content/grants/2020/boston-t-train-tracker-landscape-tile.md content/grants/calendar-ui.md → content/grants/2020/calendar-ui.md content/grants/calendar.md → content/grants/2020/calendar.md content/grants/content-saver.md → content/grants/2020/content-saver.md content/grants/cta-train-tracker-landscape-tile.md → content/grants/2020/cta-train-tracker-landscape-tile.md content/grants/display-eth-data.md → content/grants/2020/display-eth-data.md content/grants/docker-image-for-cloud-container-orchestration.md → content/grants/2020/docker-image-for-cloud-container-orchestration.md content/grants/ethereum-abi-parser.md → content/grants/2020/ethereum-abi-parser.md content/grants/go-airlock-library.md → content/grants/2020/go-airlock-library.md content/grants/haskell-airlock-library.md → content/grants/2020/haskell-airlock-library.md content/grants/hoon-001-learner-efficiency-and-early-learner-resources.md → content/grants/2020/hoon-001-learner-efficiency-and-early-learner-resources.md content/grants/host-three-college-university-urbit-meetups-1.md → content/grants/2020/host-three-college-university-urbit-meetups-1.md content/grants/host-three-college-university-urbit-meetups-2.md → content/grants/2020/host-three-college-university-urbit-meetups-2.md content/grants/host-three-college-university-urbit-meetups-3.md → content/grants/2020/host-three-college-university-urbit-meetups-3.md content/grants/host-three-virtual-urbit-meetups.md → content/grants/2020/host-three-virtual-urbit-meetups.md content/grants/links-in-urbit-reference-docs.md → content/grants/2020/links-in-urbit-reference-docs.md+1−1 content/grants/llelogram.md → content/grants/2020/llelogram.md content/grants/matrices-in-hoon.md → content/grants/2020/matrices-in-hoon.md+1−1 content/grants/matrixriotim-bridge-bot.md → content/grants/2020/matrixriotim-bridge-bot.md+1−1 content/grants/open-street-maps-data-importation.md → content/grants/2020/open-street-maps-data-importation.md content/grants/staff-the-urbit-help-desk-1.md → content/grants/2020/staff-the-urbit-help-desk-1.md content/grants/staff-the-urbit-help-desk-2.md → content/grants/2020/staff-the-urbit-help-desk-2.md+1−1 content/grants/staff-the-urbit-helpdesk-west.md → content/grants/2020/staff-the-urbit-helpdesk-west.md content/grants/the-complete-guide-to-gall-and-landscape.md → content/grants/2020/the-complete-guide-to-gall-and-landscape.md content/grants/tor-nodes-relay-search-tile.md → content/grants/2020/tor-nodes-relay-search-tile.md+1−1 content/grants/typescript-airlock-library.md → content/grants/2020/typescript-airlock-library.md content/grants/up-to-date-hoon-reference-card.md → content/grants/2020/up-to-date-hoon-reference-card.md+1−1 content/grants/urbian-a-customized-linux-distribution-for-urbit-appliances.md → content/grants/2020/urbian-a-customized-linux-distribution-for-urbit-appliances.md content/grants/urbit-event-series.md → content/grants/2020/urbit-event-series.md content/grants/urbit-explainer-video.md → content/grants/2020/urbit-explainer-video.md content/grants/urbit-http-api-for-kotlin.md → content/grants/2020/urbit-http-api-for-kotlin.md+1−1 content/grants/urbit-http-api-for-rust.md → content/grants/2020/urbit-http-api-for-rust.md content/grants/urbit-http-interface-java-edition.md → content/grants/2020/urbit-http-interface-java-edition.md content/grants/urbit-http-library-for-ruby.md → content/grants/2020/urbit-http-library-for-ruby.md content/grants/urbit-online-meetup.md → content/grants/2020/urbit-online-meetup.md content/grants/urbit-ship-and-star-hosting-and-troubleshooting-docs.md → content/grants/2020/urbit-ship-and-star-hosting-and-troubleshooting-docs.md content/grants/verifying-urbit-id-on-keybase.md → content/grants/2020/verifying-urbit-id-on-keybase.md content/grants/web-scraper.md → content/grants/2020/web-scraper.md+1−1 content/grants/analytics-script.md → content/grants/2021/analytics-script.md content/grants/authenticate-with-urbit.md → content/grants/2021/authenticate-with-urbit.md content/grants/azimuth-cli.md → content/grants/2021/azimuth-cli.md content/grants/bitcoin-wallet-maintenance.md → content/grants/2021/bitcoin-wallet-maintenance.md+3−1 content/grants/bridge-l2-revamp.md → content/grants/2021/bridge-l2-revamp.md content/grants/clojure-urbit-client.md → content/grants/2021/clojure-urbit-client.md+2−2 content/grants/comprehensive-local-server-and-mum-explanation-video.md → content/grants/2021/comprehensive-local-server-and-mum-explanation-video.md content/grants/contacts.md → content/grants/2021/contacts.md+1−1 content/grants/content-producer.md → content/grants/2021/content-producer.md content/grants/cross-platform-desktop-urbit-app.md → content/grants/2021/cross-platform-desktop-urbit-app.md content/grants/cypherscope-bot.md → content/grants/2021/cypherscope-bot.md+1−1 content/grants/educational-guide-todomvc-urbit-edition.md → content/grants/2021/educational-guide-todomvc-urbit-edition.md content/grants/feed-aggregator.md → content/grants/2021/feed-aggregator.md content/grants/graph-store-documentation-guide.md → content/grants/2021/graph-store-documentation-guide.md content/grants/guide-to-s3.md → content/grants/2021/guide-to-s3.md content/grants/host-two-urbit-meetups-11.md → content/grants/2021/host-two-urbit-meetups-11.md+1−1 content/grants/host-two-urbit-meetups-12.md → content/grants/2021/host-two-urbit-meetups-12.md content/grants/host-two-urbit-meetups-13.md → content/grants/2021/host-two-urbit-meetups-13.md content/grants/host-two-urbit-meetups-14.md → content/grants/2021/host-two-urbit-meetups-14.md content/grants/host-two-urbit-meetups-15.md → content/grants/2021/host-two-urbit-meetups-15.md content/grants/host-two-urbit-meetups-16.md → content/grants/2021/host-two-urbit-meetups-16.md content/grants/json-jet.md → content/grants/2021/json-jet.md+1−1 content/grants/login-with-urbit.md → content/grants/2021/login-with-urbit.md content/grants/machine-learning.md → content/grants/2021/machine-learning.md+1−1 content/grants/market-interface.md → content/grants/2021/market-interface.md content/grants/meetup-bom.md → content/grants/2021/meetup-bom.md content/grants/minimal-urbit-os.md → content/grants/2021/minimal-urbit-os.md content/grants/native-urbit.md → content/grants/2021/native-urbit.md content/grants/network-explorer-data-pipeline-http-api.md → content/grants/2021/network-explorer-data-pipeline-http-api.md content/grants/nuck-jet.md → content/grants/2021/nuck-jet.md+1−1 content/grants/overhaul-the-urbitorg-website.md → content/grants/2021/overhaul-the-urbitorg-website.md content/grants/planet-sales.md → content/grants/2021/planet-sales.md content/grants/pokur.md → content/grants/2021/pokur.md content/grants/ra-debugging-tools.md → content/grants/2021/ra-debugging-tools.md+4−4 content/grants/ra-page-tracking.md → content/grants/2021/ra-page-tracking.md+1−1 content/grants/ra-segfaults.md → content/grants/2021/ra-segfaults.md+1−1 content/grants/ra-stack-overflow.md → content/grants/2021/ra-stack-overflow.md+1−1 content/grants/search-in-groups.md → content/grants/2021/search-in-groups.md+1−1 content/grants/send-emails-to-a-mailing-list.md → content/grants/2021/send-emails-to-a-mailing-list.md content/grants/smol-future-sustained-knowledge-sharing-and-marketing.md → content/grants/2021/smol-future-sustained-knowledge-sharing-and-marketing.md content/grants/speech-recognition.md → content/grants/2021/speech-recognition.md content/grants/staff-the-urbit-helpdesk-east.md → content/grants/2021/staff-the-urbit-helpdesk-east.md content/grants/static-site-generation.md → content/grants/2021/static-site-generation.md content/grants/thread-documentation.md → content/grants/2021/thread-documentation.md content/grants/translate-key-parts-of-urbitorg-into-german.md → content/grants/2021/translate-key-parts-of-urbitorg-into-german.md content/grants/translate-key-parts-of-urbitorg-into-korean.md → content/grants/2021/translate-key-parts-of-urbitorg-into-korean.md content/grants/translate-key-parts-of-urbitorg-into-norwegian.md → content/grants/2021/translate-key-parts-of-urbitorg-into-norwegian.md content/grants/translate-key-parts-of-urbitorg-into-spanish.md → content/grants/2021/translate-key-parts-of-urbitorg-into-spanish.md+1−1 content/grants/try-urbit-website.md → content/grants/2021/try-urbit-website.md content/grants/twitter-uv-extension.md → content/grants/2021/twitter-uv-extension.md content/grants/ua-collaborative-text-editor.md → content/grants/2021/ua-collaborative-text-editor.md+1−1 content/grants/ua-filesharer.md → content/grants/2021/ua-filesharer.md+1−1 content/grants/ua-heads-up-poker.md → content/grants/2021/ua-heads-up-poker.md+1−1 content/grants/ua-invoice-system.md → content/grants/2021/ua-invoice-system.md+1−1 content/grants/ua-marketplace.md → content/grants/2021/ua-marketplace.md+1−1 content/grants/ucal-google-and-outlook-integration.md → content/grants/2021/ucal-google-and-outlook-integration.md content/grants/urbit-api-for-elixir.md → content/grants/2021/urbit-api-for-elixir.md+1−1 content/grants/urbit-community-concierge-east-coast-2q2021.md → content/grants/2021/urbit-community-concierge-east-coast-2q2021.md+1−1 content/grants/urbit-community-concierge-east-coast.md → content/grants/2021/urbit-community-concierge-east-coast.md+1−1 content/grants/urbit-community-concierge-west-coast-2q2021.md → content/grants/2021/urbit-community-concierge-west-coast-2q2021.md content/grants/urbit-community-concierge-west-coast.md → content/grants/2021/urbit-community-concierge-west-coast.md content/grants/urbit-http-api-for-emacs-elisp.md → content/grants/2021/urbit-http-api-for-emacs-elisp.md content/grants/urbit-http-api-for-python.md → content/grants/2021/urbit-http-api-for-python.md+2−2 content/grants/urbit-irc-bridge.md → content/grants/2021/urbit-irc-bridge.md content/grants/urbit-lfs-filehosting.md → content/grants/2021/urbit-lfs-filehosting.md+1−1 content/grants/urbit-notes.md → content/grants/2021/urbit-notes.md+2−2 content/grants/urbit-react-cookbook.md → content/grants/2021/urbit-react-cookbook.md content/grants/uturn.md → content/grants/2021/uturn.md+1−1 content/grants/uv-extension-library.md → content/grants/2021/uv-extension-library.md content/grants/video-content-manager.md → content/grants/2021/video-content-manager.md content/grants/volt-lightning-on-urbit.md → content/grants/2021/volt-lightning-on-urbit.md+2−1 content/grants/webrtc-gall-agent-and-external-app.md → content/grants/2021/webrtc-gall-agent-and-external-app.md content/grants/~home-urbit.md → content/grants/2021/~home-urbit.md+1 content/grants/abacus.md → content/grants/2022/abacus.md+2−2 content/grants/app-engram.md → content/grants/2022/app-engram.md+2−2 content/grants/app-openbsd.md → content/grants/2022/app-openbsd.md+2−2 content/grants/2022/app-store.md+159 content/grants/app-urvault.md → content/grants/2022/app-urvault.md+1−1 content/grants/app-uv-native-notificatons.md → content/grants/2022/app-uv-native-notificatons.md+2−2 content/grants/apprenticeship-extending-bitcoin.md → content/grants/2022/apprenticeship-extending-bitcoin.md+3−1 content/grants/apprenticeship-studio-collections.md → content/grants/2022/apprenticeship-studio-collections.md+2−2 content/grants/apprenticeship-studio-email.md → content/grants/2022/apprenticeship-studio-email.md+1−1 content/grants/astrolabe.md → content/grants/2022/astrolabe.md+4−3 content/grants/2022/books-development.md+44 content/grants/books.md → content/grants/2022/books.md+5−2 content/grants/2022/calendar-holium.md+53 content/grants/chess-bounty.md → content/grants/2022/chess-bounty.md+7−3 content/grants/chronicle.md → content/grants/2022/chronicle.md+3−3 content/grants/communal-computing.md → content/grants/2022/communal-computing.md+2−2 content/grants/cue.md → content/grants/2022/cue.md+2−2 content/grants/2022/desk-import-export.md+102 content/grants/digital-editor-MROB.md → content/grants/2022/digital-editor-MROB.md+4−4 content/grants/digital-storefront.md → content/grants/2022/digital-storefront.md+3−3 content/grants/dusko-valve.md → content/grants/2022/dusko-valve.md+1−1 content/grants/eth-provider.md → content/grants/2022/eth-provider.md+1−1 content/grants/eth-wallet.md → content/grants/2022/eth-wallet.md+4−3 content/grants/eyre-scry.md → content/grants/2022/eyre-scry.md+2−2 content/grants/faux.md → content/grants/2022/faux.md+3−2 content/grants/filesharer.md → content/grants/2022/filesharer.md+1 content/grants/full-stop.md → content/grants/2022/full-stop.md+1−1 content/grants/2022/gather.md+87 content/grants/general-web-permissions.md → content/grants/2022/general-web-permissions.md+1−1 content/grants/2022/gnosis-safe.md+56 content/grants/go-urbit.md → content/grants/2022/go-urbit.md+2−2 content/grants/2022/gora-apprentice.md+61 content/grants/herd.md → content/grants/2022/herd.md+2−2 content/grants/hoon-eval.md → content/grants/2022/hoon-eval.md+3−3 content/grants/hoon-markdown-library.md → content/grants/2022/hoon-markdown-library.md+1−1 content/grants/2022/http-server-driver.md+98 content/grants/2022/keep.md+119 content/grants/2022/knox.md+81 content/grants/lexicon.md → content/grants/2022/lexicon.md+2−2 content/grants/2022/lightning-development.md+201 content/grants/loom-pointer-compression.md → content/grants/2022/loom-pointer-compression.md+2−2 content/grants/meld-memory.md → content/grants/2022/meld-memory.md+2−2 content/grants/membrane.md → content/grants/2022/membrane.md+4−3 content/grants/2022/middleware-apprentice.md+55 content/grants/minesweeper.md → content/grants/2022/minesweeper.md+2−2 content/grants/native-planet-2.md → content/grants/2022/native-planet-2.md+2−2 content/grants/nested-goals.md → content/grants/2022/nested-goals.md+45−11 content/grants/notifications-protocol.md → content/grants/2022/notifications-protocol.md+3−3 content/grants/olif.md → content/grants/2022/olif.md+1−1 content/grants/peat.md → content/grants/2022/peat.md+3−2 content/grants/2022/persistent-memory.md+157 content/grants/2022/plug.md+165 content/grants/2022/pony-bounty.md+72 content/grants/port-maintenance.md → content/grants/2022/port-maintenance.md+2−2 content/grants/2022/port-to-hosting.md+56 content/grants/2022/profiling.md+74 content/grants/2022/qr-login.md+48 content/grants/quorum.md → content/grants/2022/quorum.md+2−2 content/grants/regex-library.md → content/grants/2022/regex-library.md+2−2 content/grants/seguro-phase-2.md → content/grants/2022/seguro-phase-2.md+3−3 content/grants/seguro-prototype.md → content/grants/2022/seguro-prototype.md+2−2 content/grants/2022/serving-the-people.md+101 content/grants/slam.md → content/grants/2022/slam.md+4−3 content/grants/slaw-scot-jets.md → content/grants/2022/slaw-scot-jets.md+2−2 content/grants/2022/smart-lightbulb-controller.md+104 content/grants/symmetric-routing.md → content/grants/2022/symmetric-routing.md+3−3 content/grants/2022/trail.md+168 content/grants/trill-ufa.md → content/grants/2022/trill-ufa.md+3−2 content/grants/trove.md → content/grants/2022/trove.md+11−7 content/grants/urbit-forms.md → content/grants/2022/urbit-forms.md+5−4 content/grants/2022/urbit-interface-framework.md+88 content/grants/urbitswap.md → content/grants/2022/urbitswap.md+4−2 content/grants/value-articles.md → content/grants/2022/value-articles.md+2−2 content/grants/volt-ui.md → content/grants/2022/volt-ui.md+3−1 content/grants/2022/whom.md+70 content/grants/2023/aera.md+50 content/grants/2023/app-metrics.md+74 content/grants/2023/blog-updates.md+64 content/grants/2023/bridge-grab-bag.md+35 content/grants/2023/community-meetups.md+37 content/grants/2023/did-rfp.md+26 content/grants/2023/elm.md+68 content/grants/2023/email-stella-fixa-rfp.md+29 content/grants/2023/eyre-noun-channels.md+42 content/grants/2023/generator-doccords.md+46 content/grants/2023/gh-concierge.md+42 content/grants/2023/git-on-clay.md+42 content/grants/2023/goals-2.md+64 content/grants/2023/hoon-linter.md+30 content/grants/2023/hoon-replit.md+45 content/grants/2023/issue-grab-bag.md+36 content/grants/2023/json-parser-suite.md+170 content/grants/2023/kNock-property-testing.md+71 content/grants/2023/lick.md+82 content/grants/2023/mapping-ids.md+106 content/grants/2023/network-weather.md+24 content/grants/2023/oauth2-stella-fixa-rfp.md+31 content/grants/2023/osmosis-client.md+48 content/grants/2023/pastebin-RFP.md+28 content/grants/2023/pastebin-proposal.md+33 content/grants/2023/portal-features-1.md+82 content/grants/2023/privacy-msg.md+89 content/grants/2023/quorum-2.md+84 content/grants/2023/replit.md+52 content/grants/2023/school-support-23q1.md+43 content/grants/2023/splitwise-rfp.md+26 content/grants/2023/splitwise.md+129 content/grants/2023/text-search.md+24 content/grants/2023/tinygrad.md+24 content/grants/2023/treesitter.md+71 content/grants/2023/turf.md+205 content/grants/2023/uc-concierge.md+42 content/grants/2023/update-mass.md+26 content/grants/2023/urbit-ninja-strike-team.md+38 content/grants/2023/urbit-react-docs.md+124 content/grants/2023/vere-eyre-cache.md+38 content/grants/2023/wiki-stella-fixa-rfp.md+26 content/grants/community-meetups.md−43 content/groups/~bitdeg/assembly22.md+10 content/groups/~dalten/aera.md+10 content/groups/~dibref-labter/arbit.md+9 content/groups/~dister-dozzod-lapdeg/battery-payload.md+9 content/groups/~halbex-palheb/uf-public.md+10 content/groups/~hocwyn-tipwex/uqbar-event-horizon-forever.md+11 content/groups/~martyr-sarlev-sarsen/assembly-hackers.md+10 content/groups/~mister-hilper-dozzod-dalten/quartus.md+10 content/groups/~nibset-napwyn/tlon-public.md+10 content/groups/~rondev/group-discovery.md−10 content/groups/~sillus-mallus/toki-pona.md+1 content/groups/~witbep-witbep/embark.md+11 content/groups/~wolref-podlex/foundation.md−10 content/highlights/highlight-1.md+6 content/highlights/highlight-2.md+6 content/highlights/highlight-3.md+6 content/ids/ballun-dilsup.md+7 content/ids/bintud-bitnev.md+8 content/ids/botbyn-dolrum.md+7 content/ids/datder-sonnet.md+13 content/ids/datnut-pollen.md+15 content/ids/datryn-ribdun.md+12 content/ids/datsyr-radser.md+12 content/ids/dopbet-larped.md+7 content/ids/finmep-lanteb.md+15−3 content/ids/haddef-sigwen.md+4−2 content/ids/hocmed-lidrev.md+8 content/ids/lagrev-nocfep.md+5−3 content/ids/monnys-riphet.md+7 content/ids/nallux-dozryl.md+12 content/ids/sarlev-sarsen.md+2−2 content/ids/tagdyl-ponwyn.md+10 content/ids/tambes-palped.md+10 content/ids/tobrun-tomnet.md+8 content/ids/topfet-parmed.md+6 content/organizations/assemblycapital.md+10 content/organizations/dalten.md+2−1 content/organizations/holium.md+3−2 content/organizations/labyrinthdao.md+10 content/organizations/mars-review-of-books.md+1 content/organizations/nativeplanet.md+10 content/organizations/quartus.md+4−3 content/organizations/sortug.md+1 content/organizations/third-earth.md+1 content/organizations/tirrel.md+1 content/organizations/tlon.md+2−1 content/organizations/uqbar.md+2−1 content/organizations/urbit-foundation.md+1 content/organizations/zorp.md+10 content/overview/people-history.md+36−31 content/overview/urbit-id.md+1−1 content/podcasts/2022-02-27_the-combine.md+13 content/podcasts/2022-03-04_nockin.md+18 content/podcasts/2022-03-11_mars-review.md+12 content/podcasts/2022-04-07_in-lehmans-terms.md+12 content/podcasts/2022-04-19_robot-opera.md+11 content/podcasts/2022-05-22_cincinnati-chili.md+10 content/podcasts/2022-06-04_market-bedshite.md+10 content/podcasts/2022-07-04_enable-people-to-run-their-own-servers.md+1−1 content/podcasts/2022-08-04_middling.md+10 content/podcasts/2022-08-11_probing-questions.md+14 content/podcasts/2022-08-19_the-blind.md+9 content/podcasts/2022-08-26_the-harvard-finance-bro.md+12 content/podcasts/2022-09-14_insanely-bullish-on-urbit.md+13 content/podcasts/2022-09-21_the-worlds-best-crypto-investor.md+12 content/podcasts/2022-09-30-neal-davis-urbit-sentience-daos.md+33 content/podcasts/2022-10-04-reality-maximalism-josh-lehman.md+9 content/podcasts/2022-10-06_urbit-maxi-episode copy.md+9 content/podcasts/2022-12-22_epicenter-ted-blackman-gary-lieberman.md+11 content/podcasts/2023-01-05_lets-get-personal.md+9 content/podcasts/2023-01-19_crypto-metaphysics.md+9 content/podcasts/2023-01-24_reject-triviality.md+13 content/podcasts/2023-01-26_building-future-states-with-nation3.md+9 content/podcasts/2023-01-29_urbit-for-idiots.md+11 content/podcasts/2023-02-09_crypto-narratives-new-and-old.md+9 content/podcasts/2023-02-13_distributed-networked-computing.md+17 content/podcasts/2023-02-23_the-urbit-episode.md+9 content/podcasts/2023-03-09_reclaiming-web-1.md+9 content/podcasts/2023-03-23_how-to-invest-in-web3-like-a-cool-kid.md+9 content/podcasts/2023-03-28_pupusas-volcanoes-and-databases.md+9 content/podcasts/2023-04-03_legacy-internet-new-internet.md+15 content/podcasts/2023-04-06_the-ai-episode.md+9 content/podcasts/2023-04-11_its-urbits-all-the-way-down-with-dachus-tiprel.md+9 content/podcasts/2023-04-14_epicenter-tim-galebach.md+11 content/podcasts/2023-04-20_artificial-qintelligence.md+9 content/podcasts/2023-04-27_hoon-only-legal-ui-with-hastuc-dibtux.md+11 content/podcasts/2023-05-11_full-metal-urbit-with-mopfel-winrux.md+15 content/podcasts/2023-05-18_crypto-takes-flight.md+11 content/privacy.md+1−1 content/proposals.md+21−41 content/rfps.md+40 content/updates/2018-7-30-update.md+1−1 content/updates/2019-2-11-update.md+1−1 gnosis-safe.md+1−1 lib/buildGlossary.js+59 lib/cache.js+14−7 lib/constants.js+15−6 lib/lib.js+134−60 package-lock.json+370−325 package.json+4−3 pages/404.js+1−1 pages/[slug].js+1−1 pages/_app.js+6−2 pages/api/dev-search.js+1−1 pages/api/glossary.js−10 pages/api/roadmap-search.js+8 pages/api/search.js+10−1 pages/api/urbit-org-search.js+45 pages/applications/[[...application]].js+16−5 pages/articles/[slug].js+84 pages/bitcoin.js+98 pages/blog.js+27−14 pages/blog/[slug].js+1−1 pages/campus/[[...slug]].js+312 pages/communities/[slug].js+87 pages/community/[[...slug]].js−121 pages/decentralized-discord.js+4−9 pages/ecosystem/index.js+215−237 pages/ecosystem/spotlight/[slug].js+3−53 pages/events.js+18−4 pages/events/[slug].js+1−1 pages/getinvolved.js+58 pages/getting-started/[[...slug]].js+181−183 pages/grants.js+88−67 pages/grants/[slug].js+168−64 pages/grants/apprenticeships.js+1−1 pages/grants/rfps.js+29 pages/groups/[[...group]].js+1−1 pages/ids/[id].js+1−1 pages/ids/submit.js+3−3 pages/index.js+142−132 pages/organizations/[slug].js+4−3 pages/overview/[[...slug]].js+1−1 pages/trial-over.js+35 pages/trial.js+129 pages/updates.js+1−1 pages/updates/[slug].js+1−1 public/images/android-chrome-192x192.png public/images/android-chrome-512x512.png public/images/apple-touch-icon.png public/images/developers-guide-logo.png public/images/favicon-16x16.png public/images/favicon-32x32.png public/images/favicon.ico public/images/network-explorer-logo.png public/images/operators-guide-logo.png public/images/star-market-logo.png tailwind.config.js+3−4 vercel.json+56−13
.nova/Configuration.jsondeleted−3
@@ -1,3 +0,0 @@
1−{
2− "workspace.name": "urbit.org"
3−}
components/BasicPage.js+1−1
@@ -27,7 +27,7 @@ export default function BasicPage({ post, markdown, search, index = false }) {
2727 </Head>
2828 <IntraNav ourSite="https://urbit.org" search={search} />
2929 <SingleColumn>
30− <Header />
30+ <Header search={search} />
3131 <Section>
3232 <h1>{post.title}</h1>
3333 </Section>
components/ContentArea.js+1−1
@@ -66,7 +66,7 @@ export default function ContentArea(props) {
6666 <div className="mb-16">
6767 <h2 className="mt-24">{props.title}</h2>
6868 {props?.description && (
69− <p className="text-wall-400 font-bold text-xl">
69+ <p className="text-wall-400 font-regular mt-2 text-xl">
7070 {props.description}
7171 </p>
7272 )}
components/CopyLink.js+1−1
@@ -53,7 +53,7 @@ export default function CopyLink({ content, className }) {
5353 onClick={() => copy()}
5454 >
5555 <p className="leading-5">
56− {copyStatus === "copied" ? "Copied" : "Copy Link"}
56+ {copyStatus === "copied" ? "Copied" : "Shortcode"}
5757 </p>
5858 {buttonIcon}
5959 </button>
components/DocsSidebar.js+2−2
@@ -1,6 +1,6 @@
11import Link from "next/link";
22import { useState } from "react";
3−import MenuTray from "./MenuTray";
3+import { MenuTray } from '@urbit/foundation-design-system'
44
55export default function Sidebar(props) {
66 const [isOpen, setTray] = useState(false);
@@ -9,7 +9,7 @@ export default function Sidebar(props) {
99 <div className="hidden md:flex flex-col w-96 bg-wall-100 max-h-screen h-screen">
1010 <header className="flex shrink-0 justify-between items-center pl-6 pt-12 mt-5 pb-8">
1111 <Link href="/" passHref>
12− <a className="type-ui text-wall-500">Urbit</a>
12+ <a className="font-semibold antialiased text-lg text-wall-500">Urbit</a>
1313 </Link>
1414 </header>
1515 <div className="overflow-y-auto p-6 pt-16">
components/EventPreview.js+3−4
@@ -41,11 +41,10 @@ export default function EventPreview({ event, className, big }) {
4141 )}
4242 >
4343 <div
44− className={`grow-1 flex ${
45− big ? "justify-center" : ""
46− } flex-col h-full`}
44+ className={`grow-1 flex ${big ? "justify-center" : ""
45+ } flex-col h-full`}
4746 >
48− <h3 className={`${blackText} mb-2`}>{event.title}</h3>
47+ <h3 className={`${blackText} mb-2`} id={event.title}>{event.title}</h3>
4948 <p className={blackText + " truncate text-sm"}>
5049 {event.description}
5150 </p>
components/GrantPreview.js+2−1
@@ -8,7 +8,7 @@ export default function GrantPreview({ grant }) {
88
99 const className = classnames({
1010 "bg-lightBlue": type.includes("Proposal") && isOpen,
11− "bg-green-200": type.includes("Apprenticeship") && isOpen,
11+ "bg-purple-200": type.includes("RFP") && isOpen,
1212 "bg-yellow-100": type.includes("Bounty") && isOpen,
1313 });
1414
@@ -38,6 +38,7 @@ export default function GrantPreview({ grant }) {
3838 {grant.taxonomies.grant_type.map((category) => {
3939 const className = classnames({
4040 "bg-blue-400 text-white": category === "Proposal",
41+ "bg-purple text-white": category === "RFP",
4142 "bg-green-400 text-white": category === "Apprenticeship",
4243 "bg-yellow-300": category === "Bounty",
4344 });
components/GrantProgramOverview.js+1−1
@@ -37,7 +37,7 @@ export default function GrantProgramOverview({
3737 </Head>
3838 <IntraNav ourSite="https://urbit.org" search={search} />
3939 <SingleColumn>
40− <Header />
40+ <Header search={search} />
4141 <Section narrow short>
4242 <h1>{post.title}</h1>
4343 <div className="type-ui text-wall-500 mt-4 md:mt-8 lg:mt-10">
components/Header.js+7−5
@@ -2,14 +2,13 @@ import Link from "next/link";
22import { useRouter } from "next/router";
33import { useState } from "react";
44import classnames from "classnames";
5−import MenuTray from "../components/MenuTray";
6−import { capitalize } from "@urbit/foundation-design-system";
5+import { capitalize, MenuTray } from "@urbit/foundation-design-system";
76
87function ActiveLink({ children, href, className, currentPath }) {
98 const firstCrumb = currentPath.split("/")[1];
109
1110 const activeClassName = classnames({
12− "text-wall-600": "/" + firstCrumb === href,
11+ "text-wall-900": "/" + firstCrumb === href,
1312 "text-wall-500": "/" + firstCrumb !== href,
1413 });
1514
@@ -49,7 +48,7 @@ export default function Header(props) {
4948 <nav className="items-center hidden md:flex">
5049 <ActiveLink
5150 currentPath={currentPath}
52− className="mr-5 text-green-400 type-ui button-text"
51+ className="mr-5 type-ui"
5352 href="/getting-started"
5453 >
5554 Get Started
@@ -110,7 +109,10 @@ export default function Header(props) {
110109 <a className="mt-2">Operators</a>
111110 </Link>
112111 <Link href="https://developers.urbit.org" passHref>
113− <a className="mt-2 mb-4">Developers</a>
112+ <a className="mt-2">Developers</a>
113+ </Link>
114+ <Link href="https://roadmap.urbit.org" passHref>
115+ <a className="mt-2 mb-4">Roadmap</a>
114116 </Link>
115117 <hr className="border-wall-200" />
116118
components/HighlightCard.jsnew file+22
@@ -0,0 +1,22 @@
1+import Link from "next/link";
2+export default function HighlightCard({ slug, highlight }) {
3+ return (
4+ <Link href={highlight.url}>
5+ <div className="cursor-pointer bg-wall-100 rounded-xl min-h-0 flex-1">
6+ <div className="flex flex-col p-4 h-full relative">
7+ {highlight.image ? (
8+ <div className="w-64 md:w-full rounded-xl object-cover overflow-hidden basis-3/5">
9+ <img className="h-full w-64 md:w-full object-cover" src={highlight.image} />
10+ </div>
11+ ) : (
12+ <div className="rounded-xl w-full"/>
13+ )}
14+ <div className="pt-4">
15+ <p className="mb-2 font-semibold leading-5">{highlight.title}</p>
16+ <p className="text-sm leading-5">{highlight?.description}</p>
17+ </div>
18+ </div>
19+ </div>
20+ </Link>
21+ );
22+}
components/JoinGroup.js+2−2
@@ -58,9 +58,9 @@ export default function Contact({ emphasize, groupName, label, className }) {
5858
5959 return (
6060 <div className={className}>
61− <h4 className="mt-4 text-wall-500 flex items-baseline flex-wrap">
61+ <h4 className="text-wall-500 flex items-baseline flex-wrap">
6262 {label ? label + " " : ""}
63− <div className="md:ml-2 rounded-lg flex items-stretch">
63+ <div className="rounded-lg flex items-stretch">
6464 <code
6565 className={`rounded-l-lg px-2 md:px-4 py-2 ${washedBg} flex items-center h-full ${linkText}`}
6666 >
components/MenuTray.jsdeleted−108
@@ -1,108 +0,0 @@
1−import classnames from "classnames";
2−import { useSwipeable } from "react-swipeable";
3−
4−export default function MenuTray({ isOpen, setTray, search, children }) {
5− // Locks document scrolling when menu is open
6− if (typeof document !== "undefined") {
7− if (isOpen) {
8− document.body.style.overflow = "hidden";
9− } else {
10− document.body.style.overflow = "visible";
11− }
12− }
13−
14− const handlers = useSwipeable({
15− onSwipedLeft: (e) => setTray(false),
16− });
17−
18− // Slides the tray in or out from the left
19− const trayClasses = classnames({
20− "tray-menu-open": isOpen,
21− "tray-menu-closed": !isOpen,
22− });
23−
24− // Fades the background overlay in or out
25− const overlayClasses = classnames({
26− "tray-overlay-open": isOpen,
27− "tray-overlay-closed": !isOpen,
28− });
29−
30− // Hides or shows the menu
31− const menuClasses = classnames({
32− "menu-open": isOpen,
33− "menu-closed": !isOpen,
34− });
35−
36− return (
37− <>
38− <nav
39− {...handlers}
40− className={`z-20 w-screen h-screen top-0 left-0 fixed block md:hidden ${menuClasses}`}
41− >
42− <div
43− onClick={() => setTray(!isOpen)}
44− className={`bg-washedWhite w-screen h-screen ${overlayClasses}`}
45− />
46− <div
47− className={`absolute bg-wall-100 h-screen top-0 left-0 tray-menu-width overflow-y-scroll mb-24 ${trayClasses}`}
48− >
49− <div
50− {...handlers}
51− className="flex flex-col px-4 md:px-8 pt-8 md:pt-10 lg:pt-12"
52− >
53− {children}
54− </div>
55− </div>
56−
57− <button
58− onClick={(e) => {
59− e.stopPropagation();
60− search.toggleSearch(e);
61− }}
62− className={`z-20 fixed px-4 items-center justify-center type-ui rounded-xl h-16 bg-white text-wall-500 left-4 right-4 bottom-4 mobile-search-button-width ${
63− isOpen ? "flex" : "hidden"
64− }`}
65− >
66− Search
67− </button>
68− </nav>
69− <button
70− onClick={() => setTray(!isOpen)}
71− className="z-20 fixed bottom-4 right-4 w-16 h-16 bg-wall-600 flex items-center justify-center rounded-full md:hidden"
72− >
73− {isOpen ? (
74− <svg
75− width="16"
76− height="16"
77− viewBox="0 0 16 16"
78− xmlns="http://www.w3.org/2000/svg"
79− >
80− <path
81− fillRule="evenodd"
82− clipRule="evenodd"
83− d="M0.39382 13.7045C-0.131273 14.2296 -0.131274 15.081 0.39382 15.6061C0.918913 16.1312 1.77026 16.1312 2.29535 15.6061L7.99999 9.90142L13.7047 15.6061C14.2297 16.1312 15.0811 16.1312 15.6062 15.6061C16.1313 15.081 16.1313 14.2296 15.6062 13.7046L9.90152 7.99989L15.6061 2.29535C16.1312 1.77026 16.1312 0.918913 15.6061 0.39382C15.081 -0.131273 14.2296 -0.131273 13.7045 0.39382L7.99999 6.09836L2.29548 0.393844C1.77038 -0.131249 0.919038 -0.13125 0.393945 0.393844C-0.131148 0.918937 -0.131148 1.77028 0.393945 2.29537L6.09846 7.99989L0.39382 13.7045Z"
84− className="fill-white"
85− />
86− </svg>
87− ) : (
88− <svg
89− width="16"
90− height="16"
91− viewBox="0 0 16 17"
92− xmlns="http://www.w3.org/2000/svg"
93− >
94− <rect width="16" height="3" rx="1.5" className="fill-white" />
95− <rect y="7" width="16" height="3" rx="1.5" className="fill-white" />
96− <rect
97− y="14"
98− width="16"
99− height="3"
100− rx="1.5"
101− className="fill-white"
102− />
103− </svg>
104− )}
105− </button>
106− </>
107− );
108−}
components/Meta.js+21−2
@@ -2,14 +2,33 @@ export default function Meta(post, disableImage, large = false) {
22 const author = post?.extra?.author || "urbit.org";
33 const title = post?.title ? post.title : "";
44 const description =
5− post?.description || "Urbit is a personal server built from scratch.";
5+ post?.description || "Urbit is a new kind of computer that you can own completely in ways that matter: networking, identity, & data.";
66 const image =
77 post?.extra?.image ||
88 post?.image ||
9− "https://media.urbit.org/logo/urbit-logo-card.png";
9+ "https://storage.googleapis.com/media.urbit.org/site/opengraph/sig-white.png";
1010 return (
1111 <>
1212 <link rel="icon" type="image/png" href="/images/favicon.ico" />
13+ <link
14+ rel="apple-touch-icon"
15+ sizes="180x180"
16+ href="/images/apple-touch-icon.png"
17+ />
18+ <link
19+ rel="icon"
20+ type="image/png"
21+ sizes="32x32"
22+ href="/images/favicon-32x32.png"
23+ />
24+ <link
25+ rel="icon"
26+ type="image/png"
27+ sizes="16x16"
28+ href="/images/favicon-16x16.png"
29+ />
30+ <link rel="manifest" href="/images/site.webmanifest" />
31+
1332 <meta
1433 name="twitter:card"
1534 content={large ? "summary_large_image" : "summary"}
components/Search.jsdeleted−405
@@ -1,405 +0,0 @@
1−import { Component } from "react";
2−import { withRouter } from "next/router";
3−import debounce from "lodash.debounce";
4−import Downshift from "downshift";
5−import ob from "urbit-ob";
6−import Sigil from "../components/Sigil";
7−
8−class Search extends Component {
9− constructor(props) {
10− super(props);
11− this.state = {
12− results: [],
13− };
14− this.searchEndpoint = this.searchEndpoint.bind(this);
15− this.onInputValueChange = this.onInputValueChange.bind(this);
16− this.onSelect = this.onSelect.bind(this);
17− this.glossarySearch = this.glossarySearch.bind(this);
18− this.patpSearch = this.patpSearch.bind(this);
19− this.devSearch = this.devSearch.bind(this);
20− this.opsSearch = this.opsSearch.bind(this);
21− }
22−
23− searchEndpoint(query) {
24− return `/api/search?q=${query}`;
25− }
26−
27− devSearch(query) {
28− return `/api/dev-search?q=${query}`;
29− }
30−
31− glossarySearch(query) {
32− return `/api/glossary?q=${encodeURIComponent(query)}`;
33− }
34−
35− opsSearch(query) {
36− return `/api/ops-search?q=${query}`;
37− }
38−
39− patpSearch(query) {
40− return (
41− (ob.isValidPatp(`~${deSig(query.toLowerCase())}`) &&
42− `~${deSig(query.toLowerCase())}`.length < 15) ||
43− (!isNaN(query) && query <= 4294967295)
44− );
45− }
46−
47− onSelect(item) {
48− if (item.slug) {
49− this.props.router.push(item.slug);
50− }
51−
52− this.setState({
53− query: "",
54− results: [],
55− });
56−
57− this.props.closeSearch();
58− }
59−
60− onInputValueChange = debounce(async (query) => {
61− if (query.length) {
62− const search = fetch(this.searchEndpoint(query))
63− .then((res) => res.json())
64− .then(async (res) => {
65− return res.results.map((item) => ({
66− type: "RESULT",
67− content: item,
68− }));
69− });
70−
71− const patp = this.patpSearch(query)
72− ? !isNaN(query)
73− ? ob.patp(query)
74− : ob.patp(ob.patp2dec(`~${deSig(query)}`))
75− : null;
76−
77− const patpResult = this.patpSearch(query)
78− ? [
79− {
80− type: "PATP",
81− content: {
82− patp: patp,
83− slug: `/ids/${patp}`,
84− },
85− },
86− ]
87− : [];
88−
89− const glossarySearch = fetch(this.glossarySearch(query))
90− .then((res) => res.json())
91− .then((res) => {
92− return res.results.map((item) => ({
93− type: "GLOSSARY_RESULT",
94− content: item,
95− }));
96− });
97−
98− const devSearch = fetch(this.devSearch(query))
99− .then((res) => res.json())
100− .then((res) => {
101− return res.results.map((item) => ({
102− type: "DEV_RESULT",
103− content: item,
104− }));
105− });
106−
107− const opsSearch = fetch(this.opsSearch(query))
108− .then((res) => res.json())
109− .then((res) => {
110− return res.results.map((item) => ({
111− type: "OPS_RESULT",
112− content: item,
113− }));
114− });
115−
116− const [results, glossaryResults, devResults, opsResults] =
117− await Promise.all([search, glossarySearch, devSearch, opsSearch]);
118−
119− const list = [
120− ...glossaryResults,
121− ...patpResult,
122− ...results,
123− ...devResults,
124− ...opsResults,
125− ];
126−
127− this.setState({ results: list });
128− } else {
129− this.setState({ results: [] });
130− }
131− }, 250);
132−
133− render() {
134− const { state, props } = this;
135−
136− if (props.showSearch) {
137− return (
138− <Downshift
139− onSelect={(selection) => this.onSelect(selection)}
140− onInputValueChange={(event) => this.onInputValueChange(event)}
141− itemToString={(item) => (item ? item.slug : "")}
142− defaultHighlightedIndex={0}
143− >
144− {({
145− getInputProps,
146− getItemProps,
147− getLabelProps,
148− getMenuProps,
149− isOpen,
150− inputValue,
151− highlightedIndex,
152− selectedItem,
153− getRootProps,
154− }) => (
155− <div className="fixed w-screen h-screen z-50 flex flex-col items-center p-4">
156− <div
157− onClick={(event) => props.closeSearch(event)}
158− className="top-0 left-0 fixed w-screen h-screen bg-washedWall"
159− />
160− <div className="relative flex flex-col max-w-screen-lg md:my-32 w-full md:w-10/12 lg:w-8/12 xl:w-6/12 rounded-xl bg-white min-h-0 overflow-hidden">
161− <div
162− style={{ display: "inline-block" }}
163− {...getRootProps({}, { suppressRefError: true })}
164− >
165− <input
166− autoFocus
167− className="text-lg md:text-xl lg:text-2xl font-medium text-green-400 bg-transparent py-2 px-4 outline-none relative w-full"
168− placeholder="Search..."
169− type="text"
170− onClick={(e) => e.stopPropagation()}
171− {...getInputProps({
172− onKeyDown: (event) => {
173− if (event.key === "Escape") {
174− // Prevent Downshift's default 'Escape' behavior.
175− event.nativeEvent.preventDownshiftDefault = true;
176− this.props.closeSearch(event);
177− }
178− },
179− })}
180− />
181− </div>
182− <ul {...getMenuProps()} className="overflow-y-scroll">
183− {isOpen
184− ? state.results.map((item, index) => {
185− const selected = highlightedIndex === index;
186− if (item.type === "PATP") {
187− return (
188− <li
189− className={`cursor-pointer p-2 flex space-x-2 items-center text-left w-full ${
190− selected ? "bg-green-400" : ""
191− }`}
192− {...getItemProps({
193− key: item.content.slug + "-" + index,
194− index,
195− item: item.content,
196− selected: highlightedIndex === index,
197− })}
198− >
199− <div className="rounded-md overflow-hidden">
200− <Sigil
201− patp={item.content.patp}
202− size={25}
203− icon
204− />
205− </div>
206− <p className="font-mono">{item.content.patp}</p>
207− </li>
208− );
209− }
210− if (item.type === "GLOSSARY_RESULT") {
211− return (
212− <li
213− className={`cursor-pointer flex text-left w-full ${
214− selected ? "bg-green-400" : ""
215− }`}
216− {...getItemProps({
217− key: item.content.slug + "-" + index,
218− index,
219− item: item.content,
220− selected: highlightedIndex === index,
221− })}
222− >
223− <div className="font-semibold p-3">
224− <p
225− className={`text-base ${
226− selected ? "text-white" : "text-wall-600"
227− }`}
228− >
229− {item.content.symbol.length > 0 && (
230− <code
231− className={`mr-1 rounded px-1 py-0.5 ${
232− selected
233− ? "bg-washedWhite"
234− : "bg-wall-100"
235− }`}
236− >
237− {item.content.symbol}
238− </code>
239− )}
240− {item.content.name}
241− </p>
242− <p
243− className={`font-normal text-base mt-1 ${
244− selected ? "text-white" : "text-wall-600"
245− }`}
246− dangerouslySetInnerHTML={{
247− __html: item.content.desc,
248− }}
249− ></p>
250− </div>
251− </li>
252− );
253− }
254− if (item.type === "RESULT") {
255− return (
256− <li
257− className={`cursor-pointer flex text-left w-full ${
258− selected ? "bg-green-400" : ""
259− }`}
260− {...getItemProps({
261− key: item.content.link + "-" + index,
262− index,
263− item: item.content,
264− selected,
265− })}
266− >
267− <div className="p-3">
268− <p
269− className={`font-medium text-base ${
270− selected ? "text-white" : "text-wall-600"
271− }`}
272− >
273− {item.content.parent !== "Content"
274− ? `${item.content.parent} /`
275− : ""}{" "}
276− {item.content.title}
277− </p>
278− <p
279− className={`text-base font-regular text-small ${
280− selected ? "text-midWhite" : "text-wall-500"
281− }`}
282− >
283− {item.content.content}
284− {item?.content?.foundOnPage && (
285− <span className="italic block">
286− Found in page content
287− </span>
288− )}
289− </p>
290− </div>
291− </li>
292− );
293− }
294− if (item.type === "DEV_RESULT") {
295− const devItem = Object.assign({}, item.content);
296− devItem[
297− "slug"
298− ] = `https://developers.urbit.org${item.content.slug}`;
299− return (
300− <li
301− className={`cursor-pointer flex text-left w-full ${
302− selected ? "bg-green-400" : ""
303− }`}
304− {...getItemProps({
305− key: item.content.link + "-" + index,
306− index,
307− item: devItem,
308− selected,
309− })}
310− >
311− <div className="p-3">
312− <p
313− className={`font-medium text-base ${
314− selected ? "text-white" : "text-wall-600"
315− }`}
316− >
317− <span className="text-wall-400">
318− {item.content.parent !== "Content"
319− ? `developers.urbit.org / ${item.content.parent} /`
320− : "developers.urbit.org /"}{" "}
321− </span>
322− {item.content.title}
323− </p>
324− <p
325− className={`text-base font-regular text-small ${
326− selected ? "text-midWhite" : "text-wall-500"
327− }`}
328− >
329− {item.content.content}
330− {item?.content?.foundOnPage && (
331− <span className="italic block">
332− Found in page content
333− </span>
334− )}
335− </p>
336− </div>
337− </li>
338− );
339− }
340− if (item.type === "OPS_RESULT") {
341− const opsItem = Object.assign({}, item.content);
342− opsItem[
343− "slug"
344− ] = `https://operators.urbit.org${item.content.slug}`;
345− return (
346− <li
347− className={`cursor-pointer flex text-left w-full ${
348− selected ? "bg-green-400" : ""
349− }`}
350− {...getItemProps({
351− key: item.content.link + "-" + index,
352− index,
353− item: opsItem,
354− selected,
355− })}
356− >
357− <div className="p-3">
358− <p
359− className={`font-medium text-base ${
360− selected ? "text-white" : "text-wall-600"
361− }`}
362− >
363− <span className="text-wall-400">
364− {item.content.parent !== "Content"
365− ? `operators.urbit.org / ${item.content.parent} /`
366− : "operators.urbit.org /"}{" "}
367− </span>
368− {item.content.title}
369− </p>
370− <p
371− className={`text-base font-regular text-small ${
372− selected ? "text-midWhite" : "text-wall-500"
373− }`}
374− >
375− {item.content.content}
376− {item?.content?.foundOnPage && (
377− <span className="italic block">
378− Found in page content
379− </span>
380− )}
381− </p>
382− </div>
383− </li>
384− );
385− }
386− return null;
387− })
388− : null}
389− </ul>
390− </div>
391− </div>
392− )}
393− </Downshift>
394− );
395− } else {
396− return null;
397− }
398− }
399−}
400−
401−function deSig(string) {
402− return string.startsWith("~") ? string.substring(1) : string;
403−}
404−
405−export default withRouter(Search);
components/Sidebar.js+1−1
@@ -1,5 +1,5 @@
11import { useState } from "react";
2−import MenuTray from "./MenuTray";
2+import { MenuTray } from '@urbit/foundation-design-system';
33
44export default function Sidebar(props) {
55 const [isOpen, setTray] = useState(false);
components/Sigil.jsdeleted−36
@@ -1,36 +0,0 @@
1−import { sigil, reactRenderer } from "@tlon/sigil-js";
2−
3−export const foregroundFromBackground = (background) => {
4− const rgb = {
5− r: parseInt(background.slice(1, 3), 16),
6− g: parseInt(background.slice(3, 5), 16),
7− b: parseInt(background.slice(5, 7), 16),
8− };
9− const brightness = (299 * rgb.r + 587 * rgb.g + 114 * rgb.b) / 1000;
10− const whiteBrightness = 255;
11−
12− return whiteBrightness - brightness < 50 ? "black" : "white";
13−};
14−
15−export const Sigil = ({ patp, size, color = "#24201E", icon }) => {
16− if (patp.length > 14) {
17− return <div />;
18− }
19− const foreground = foregroundFromBackground(color);
20− return (
21− <div
22− className={icon ? "p-1" : ""}
23− style={{ backgroundColor: icon ? color || "black" : "transparent" }}
24− >
25− {sigil({
26− patp: patp,
27− renderer: reactRenderer,
28− size: icon ? size / 2 : size,
29− colors: [color, foreground],
30− icon: icon || false,
31− })}
32− </div>
33− );
34−};
35−
36−export default Sigil;
components/ecosystem/Badge.jsnew file+20
@@ -0,0 +1,20 @@
1+import classnames from "classnames";
2+export default function EcosystemBadge({ type }) {
3+ return (
4+ <div
5+ className={classnames(
6+ "uppercase font-bold text-white text-xs w-fit rounded-lg mb-2 px-2 py-1",
7+ {
8+ "bg-[#B37ED7]": type === "Organization",
9+ "bg-[#83b2d4]": type === "Application",
10+ "bg-wall-600": type === "Podcast",
11+ "bg-[#8dd5b1]": type === "Marketplace",
12+ "bg-[#B5966D]": type === "Article",
13+ "bg-[#219DFF]": type === "Group",
14+ }
15+ )}
16+ >
17+ {type}
18+ </div>
19+ );
20+}
components/ecosystem/BasicPage.js+47−9
@@ -1,5 +1,6 @@
11import { useRouter } from "next/router";
22import Head from "next/head";
3+import Link from "next/link";
34import Meta from "../Meta";
45import ErrorPage from "../../pages/404";
56import classnames from "classnames";
@@ -12,6 +13,7 @@ import {
1213} from "@urbit/foundation-design-system";
1314import Header from "../Header";
1415import Footer from "../Footer";
16+import MetadataBlock from "./MetadataBlock";
1517
1618export default function BasicPage({
1719 section,
@@ -28,6 +30,7 @@ export default function BasicPage({
2830 metaPost.title = `${post.title} - ${section}`;
2931 metaPost.description =
3032 section === "Podcast" ? `${post.podcast} - ${post.date}` : post.description;
33+ section === "Article" ? `${post.publication} - ${post.date}` : post.description;
3134 return (
3235 <Container>
3336 <Head>
@@ -38,12 +41,12 @@ export default function BasicPage({
3841 </Head>
3942 <IntraNav ourSite="https://urbit.org" search={search} />
4043 <SingleColumn>
41− <Header />
44+ <Header search={search} />
4245 <Section narrow className="space-y-12">
4346 <div className="flex items-center space-x-4">
4447 <img src={post.image} className="w-36" />
4548 <div className="flex flex-col pl-2">
46− <h1 className={classnames({ "text-3xl": section === "Podcast" })}>
49+ <h1 className="text-3xl">
4750 {post.title}
4851 </h1>
4952 <p>{section}</p>
@@ -53,18 +56,41 @@ export default function BasicPage({
5356 <div className="flex justify-between">
5457 <div className="flex space-x-12">
5558 {post?.podcast && (
56− <div className="flex flex-col">
57− <p className="font-bold text-wall-400">Podcast</p>
58− <p>{post.podcast}</p>
59− </div>
59+ <MetadataBlock
60+ title="Podcast"
61+ content={post.podcast}
62+ />
63+ )}
64+ {post?.publication && (
65+ <MetadataBlock
66+ title="Publication"
67+ content={post.publication}
68+ />
69+ )}
70+ {post?.author && (
71+ <MetadataBlock
72+ title="Author"
73+ content={post.author}
74+ />
6075 )}
6176 {post?.date && (
77+ <MetadataBlock
78+ title="Date"
79+ content={post.date}
80+ />
81+ )}
82+
83+ {post?.twitter && (
6284 <div className="flex flex-col">
63− <p className="font-bold text-wall-400">Date</p>
64− <p className="shrink-0">{post.date}</p>
85+ <p className="font-bold text-wall-400">Twitter</p>
86+ <Link href={"http://twitter.com/" + post.twitter}>
87+ <a className="text-green-400 text-sm font-semibold font-mono">@{post.twitter}</a>
88+ </Link>
6589 </div>
6690 )}
67− {post?.URL && section !== "Podcast" && (
91+
92+
93+ {post?.URL && section !== "Podcast" && section !== "Article" && (
6894 <div className="flex flex-col">
6995 <p className="font-bold text-wall-400">Website</p>
7096 <a
@@ -75,6 +101,7 @@ export default function BasicPage({
75101 </a>
76102 </div>
77103 )}
104+
78105 {post?.URL && section === "Urbit Marketplace" && (
79106 <div className="flex flex-col">
80107 <p className="font-bold text-wall-400">Accepts</p>
@@ -84,6 +111,9 @@ export default function BasicPage({
84111 </div>
85112 )}
86113 </div>
114+
115+
116+
87117 {post?.URL && section === "Podcast" && (
88118 <a
89119 href={post.URL}
@@ -93,6 +123,14 @@ export default function BasicPage({
93123 &nbsp;Listen
94124 </a>
95125 )}
126+ {post?.URL && section === "Article" && (
127+ <a
128+ href={post.URL}
129+ className="button-lg bg-green-400 text-white cursor-pointer flex space-x-2"
130+ >
131+ Read
132+ </a>
133+ )}
96134 </div>
97135 <div className="flex">
98136 <div className="markdown w-full">
components/ecosystem/EcosystemSidebar.jsnew file+86
@@ -0,0 +1,86 @@
1+import { useRouter } from "next/router";
2+import Link from "next/link";
3+import classnames from "classnames";
4+function ActiveLink({ children, href, className, currentPath }) {
5+ // special casing this behaviour which overloads one nav
6+ const archive = Boolean(
7+ currentPath === "/ecosystem?type=archive" && href === "/ecosystem"
8+ );
9+ const activeClassName = classnames({
10+ "text-wall-800": currentPath === href || archive,
11+ "text-wall-400": currentPath !== href && !archive,
12+ });
13+
14+ return (
15+ <Link href={href} passHref>
16+ <a className={`${className} ${activeClassName}`}>{children}</a>
17+ </Link>
18+ );
19+}
20+
21+export default function EcosystemSidebar() {
22+ const router = useRouter();
23+ let currentPath = router.asPath;
24+ return (
25+ <div className="flex flex-col space-y-4 pr-24">
26+ <ActiveLink
27+ currentPath={currentPath}
28+ className="type-ui"
29+ href="/ecosystem"
30+ >
31+ Spotlight
32+ </ActiveLink>
33+ <ActiveLink
34+ currentPath={currentPath}
35+ className="type-ui"
36+ href="/ecosystem?type=communities"
37+ >
38+ Communities
39+ </ActiveLink>
40+ <ActiveLink
41+ currentPath={currentPath}
42+ className="type-ui"
43+ href="/ecosystem?type=organizations"
44+ >
45+ Organizations
46+ </ActiveLink>
47+
48+ <ActiveLink
49+ currentPath={currentPath}
50+ className="type-ui"
51+ href="/ecosystem?type=applications"
52+ >
53+ Applications
54+ </ActiveLink>
55+ <ActiveLink
56+ currentPath={currentPath}
57+ className="type-ui"
58+ href="/ecosystem?type=groups"
59+ >
60+ Groups
61+ </ActiveLink>
62+ <ActiveLink
63+ currentPath={currentPath}
64+ className="type-ui"
65+ href="/ecosystem?type=marketplaces"
66+ >
67+ Marketplaces
68+ </ActiveLink>
69+ <ActiveLink
70+ currentPath={currentPath}
71+ className="mr-5 type-ui"
72+ href="/ecosystem?type=podcasts"
73+ >
74+ Podcasts
75+ </ActiveLink>
76+
77+ <ActiveLink
78+ currentPath={currentPath}
79+ className="mr-5 type-ui"
80+ href="/ecosystem?type=articles"
81+ >
82+ Articles
83+ </ActiveLink>
84+ </div>
85+ );
86+}
components/ecosystem/IndexCard.js+13−29
@@ -1,28 +1,30 @@
11import Link from "next/link";
2−import classnames from "classnames";
2+import EcosystemBadge from "./Badge";
33export default function IndexCard({ slug, feat }) {
44 return (
55 <Link href={slug}>
66 <div className="cursor-pointer bg-wall-100 rounded-xl min-h-0 flex-1">
7− <div className="flex flex-col p-4 justify-between items-between h-full relative">
7+ <div className="flex flex-col p-4 h-full relative">
88 {feat.image ? (
9− <img
10− className="rounded-xl w-full flex-1 object-cover"
11− src={feat.image}
12− style={{ aspectRatio: "4 / 3" }}
13− />
9+ <div
10+ className="w-64 md:w-full rounded-xl object-cover overflow-hidden basis-1/2"
11+ style={{
12+ backgroundColor: feat?.matchedPost?.bgColor || "rgba(0,0,0,0)",
13+ }}
14+ >
15+ <img className="h-full w-64 md:w-full object-cover" src={feat.image} />
16+ </div>
1417 ) : (
1518 <div
16− className="rounded-xl w-full flex-1"
19+ className="rounded-xl w-full"
1720 style={{
18− aspectRatio: "4 / 3",
1921 backgroundColor: feat?.matchedPost?.bgColor || "rgba(0,0,0,0)",
2022 }}
2123 />
2224 )}
23− <div className="grow-1 shrink-0 flex flex-col h-full min-h-0 pt-4">
25+ <div className="pt-4">
2426 <p className="mb-2 font-semibold leading-5">{feat.title}</p>
25− {badge(feat.type)}
27+ <EcosystemBadge type={feat.type} />
2628 <p className="text-sm leading-5">{feat?.description}</p>
2729 </div>
2830 </div>
@@ -30,21 +32,3 @@ export default function IndexCard({ slug, feat }) {
3032 </Link>
3133 );
3234}
33−
34−const badge = (type) => {
35− return (
36− <div
37− className={classnames(
38− "uppercase font-bold text-white text-xs w-fit rounded-lg mb-5 px-2 py-1",
39− {
40− "bg-[#B37ED7]": type === "Organization",
41− "bg-[#83b2d4]": type === "Application",
42− "bg-wall-600": type === "Podcast",
43− "bg-[#8dd5b1]": type === "Marketplace",
44− }
45− )}
46− >
47− {type}
48− </div>
49− );
50−};
components/ecosystem/MetadataBlock.jsnew file+7
@@ -0,0 +1,7 @@
1+export default function MetadataBlock({ title, content }) {
2+ return <div className="flex flex-col py-2 basis-1/2">
3+ <p className="font-bold text-wall-400">{title}</p>
4+ <p>{content}</p>
5+ </div>
6+
7+}
components/ecosystem/Post.js+33−22
@@ -1,10 +1,11 @@
11import { Markdown } from "@urbit/foundation-design-system";
2−import classnames from "classnames";
2+import EcosystemBadge from "./Badge";
3+
34import Link from "next/link";
45export default function Post({ post }) {
56 return ["featured-1", "featured-2", "featured-3"].map((feat) => {
67 const childPath =
7− post[feat] && post[feat]?.matchedPost?.type === "Application"
8+ post[feat] && (post[feat]?.matchedPost?.type === "Application" || post[feat]?.matchedPost?.type === "Group")
89 ? `${post[feat]?.matchedPost.ship}/${post[feat].matchedPost.slug}`
910 : `${post[feat].matchedPost?.slug}`;
1011 const href = post[feat]?.matchedPost
@@ -23,10 +24,10 @@ export default function Post({ post }) {
2324 post[feat]?.matchedPost?.bgColor || "rgba(0,0,0,0)",
2425 }}
2526 >
26− {post[feat]?.image && (
27+ {(post[feat]?.matchedPost?.image || post[feat]?.matchedPost?.tile) && (
2728 <img
2829 className="rounded-xl w-24 object-cover"
29− src={post[feat].image}
30+ src={post[feat]?.matchedPost?.image || post[feat]?.matchedPost?.tile}
3031 />
3132 )}
3233 </div>
@@ -34,7 +35,7 @@ export default function Post({ post }) {
3435 <h4 className="text-xl pb-2 leading-6 font-bold">
3536 {post?.[feat].title}
3637 </h4>
37− {badge(post[feat].type)}
38+ <EcosystemBadge type={post[feat].type} />
3839 </div>
3940 </div>
4041 <div className="markdown mt-8 mb-8">
@@ -49,6 +50,14 @@ export default function Post({ post }) {
4950 </Link>
5051 )}
5152
53+ {post[feat].type === "Article" && (
54+ <Link href={href || "#"} passHref>
55+ <a class="button-sm text-white flex-col bg-green-400 cursor-pointer pr-4 w-fit">
56+ Read {post[feat].type}
57+ </a>
58+ </Link>
59+ )}
60+
5261 {post[feat].type === "Application" && (
5362 <Link href={href || "#"} passHref>
5463 <a class="button-sm text-white flex-col bg-green-400 cursor-pointer pr-4 w-fit">
@@ -65,6 +74,15 @@ export default function Post({ post }) {
6574 </Link>
6675 )}
6776
77+ {post[feat].type === "Community" && (
78+ <Link href={href || "#"} passHref>
79+ <a class="button-sm text-white flex-col bg-green-400 cursor-pointer pr-4 w-fit">
80+ More about {post[feat].title}
81+ </a>
82+ </Link>
83+ )}
84+
85+
6886 {post[feat].type === "Marketplace" && (
6987 <Link href={href || "#"} passHref>
7088 <a class="button-sm text-white flex-col bg-green-400 cursor-pointer pr-4 w-fit">
@@ -72,25 +90,18 @@ export default function Post({ post }) {
7290 </a>
7391 </Link>
7492 )}
93+
94+ {post[feat].type === "Group" && (
95+ <Link href={href || "#"} passHref>
96+ <a class="button-sm text-white flex-col bg-green-400 cursor-pointer pr-4 w-fit">
97+ More about {post[feat].title}
98+ </a>
99+ </Link>
100+ )}
101+
75102 </div>
76103 ) : null;
77104 });
78105}
79106
80−const badge = (type) => {
81− return (
82− <div
83− className={classnames(
84− "uppercase font-bold text-white text-xs w-fit rounded-lg mb-2 px-2 py-1",
85− {
86− "bg-[#B37ED7]": type === "Organization",
87− "bg-[#83b2d4]": type === "Application",
88− "bg-wall-600": type === "Podcast",
89− "bg-[#8dd5b1]": type === "Marketplace",
90− }
91− )}
92− >
93− {type}
94− </div>
95− );
96−};
107+
components/ecosystem/SpotlightArchive.jsnew file+66
@@ -0,0 +1,66 @@
1+import { Container, IntraNav, SingleColumn, Section } from "@urbit/foundation-design-system";
2+import Header from "../Header";
3+import Footer from "../Footer";
4+import Meta from "../Meta";
5+import Head from "next/head";
6+import Link from "next/link";
7+import EcosystemSidebar from "./EcosystemSidebar";
8+import Sidebar from "../Sidebar";
9+
10+export default function SpotlightArchive({ posts, search }) {
11+ const post = {
12+ title: "Spotlight Archive",
13+ description: "The archive of ecosystem spotlights.",
14+ };
15+ return (
16+ <Container>
17+ <Head>
18+ <title>Archive • Spotlight • Urbit</title>
19+ {Meta(post)}
20+ </Head>
21+ <IntraNav ourSite="https://urbit.org" search={search} />
22+ <SingleColumn>
23+ <Header search={search} />
24+ <Section>
25+ <div className="measure">
26+ <h1>Ecosystem</h1>
27+ </div>
28+ </Section>
29+ <Section className="flex">
30+ <Sidebar>
31+ <EcosystemSidebar />
32+ </Sidebar>
33+ <div>
34+ <h3 className="mb-12">Spotlight Archive</h3>
35+ {posts.map((post) => {
36+ return (
37+ <div key={post.slug} className="mb-24 cursor-pointer">
38+ <Link href={`/ecosystem/spotlight/${post.slug}`}>
39+ <div>
40+ <h3 className="text-green-400">{post.title}</h3>
41+ <div className="type-ui mt-2">
42+ {["featured-1", "featured-2", "featured-3"].map(
43+ (feat, i) => {
44+ if (post?.[feat]) {
45+ return (
46+ <>
47+ {i ? ", " : ""}
48+ <span>{post[feat].title}</span>
49+ </>
50+ );
51+ }
52+ }
53+ )}
54+ </div>
55+ </div>
56+ </Link>
57+ </div>
58+ );
59+ })}
60+ </div>
61+ </Section>
62+ </SingleColumn>
63+ <Footer />
64+ </Container>
65+ );
66+}
components/gateway/Description.js−1
@@ -4,7 +4,6 @@ const Description = ({ description, fallback, markdown }) => {
44 return (
55 (description !== fallback || markdown) && (
66 <div className="flex flex-col space-y-4">
7− <p className="font-bold text-wall-400">Description</p>
87 {markdown ? (
98 <div className="markdown">
109 <Markdown.render content={JSON.parse(markdown)} />
components/gateway/Image.js+5−6
@@ -1,5 +1,4 @@
1−import Sigil from "../Sigil";
2−
1+import { Sigil } from "@urbit/foundation-design-system";
32const GatewayImage = ({
43 error = false,
54 patp = false,
@@ -9,7 +8,7 @@ const GatewayImage = ({
98}) => {
109 if (error) {
1110 return (
12− <div className="overflow-hidden rounded-xl">
11+ <div className="overflow-hidden rounded-xl shrink-0">
1312 <svg
1413 width={size}
1514 height={size}
@@ -29,7 +28,7 @@ const GatewayImage = ({
2928
3029 if (patp) {
3130 return (
32− <div className="rounded-xl overflow-hidden">
31+ <div className="rounded-xl overflow-hidden shrink-0">
3332 <Sigil patp={patp} size={size} color={color} />
3433 </div>
3534 );
@@ -39,14 +38,14 @@ const GatewayImage = ({
3938 return (
4039 <div
4140 style={{ height: size, width: size, backgroundColor: image }}
42− className="rounded-xl"
41+ className="rounded-xl shrink-0"
4342 />
4443 );
4544 }
4645
4746 return image ? (
4847 <div
49− className="rounded-xl overflow-hidden"
48+ className="rounded-xl overflow-hidden shrink-0"
5049 style={{ backgroundColor: color }}
5150 >
5251 <img src={image} style={{ height: size, width: size }} />
components/gateway/ResourceCard.js+14−3
@@ -1,11 +1,22 @@
11import Link from "next/link";
22import GatewayImage from "./Image";
3+import classNames from "classnames";
4+import { capitalize } from "@urbit/foundation-design-system";
35
4−const ResourceCard = ({ type, shortcode, title, color, image }) => (
6+const ResourceCard = ({ type, shortcode, title, description = "", color, image, full }) => (
57 <Link href={`/${type}s/${shortcode}`}>
6− <div className="cursor-pointer rounded-xl bg-wall-100 p-4 flex items-center space-x-4 mr-2 my-1">
8+ <div className={classNames("cursor-pointer rounded-xl bg-wall-100 p-4 flex items-center space-x-4 mr-2 my-1", {
9+ "basis-full": full
10+ })}>
711 <GatewayImage color={color} image={image || color} size={50} />
8− <a className="font-semibold">{title}</a>
12+ {full
13+ ? <><div className="flex flex-col w-full">
14+ <a className="font-semibold">{title}</a>
15+ <p className="hidden lg:block">{description}</p>
16+ </div>
17+ <a className="button-lg bg-green-400 text-white shrink-0">View {capitalize(type)}</a>
18+ </>
19+ : <a className="font-semibold">{title}</a>}
920 </div>
1021 </Link>
1122);
content/applications/~bacwyl-samweg/templeochess.mdnew file+22
@@ -0,0 +1,22 @@
1++++
2+title = "Temple O Chess"
3+shortcode = "~bacwyl-samweg/templeochess"
4+license = "MIT"
5+image = "https://0x0.st/oFuT.png"
6+bgColor = "#FFFF55"
7+developer = "~bacwyl-samweg"
8+website = "https://youtu.be/Raej8C2yIEc"
9+description = "chess game from Temple OS"
10++++
11+
12+### Chess from Temple OS
13+![Screenshot](https://0x0.st/oORF.png)
14+
15+Temple O Chess is a pixel-for-pixel reproduction of the chess game from Temple OS.
16+
17+It was created using [this youtube video](https://youtu.be/Raej8C2yIEc) as a reference.
18+
19+It's a fully playable online chess game. Instead of a challenge system, games are formed using a naive public queue.
20+
21+Just queue up, and you will be automatically matched with the next (or previous) player.
22+
content/applications/~datder-sonnet/hodl.mdnew file+16
@@ -0,0 +1,16 @@
1++++
2+title = "hodl"
3+description = "Track your digital hodlings"
4+shortcode = "~hodler-datder-sonnet/hodl"
5+license = "MIT"
6+image = "https://user-images.githubusercontent.com/16504501/194947852-8802fd63-5954-4ce8-b147-2072bd929242.png"
7+bgColor = "#b8a3d1"
8+developer = "~datder-sonnet"
9+website = "https://github.com/tomholford/hodl"
10++++
11+
12+A portfolio app for tracking your digital assets.
13+
14+Add transactions to get a summary of your crypto net worth.
15+
16+Supports over 13K coins via the Coingecko API.
content/applications/~disreb-winner-mittec/urbit-go.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Go"
3+shortcode = "~disreb-winner-mittec/urbit-go"
4+license = "GPLv3"
5+image = "https://winnermittec.space/icon.svg"
6+bgColor = "#D37504"
7+developer = "~winner-mittec"
8+website = "https://winnermittec.space/"
9+description = "Go on Urbit"
10++++
11+
12+The classic board-game Go, now on Urbit!
content/applications/~dister-dister-datryn-ribdun/campfire.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Campfire"
3+shortcode = "~dister-dister-datryn-ribdun/campfire"
4+description = "Voice and video chat"
5+license = "MIT"
6+image = "https://raw.githubusercontent.com/datryn-ribdun/urbit-webrtc/master/campfire/logo.svg"
7+bgColor = "#FFC179"
8+developer = "~datryn-ribdun"
9+website = "https://github.com/datryn-ribdun/urbit-webrtc"
10++++
11+
12+Hang out with your friends. Voice and video chat by Holium.
content/applications/~dister-dister-sidnym-ladrut/quorum.mdnew file+17
@@ -0,0 +1,17 @@
1++++
2+title = "Quorum"
3+shortcode = "~dister-dister-sidnym-ladrut/quorum"
4+developer = "Quorum Team"
5+description = "A choral explanations app for Urbit"
6+license = "MIT"
7+website = ""
8+bgColor = ""
9+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/quorum-logo.png"
10++++
11+
12+Quorum is a Stack Overflow/Quora style application that allows individuals to submit and vote on questions and answers in threads.
13+
14+To join the Urbit Foundation's [battery payload] board, when prompted to add a board, enter `~dister-dozzod-lapdeg` as the provider, and `battery-payload` as the board.
15+
16+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/quorum.png)
17+
content/applications/~dister-dozzod-bacdun/uqbar-suite.mdnew file+20
@@ -0,0 +1,20 @@
1++++
2+title = "Uqbar Development Suite"
3+shortcode = "~dister-dozzod-bacdun/zig"
4+developer = "Uqbar"
5+description = "The contract & app development, wallet, and block explorer suite from Uqbar."
6+license = "MIT"
7+website = "https://uqbar.network"
8+bgColor = ""
9+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/uqbarsuite.png"
10++++
11+
12+The Uqbar Development Suite, also known as Ziggurat, is an all-in-one developer suite designed to give programmers a seamless coding experience as they create and deploy smart contracts and blockchain-integrated Urbit apps to our testnet. The Ziggurat suite consists of:
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/ziggurat-1.png)
15+
16+
17+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/ziggurat-2.png)
18+
19+
20+For more information, read our [Developer Docs](https://uqbar-network.gitbook.io/uqbar-developer-documentation/developer-documentation/developer-documentation).
content/applications/~dister-dozzod-dalten/books.mdnew file+20
@@ -0,0 +1,20 @@
1++++
2+title = "Books"
3+developer = "Quartus Co."
4+shortcode = "~dister-dozzod-dalten/books"
5+description = "It just makes cents"
6+license = "MIT"
7+website = "https://dalten.org"
8+bgColor = "#E44D11"
9++++
10+
11+Books is an application for managing your crypto wallets, transactions, and counterparties. It allows you to add your wallet and other people’s, track balances and transactions, and add private annotations to all of the above.
12+
13+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/books.png)
14+
15+## Books in a Nutshell
16+If you spend much time interacting with crypto, you probably have a few wallets: a few hot wallets in metamask, a ledger or two, perhaps an Urbit ID on a master ticket, and that’s just Ethereum.
17+
18+To get a good picture of your aggregate activity you can use a variety of chain analytics tools, but there’s always a sizable catch: there’s nowhere to record the identities of the counter parties you transact with, or the purpose of the transactions. To do this now, your options are to either keep your own records (offline), use a local-storage based address book like Metamask’s, or put your data on someone else’s servers.
19+
20+Books provides an ideal solution: annotate on-chain, public information with private data stored on your urbit, your personal server. This lets you account for your spending, keep records of the people you transact with, and organize your wallets without compromising on privacy or mobility.
content/applications/~dalten/gora.md → content/applications/~dister-dozzod-dalten/gora.mdrenamed+1
@@ -21,3 +21,4 @@ Gora has two distros in
2121circulation - these can be found at:
2222~laddys-dozzod-dalten (Vue.js frontend)
2323~mister-dozzod-dalten (sail frontend)
24+The canonical distro for all Quartus and Dalten Collective apps can always be found at ~dister-dozzod-dalten
content/applications/~dister-dozzod-dalten/keep.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "Keep"
3+developer = "Quartus Co."
4+shortcode = "~dister-dozzod-dalten/keep"
5+description = "State backup for your agents"
6+license = "MIT"
7+website = "https://dalten.org"
8+bgColor = "#E44D11"
9++++
10+
11+Keep is backup utility for preserving the state of your applications across breaches. Unlike [peat](https://urbit.org/ecosystem/applications/~dister-dozzod-dalten/peat), Keep can backup the state of any arbitrary agent, but does not offer granular control of specific graphs or other targeted contexts.
12+
13+For support with any of Quartus' applications, please visit the [Quartus public group](https://urbit.org/ecosystem/groups/~mister-hilper-dozzod-dalten/quartus)
content/applications/~magped-magped-rabsef-bicrym/orca.md → content/applications/~dister-dozzod-dalten/orca.mdrenamed+5−3
@@ -1,13 +1,15 @@
11+++
2−title = "orca"
3−developer = "~dalten"
4−shortcode = "~magped-magped-rabsef-bicrym/orca"
2+title = "Orca"
3+developer = "Quartus Co."
4+shortcode = "~dister-dozzod-dalten/orca"
55description = "Now THIS is podchatting"
66license = "MIT"
77website = "https://dalten.org"
88bgColor = "#13181C"
99+++
1010
11+** ocra has been deprecated and will soon be replaced with updated tooling supporting chat federation for the new Groups backend **
12+
1113Now THIS is podchatting
1214
1315![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/orca.png)
content/applications/~dister-dozzod-dalten/peat.mdnew file+36
@@ -0,0 +1,36 @@
1++++
2+title = "peat"
3+developer = "Quartus Co."
4+shortcode = "~dister-dozzod-dalten/peat"
5+description = "Graph Backup and Restoration Utility"
6+license = "REKT"
7+website = "https://dalten.org"
8+bgColor = "#574D5A"
9++++
10+
11+Peat is Urbit's first backup utility and works with the %graph-store backend. Quartus is also working to support backup and recovery for arbitrary agent state via %keep, as well as updated utility tooling that supports the new Groups backend.
12+
13+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/peat.png)
14+
15+## Peat in a Nutshell
16+- Import
17+ - Recover a Social `graph` from a saved file - transferrable between ships
18+- Export
19+ - Export a Social `graph` to a file on underlying file system (e.g. Unix)
20+- Backup/Restore
21+ - Local recreation of a `graph` that exists, 're-basing' the `graph` to be hosted by the local ship
22+## Import from Disk - Details
23+- User has a `/path/to/pier/<project-desk>/hav` directory for importing (though they could import from anywhere, really).
24+- User also has a form interface, through Peat's webapp allowing them to import without tracking the files in their loom.
25+### From Clay
26+- User gets instructions from the frontend as to how to add files to this directory and commit the desk so the files are available in the OS
27+ - NOTE: This should be converted to using `drum`'s `get` functionality at some point, but this hasn't been wired up yet in `drum`.
28+- User can see all files available for restoration in the default `hav` directory, delineated by whether they represent Agent `state` or `graph`s
29+- User can select a file for restoration
30+- User can apply the file for restoration
31+ - Potentially needing to specify additional details, for a `graph` (e.g. what `group` to associate it with, and what to call the new `resource`)
32+User is informed that the restoration is underway/has completed
33+### From Web
34+- User gets instructions from the frontend as to how to upload files through the frontend, resulting in their unpacking and importing to graph store
35+- User can select from local files on the computer through which they're accessing the frontend.
36+- Note: This method avoids polluting loom with transient files - it is to be the preferred method
content/applications/~magped-magped-rabsef-bicrym/wrdu.md → content/applications/~dister-dozzod-dalten/wrdu.mdrenamed+3−3
@@ -1,8 +1,8 @@
11+++
22title = "wrdu"
3−developer = "~dalten"
4−shortcode = "~magped-magped-rabsef-bicrym/wrdu"
5−description = "word game by ~dalten for our mothers"
3+developer = "Quartus Co."
4+shortcode = "~dister-dozzod-dalten/wrdu"
5+description = "Word game by ~dalten for our mothers"
66license = "MIT"
77website = "https://dalten.org"
88bgColor = "#79A86B"
content/applications/~donpub-datdux/forms.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Forms"
3+shortcode = "~donpub-datdux/forms"
4+developer = "~nallux-dozryl"
5+description = "Publish and Respond to Forms."
6+license = "MIT"
7+website = "https://github.com/nallux-dozryl/urbit-forms"
8+bgColor = "#AFC4E0"
9+image = ""
10++++
11+
12+Create and fill out forms and surveys on Urbit.
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/new-form.png)
content/applications/~fabnev-hinmur/escape.md+3−5
@@ -6,13 +6,11 @@ description = "EScape from Eternal September. The UI from Uqbar."
66license = "MIT"
77website = "https://uqbar.network"
88bgColor = "#f2f3ef"
9−image = "https://escape-app-dist.s3.us-east-2.amazonaws.com/uqbar-logo.png"
9+image = "https://escape-app-dist.s3.us-east-2.amazonaws.com/escape-logo.png"
1010+++
1111
12−EScape is an alternative interface to Tlon's groups app.
12+EScape is a fully-integrated social management and DAO Tooling system. EScape provides a simple, intuitive, and unified interface for managing groups, messaging ships, receiving notifications, and interacting with other Urbit apps.
1313
14−![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/escape.png)
15−
16−EScape lets you view groups, messages, and apps in collapsible column interface, organize groups by folders, and "like" messages in chats. EScape is also has apps for both iOS and Android that include push notifications for chat mentions and messages.
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/escape2.png)
1715
1816Get EScape on [iOS](https://apps.apple.com/my/app/escape-by-uqbar/id1610194217) and [Android](https://play.google.com/store/apps/details?id=network.uqbar.escape).
content/applications/~fabnev-hinmur/handshake.md+1−1
@@ -9,6 +9,6 @@ bgColor = "#df828b"
99image = "https://static.thenounproject.com/png/2002633-200.png"
1010+++
1111
12−An app for building guestlists of Urbit IDs and verifying their ownership at the door. For best experience, access from [EScape](/applications/~fabnev-hinmur/escape).
12+Handshake generates and verifies QR codes for admission into IRL events.
1313
1414![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/handshake.png)
content/applications/~finmep-lanteb/chess.md+5−3
@@ -1,12 +1,14 @@
11+++
22title = "Chess"
33shortcode = "~finmep-lanteb/chess"
4−developer = "~finmep-lanteb & ~sigryn-habrex"
4+developer = "~bonbud-macryg, ~finmep-lanteb, ~nordus-mocwyl, ~rovmug-ticfyn, ~sigryn-habrex"
55description = "Fully peer-to-peer chess over Urbit"
66license = "GPL3"
7−website = "https://github.com/ashelkovnykov/urbit-chess"
7+website = "https://github.com/thecommons-urbit/chess"
88bgColor = "#ffffff"
99image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/finmep-chess.svg"
1010+++
1111
12−Fully decentralized, peer-to-peer Chess app for Urbit
12+Fully decentralized, peer-to-peer Chess app for Urbit
13+
14+![chess example](https://raw.githubusercontent.com/thecommons-urbit/chess/master/images/urbit-chess-demo.png)
content/applications/~hanfel-dovned/board.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Board"
3+shortcode = "~dister-hanfel-dovned/board"
4+license = "MIT"
5+image = ""
6+bgColor = "#9E34EB"
7+developer = "~hanfel-dovned"
8+website = "https://github.com/hanfel-dovned/Board"
9+description = "A digital bulletin-board"
10++++
11+
12+An implementation of [Robin Sloan’s Spring ‘83](https://www.robinsloan.com/lab/specifying-spring-83/) concept as an Urbit app called %board. Imagine a digital bulletin-board where each item is a person’s miniature homepage, and the pages you see are based on who you know.
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/board.png)
content/applications/~hanfel-dovned/pony.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Pony"
3+shortcode = "~dister-hanfel-dovned/pony"
4+license = "MIT"
5+image = ""
6+bgColor = "#232323"
7+developer = "~hanfel-dovned"
8+website = "https://github.com/hanfel-dovned/Pony"
9+description = "Pony is an app for longform threaded conversations"
10++++
11+
12+Pony is an app for longform threaded conversations, like a blend of email and message boards. Create private threads with arbitrary sets of ships, fork threads to new sets of participants, schedule messages to be sent later, and much more.
content/applications/~hanfel-dovned/slam.md+1
@@ -6,6 +6,7 @@ image = "https://hanfel-dovned.sfo3.digitaloceanspaces.com/slam-tile.png"
66bgColor = "#100032"
77developer = "~hanfel-dovned"
88website = "https://github.com/hanfel-dovned/Slam"
9+description = "A social arcade game"
910+++
1011
1112Slam is a social arcade game where you battle waves of enemies that are generated from your pals' gorae.
content/applications/~hanrut-sillet-dachus-tiprel/blog.mdnew file+16
@@ -0,0 +1,16 @@
1++++
2+title = "%blog"
3+shortcode = "~hanrut-sillet-dachus-tiprel/blog"
4+license = "MIT"
5+image = ""
6+bgColor = "#533E78"
7+developer = "~dachus-tiprel"
8+website = "https://dachus-tiprel.tlon.network/blog/introducing-blog"
9+description = "The easiest and most versatile publishing app on Urbit"
10++++
11+
12+A publishing tool for creating a basic blog with markdown and css.
13+
14+Blog is just what it sounds like. A new tool from Uqbar, the app lets anyone on Urbit spin up and customize a blog that displays to the net at an auto-generated URL. Nothing could be breezier. Plus it’s got payments through Uqbar and group-blogging settings on the roadmap. Find out more about it on it's [creator's blog](https://dachus-tiprel.tlon.network/blog/introducing-blog).
15+
16+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/blog.png)
content/applications/~lander-dister-dozzod-dozzod/groups.mddeleted−31
@@ -1,31 +0,0 @@
1−+++
2−title = "Groups"
3−developer = "Tlon"
4−shortcode = "~lander-dister-dozzod-dozzod/landscape"
5−description = "A suite of applications to communicate on Urbit"
6−license = "MIT"
7−website = "https://tlon.io"
8−bgColor = "#DC5F3F"
9−+++
10−
11−
12−Groups is Tlon's flagship app: a community center, workspace, gallery, publisher, and messenger. Designed as a tool for collectives and organizations of various sizes on Urbit, Groups can host a company communication suite, a DAO, a blog, a music syndicate, and just about anything that involves collaboration, publication, or communication.
13−
14−![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/groups.png)
15−
16−*Messages–send encrypted direct messages to one or many friends:*
17−
18−Reach out to your friends directly via Messages, a simple chat tool that lets you talk one-on-one or with many.
19−
20−*Notebooks–write and publish documents or blog posts:*
21−
22−Write a blog post, create a magazine, draft an announcement or documentation using Notebooks, a short and long form text editor. You can add images, give other ships permission to comment on your posts, and mirror your content on the mainnet with ~tirrel's %studio app.
23−
24−*Collections–maintain a mood board and gather links:*
25−
26−Assemble a feed of images, save links for later, make a mood board, or start a forum on Collections, a repository for day-to-day digital trawling.
27−
28−*Profiles–personalize your Urbit ID:*
29−
30−Make your Urbit ID yours: set a nickname, write a bio, change your avatar, or choose to stay anonymous. You can also pin featured groups on your profile. Hint: It’s a good way to share and discover new groups to join.
31−
content/applications/~larryx-woldyr/osmosis.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Osmosis"
3+shortcode = "~larryx-woldyr/osmosis"
4+license = "MIT"
5+image = "https://holium-app-globs.nyc3.cdn.digitaloceanspaces.com/osmosis/osmosis-logo-wc.png"
6+bgColor = "#180D39"
7+developer = "~larryx-woldyr"
8+website = "https://https://osmosis.zone/"
9+description = "Interchain liquidity lab."
10++++
11+
12+A fully self-hosted Osmosis frontend, deployed via Urbit.
content/applications/~larryx-woldyr/safe.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Safe"
3+shortcode = "~larryx-woldyr/safe"
4+license = "MIT"
5+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/safe.jpeg"
6+bgColor = "#180D39"
7+developer = "~larryx-woldyr"
8+website = "https://safe.global/"
9+description = "Safe front-end"
10++++
11+
12+A fully self-hosted Safe frontend, deployed via Urbit.
content/applications/~larryx-woldyr/uniswap.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Uniswap"
3+shortcode = "~larryx-woldyr/uniswap-v3"
4+license = "MIT"
5+image = "https://cryptologos.cc/logos/uniswap-uni-logo.png"
6+bgColor = "0xffffff"
7+developer = "~larryx-woldyr"
8+website = "http://uniswap.org"
9+description = "Self-hosted Uniswap interface"
10++++
11+
12+A self-hosted Uniswap interface for swapping assets on Ethereum.
content/applications/~larryx-woldyr/urbhue.mdnew file+18
@@ -0,0 +1,18 @@
1++++
2+title = "Hue"
3+shortcode = "~larryx-woldyr/urbhue"
4+license = "MIT"
5+image = "https://i.imgur.com/czmkmoK.png"
6+bgColor = "#F0B43D"
7+developer = "~larryx-woldyr"
8+website = "https://ajlamarc.com"
9+description = "Controlling Philips Hue"
10++++
11+
12+In this prototype, Philips Hue Lightbulbs and groups can be controlled from a standard Urbit application by using the Hue Remote API.
13+
14+History and logging of the bulb are collected to provoke consideration of what should be controlled and tracked by the people living in a smart home.
15+
16+This app will hopefully inspire people to think of the potential utility of Urbit in the smart home, inspire non-Urbit users to think of Urbit in non-community driven scenarios, and be a small step forward in understanding the affordances for Urbit in the home.
17+
18+For more information on `%urbhue`, check out our Urbit group: `~pilwyc-fastec/communal-computing-for-urbit`
content/applications/~lomder-librun/realm.mdnew file+18
@@ -0,0 +1,18 @@
1++++
2+title = "Realm"
3+shortcode = "~lomdyr-librun/realm"
4+license = ""
5+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/realm-icon.png"
6+bgColor = ""
7+developer = "Holium"
8+website = "https://www.holium.com/"
9+description = "A desktop interface for Urbit"
10++++
11+
12+Realm is a desktop app for Urbit communities (currently in private alpha).
13+
14+[Sign up for the alpha.](https://www.holium.com/)
15+
16+<iframe width="560" height="315" src="https://www.youtube.com/embed/gdu4QtFR-Bs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
17+
18+Note that the shortcode will not install this application.
content/applications/~migmeg-fidlen-sillus-mallus/kenning.mdnew file+17
@@ -0,0 +1,17 @@
1++++
2+title = "kenning"
3+shortcode = "~migmeg-fidlen-sillus-mallus/kenning"
4+license = "MIT"
5+image = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Voiced_dental_fricative_%28vector%29.svg/1920px-Voiced_dental_fricative_%28vector%29.svg.png"
6+bgColor = "#a59a2d"
7+developer = "~sillus-mallus"
8+website = "https://lovecrypt.net"
9+description = "Memorization tool for text passages."
10++++
11+
12+Memorize passages of text. Every passage is called a “kenning”.
13+
14+1. Every kenning is assigned a kelvin version based on word count.
15+1. You may test your knowledge by filling in the blanks.
16+1. As kelvin decreases, the number of blanks increases.
17+1. For large passages, split the text into several kens for best results.
content/applications/~niblyx-malnus/gol-cli.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "Goals"
3+shortcode = "~dister-dozzod-niblyx-malnus/gol-cli"
4+license = "MIT"
5+image = ""
6+bgColor = "#362711"
7+developer = "~niblyx-malnus"
8+website = ""
9+description = "Hierarchically nested goals and projects"
10++++
11+
12+### Goals helps you track and share interrelated tasks
13+
14+
15+Goals is primarily dealing with four kinds of relationships: containment/ownership, virtual nesting, precedence, and priority. These fundamental relationships between goals and that any other important information about a goal does not require any complex sort of topological representation, but can simply be a piece of data associated with the goal.
content/applications/~nocsyx-lassul/sphinx.md+1
@@ -6,6 +6,7 @@ image = "https://nyc3.digitaloceanspaces.com/hmillerdev/nocsyx-lassul/2022.7.16.
66bgColor = "#b25068"
77developer = "~nocsyx-lassul"
88website = "https://github.com/arthyn/sphinx"
9+description = "Community powered search"
910+++
1011
1112### Community powered search
content/applications/~nodmyn-dosrux/basket.mdnew file+34
@@ -0,0 +1,34 @@
1++++
2+title = "basket"
3+shortcode = "~nodmyn-dosrux/basket"
4+license = "MIT"
5+image = "https://0x0.st/oFHB.png"
6+bgColor = "#F2F2F2"
7+developer = "Assembly Capital"
8+website = "https://github.com/bacwyls/basket"
9+description = "show off your meme collection"
10++++
11+
12+
13+### Basket is a simple db of tagged images
14+
15+The frontend displays the most recent image in the full window,
16+so it can be used to add some personal style to an urbit desktop environment.
17+
18+In addition to being a personal db, basket is an experimental app on top of the 'rooms' primitive in [Realm](https://twitter.com/HoliumCorp).
19+
20+Members of a room have temporary write-access to each others basket db.
21+The frontend makes it ergonomic and fun to share / collaboritively create this data.
22+
23+In theory (at scale), this creates a kind of decentralized giphy.
24+
25+The images you know about are the images your friends have shared with you.
26+It gamifies the creation of rich, human curated image metadata.
27+One obvious use case for this is keeping track of memes.
28+
29+To export the full dataset you can GET `http://yoururbitship.com/~/scry/basket/images.json`
30+Then you might want to use a python script to actually download the images to local storage.
31+
32+Eventually, it would be nice to have a simple way to export and share the dataset.
33+
34+Read full documentation on the [Github repository](https://github.com/bacwyls/basket).
content/applications/~nodmyn-dosrux/houston.md+1−1
@@ -4,7 +4,7 @@ shortcode = "~nodmyn-dosrux/houston"
44license = "MIT"
55image = "https://0x0.st/ojrj.png"
66bgColor = "#FFFFFF"
7−developer = "~nodmyn-dosrux"
7+developer = "Assembly Capital"
88website = "https://github.com/assemblycapital/houston"
99description = "Moon Management Dashboard"
1010+++
content/applications/~nodmyn-dosrux/radio.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "radio"
3+shortcode = "~nodmyn-dosrux/radio"
4+license = "MIT"
5+image = "https://0x0.st/o4--.png"
6+bgColor = "#f2f2f2"
7+developer = "Assembly Capital"
8+website = "https://github.com/bacwyls/radio"
9+description = "an app for urbit disc jockeys"
10++++
11+
12+Create and tune into virtual radio stations where you can chat and play Youtube videos with your friends.
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/radio.png)
15+
content/applications/~nodmyn-dosrux/vita.mdnew file+20
@@ -0,0 +1,20 @@
1++++
2+title = "vita"
3+shortcode = "~nodmyn-dosrux/vita"
4+license = "MIT"
5+image = "https://bwyl.nyc3.digitaloceanspaces.com/vita%2Fvita.png"
6+bgColor = "#F2F2F2"
7+developer = "Assembly Capital"
8+website = "https://github.com/assemblycapital/vita"
9+description = "monitor your app distributions"
10++++
11+
12+### Keep track of your app distributions
13+
14+To get downloads, `:vita` periodically scrys %cs /subs for each desk and caches the results.
15+
16+`:vita` accepts foreign pokes attesting to activity on a desk.
17+`/lib/vita-client.hoon` helps any agent send vita activity pokes.
18+It sends a maximum of one poke per day, and allows users to opt-in / opt-out depending on developer preference.
19+
20+Read full documentation on the [Github repository](https://github.com/assemblycapital/vita).
content/applications/~paldev/scooore.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "sc'o're"
3+developer = "~paldev"
4+shortcode = "~paldev/scooore"
5+description = "leaderboard for groups' ['o']s, as seen on tv!"
6+license = "MIT"
7+image ="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/scooore.svg"
8+website = "https://pal.dev/suite/scooore"
9+bgColor = "#FDFF54"
10++++
11+
12+A leaderboard of your peers' emoji reactions in Groups.
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/scooore.png)
content/applications/~pocwet/straw.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "Straw"
3+developer = "~pocwet"
4+shortcode = "~pocwet/straw"
5+description = "Vote on what to publish."
6+license = "MIT"
7+website = "https://urbit.org"
8+bgColor = "#6C6973"
9+image = ""
10++++
11+
12+
13+This app lets group members vote on whether a post is published to a notebook. It is intended for use with Studio, which you can install from ~tirrel/studio.
content/applications/~sogryp-dister-dozzod-dozzod/groups.mdnew file+40
@@ -0,0 +1,40 @@
1++++
2+title = "Groups"
3+shortcode = "~sogryp-dister-dozzod-dozzod/groups"
4+license = "MIT"
5+image = "https://bootstrap.urbit.org/icon-groups.svg"
6+bgColor = "#EFF0F4"
7+developer = "Tlon"
8+website = "https://github.com/tloncorp/landscape-apps"
9+description = "Groups is a decentralized platform that integrates with Talk, Notebook, and Gallery for a full, communal suite of tools."
10++++
11+
12+Start, host, and cultivate communities. Own your communications, organize your resources, and share documents. Groups is a decentralized platform that integrates with Talk, Notebook, and Gallery for a full, communal suite of tools.
13+
14+ <video autoPlay muted loop playsInline>
15+ <source
16+ src="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/groups-create-a-group.webm"
17+ type="video/webm"
18+ />
19+ </video>
20+
21+Teams, clubs, DAOs, and secret societies use Groups to digitally congregate, using channel integrations to extend their capabilities.
22+
23+ <video autoPlay muted loop playsInline>
24+ <source
25+ src="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/groups-create-a-channel.webm"
26+ type="video/webm"
27+ />
28+ </video>
29+
30+Write, edit, and publish longform or shorter documents with Notebook, a basic text editor for announcements, internal meeting minutes, blogs, and everything in between.
31+
32+ <video autoPlay muted loop playsInline>
33+ <source
34+ src="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/notebooks.webm"
35+ type="video/webm"
36+ />
37+ </video>
38+
39+
40+Gather links to images, articles, and web pages to maintain a collection of references with Gallery, a versatile and interoperable repository for day-to-day digital trawling.
content/applications/~sogryp-dister-dozzod-dozzod/talk.mdnew file+21
@@ -0,0 +1,21 @@
1++++
2+title = "Talk"
3+shortcode = "~sogryp-dister-dozzod-dozzod/talk"
4+license = "MIT"
5+image = "https://bootstrap.urbit.org/icon-talk.svg"
6+bgColor = "#2B5DC0"
7+developer = "Tlon"
8+website = "https://github.com/tloncorp/landscape-apps"
9+description = "Talk is a decentralized chat app that integrates with Groups, Notebook, and Gallery for a full, communal suite of tools."
10++++
11+
12+Send peer-to-peer direct messages to one or many friends. Talk is a simple chat tool for catching up, getting work done, and everything in between.
13+
14+ <video autoPlay muted loop playsInline>
15+ <source
16+ src="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/talk.webm"
17+ type="video/webm"
18+ />
19+ </video>
20+
21+Start threads. React with emojis. Respond to your Groups chat channels from Talk. When integrated with Groups, both direct messages and team chats appear in Talk. Two apps in one place.
content/applications/~sortug/gate.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Gate"
3+shortcode = "~dister-dozzod-sortug/gate"
4+license = "MIT"
5+image = "https://s3.sortug.com/img/fav.png"
6+bgColor = "#000000"
7+developer = "Sortug Development"
8+website = "https://sortug.com"
9+description = "Seamless QR login"
10++++
11+
12+# Secure, seamless login for Urbit
13+
14+Let's make joining Urbit easier!
15+
16+Why do this?
17+![code](https://s3.sortug.com/img/gate-code.png)
18+When you can do this?
19+![gate](https://s3.sortug.com/img/gate-gate.png)
20+
21+Logging in to any Urbit app requires you to input your ship's URL and the `+code` generated on dojo. This requires people to login to their ship's terminal, output the code on dojo, then copy and paste it in their browser or app. This is bad enough if you have a ship running locally, but if you have it running remotely (as is common) the process becomes seriously annoying.
22+
23+Mainstream mobile apps such as Signal handle first login much more seamlessly; after registration is done, further logins are done via QR code. The app produces a QR code, you scan it, and that's it. That's the state-of-the-art, battle-tested user experience for modern applications. Now available on Urbit.
24+
25+Gate makes it easier for newcomers to use Urbit, and greatly enhances the user experience of native applications, desktop and mobile, that Urbit deserves.
26+
27+Users can login to Urbit just by scanning a QR code, receive a URL link and login to an Urbit ship instantly by clicking on it. That simple. Most importantly, hosting providers can use Gate to send a QR code or a URL link to a user, and have the user access his Urbit apps with a simple camera scan or click of a link, making the onboarding process much easier for non-technical users.
content/applications/~sortug/trill.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Trill"
3+shortcode = "~dister-dozzod-sortug/trill"
4+license = "MIT"
5+image = "https://s3.urbit.cloud/img/trill-logo.png"
6+bgColor = "#000000"
7+developer = "Sortug Development"
8+website = "https://sortug.com"
9+description = "Urbit Native Microblog"
10++++
11+
12+### Your own social feed, forever.
13+
14+Urbit is a networked personal server. It is the ideal stack to host a microblog service.
15+
16+For years Urbit users have been busy chatting to each other, coordinating to build the network. But it is time that we lay back a little and just post at our leisure.
17+
18+Trill is an Urbit native microblog. You can post text or media links into your feed, make threads, and share it with your friends and followers. You can also build a timeline of your favorite Urbit users, and keep lists of users, categorized as you want.
19+
20+Unlike other microblogs, however, users of Trill truly own their feed. Users host their own content. They can even program it; tinker with the source as much as you want.
21+
22+There are no ads in Trill, no "trends", no analytics. We don't even know how many people are using Trill. And we don't care. We just want to trill. Please join the party.
23+
24+### More information
25+You can install the app by searching for ~dister-dozzod-sortug on your Grid interface, or by running `|install ~dister-dozzod-sortug %trill` in Dojo.
26+
27+The official group of the app is at ~hoster-dozzod-sortug/trill on the Groups app.
content/applications/~sortug/ufa.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Urbit Feed Aggregator"
3+shortcode = "~dister-dozzod-sortug/ufa"
4+license = "MIT"
5+image = "https://s3.urbit.cloud/img/lan.png"
6+bgColor = "#000000"
7+developer = "Sortug Development"
8+website = "https://sortug.com"
9+description = "Bring all the web into Urbit"
10++++
11+
12+### Own your content, share it with your friends
13+
14+Urbit is your personal server. Why do you want a personal server? Many things. But one of them, part of the initial vision of Urbit's development, was to use to interact programatically with the Web. To interact with Web services, but in your own terms. Using your chosen frontend, blocking all tracking, telemetry, analytics and other malicious code. Urbit as an API aggregator.
15+
16+The Urbit Feed Aggregator (aka UFA) makes that vision true. Now you will be able to browse the best content on the internet, but really own it, like people used to own books, magazines and newspapers. Control, curate, save and share your the content you like, with complete freedom.
17+
18+UFA is not just an app, it's a platform to which a myriad apps will be added in the future. As of present (August 2022) UFA includes support for Trill (our sister app, the Urbit native microblog) and Twitter. You can read and keep lists of Twitter content without having to login to Twitter.com, and you can save and share that content inside Urbit, via the Trill or Groups apps.
19+
20+### More information
21+You can install the app by searching for ~dister-dozzod-sortug on your Grid interface, or by running `|install ~dister-dozzod-sortug %ufa` in Dojo.
22+
23+The official group of the app is at ~hoster-dozzod-sortug/ufa on the Groups app.
24+
25+You can also follow ~sortug on Trill for announcements.
26+
27+Within 2022 RSS, Instagram and Email support will be added. For the future, the sky is the limit. If you want to help create a new plugin for UFA, please contact us at the official group.
content/applications/~tiller-tolbus/membrane.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Membrane"
3+shortcode = "~mister-master-tiller-tolbus/membrane"
4+license = "MIT"
5+image = "https://tiller-tolbus.nyc3.digitaloceanspaces.com/membrane.png"
6+bgColor = ""
7+developer = "~tiller-tolbus"
8+website = ""
9+description = "Spreadsheets and databases"
10++++
11+
12+### Membrane is a spreadsheet tool for Urbit
13+
14+Spreadsheets were the original tool for the productivity power user, so it is only fitting that we bring them to Urbit. Keep a budget, run a formula, and share your sheets with friends using Membrane.
content/applications/~tirrel/scene.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Scene"
3+shortcode = ""
4+license = ""
5+image = "https://tirrel.io/assets/scene-logo-stroke.svg"
6+bgColor = "rgb(0, 0, 0)"
7+developer = "Tirrel Corp."
8+website = "https://tirrel.io"
9+description = "The new Urbit desktop, by ~tirrel corp."
10++++
11+
12+![Screenshot](https://tirrel.io/assets/scene-demo-screenshot.webp)
13+
14+[Download scene here](https://tirrel.io/scene/index.html).
content/applications/~tirrel/studio.md+1−1
@@ -1,7 +1,7 @@
11+++
22title = "Studio"
33shortcode = "~tirrel/studio"
4−license = "MIT"
4+license = ""
55image = "https://tirrel.io/assets/stool.svg"
66bgColor = "rgb(160, 226, 167)"
77developer = "Tirrel Corp."
content/applications/~worpet-bildet/portal.mdnew file+16
@@ -0,0 +1,16 @@
1++++
2+title = "Portal"
3+shortcode = "~worpet-bildet/portal"
4+license = ""
5+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/portal.svg"
6+bgColor = "rgb(0,0,0)"
7+developer = ""
8+website = ""
9+description = "Portal is the front page"
10++++
11+
12+### Portal is the front page for urbit
13+
14+Portal made its debut as the solution to decentralized discovery on Urbit. Portal enables anyone on Urbit to curate content, apps, and groups for other ships to discover
15+
16+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/portal-screenshot.png)
content/apprenticeships.md+14−15
@@ -1,39 +1,38 @@
11+++
22title = "Become an Apprentice"
3−date = "2022-03-27"
3+date = "2023-01-04"
44weight = 1
55description = "Everything you need to know about applying for an apprenticeship"
66+++
77
88Apprenticeships are practical learning opportunities for new Urbit developers provided by experienced members of the Urbit development community. As an apprentice, you'll have the opportunity to:
99
10−- Learn from an expert Urbit engineer
11−- Make real contributions to the project, and
10+- Learn from an experienced Urbit contributor
11+- Make helpful contributions to an active project, and
1212- Earn address space for learning
1313
1414Becoming an apprentice is easily one of the best ways to level up your skills, and perhaps even land a job.
1515
1616## Get started
1717
18−Apprenticeships are for those that are new to Urbit development (or an area of it), but not new to programming. Nearly all apprenticeships involve some degree of Hoon work, so you should make sure that you've completed [Hoon School](/docs/hoon/hoon-school/intro) and the [Gall Guide](/docs/userspace/gall-guide/intro) prior to signing up.
18+Apprenticeships are for those that are new to Urbit development (or an area of it), and would like to find their grounding by working on a pre-existing codebase and problem set. Nearly all apprenticeships involve some degree of Hoon work, so you should make sure that you've completed [Hoon School](https://developers.urbit.org/guides/core/hoon-school) and [App School](https://developers.urbit.org/guides/core/app-school/intro) in either their asychronous or [cohort formats](https://developers.urbit.org/courses) prior to signing up.
1919
20−There are two ways to sign up for an apprenticeship:
20+To become an apprentice, [apply for an open apprenticeship](/grants?program=apprenticeship&open=true&wip=false&completed=false#view-grants)
2121
22−1. [Apply for an open apprenticeship](/grants?program=apprenticeship&open=true&wip=false&completed=false#view-grants)
23−2. [Sign up to be matched to a mentor](https://airtable.com/shrUZQpHqRtudHhAx)
24−
25−Apprenticeships are sometimes posted on the site to be claimed, but more often than not they emerge out of a conversation between a mentor and an apprentice. This is because mentors are generally busy engineering, and while they know many things that need to be done, getting those ideas into writing is difficult.
26−
27−When you [sign up to be matched](https://airtable.com/shrUZQpHqRtudHhAx), the Urbit Foundation will review your application, pass it around to available mentors, and more often than not a call will get scheduled and an apprenticeship started.
22+Although some apprenticeships are posted on this site to be claimed, more often than not they emerge out of a conversation between a mentor and an enthusiastic potential apprentice. This is because mentors are generally busy engineering, and while they know many things that need to be done, getting those ideas into writing is difficult.
2823
2924## How it works
3025
31−Once a mentor has written up an apprenticeship, approved an apprentice, and all parties have signed a contract with the Urbit Foundation, work can proceed.
26+Once a mentor has written up an apprenticeship, and approved an apprentice, The Urbit Foundation will perform a quick KYC step and send contracts to all parties for signing. Once those contracts are executed, work can proceed.
3227
3328Mentors and apprentices work together by having weekly pairing sessions and maintaining an open line of communication over Urbit. It's expected that mentors put at least two hours per week into supporting their apprentice.
3429
35−When a mentor has signed off on the apprentice's work, the mentor will notify the Urbit Foundation of completion and the apprentice will invoice the UF for payment.
36−
3730## Funding
3831
39−Apprenticeships pay 1 star upon the sucessful completion of the apprenticeship, for an apprenticeship of a duration of up to three months. Upon completion of your apprenticeship, please [submit an invoice here](https://airtable.com/shrXXCs1uaxtNSBcg).
32+Apprenticeships pay 1 star upon the sucessful completion of the apprenticeship, for an apprenticeship of a duration of up to three months.
33+
34+## Getting Paid
35+
36+When you have completed the scope of your grant, you will create a detailed writeup of the work completed and your learnings, share the writeup with your mentor, and get your approval of completion. After recieving this approval from your mentor, please [submit an invoice here](https://airtable.com/shrXXCs1uaxtNSBcg). Your mentor must also contact `~marfun-pacpet` to confirm completion of the apprenticeship and approve the payment. Once the Urbit Foundation receives approval from your champion and an invoice for the amount agreed upon in your grant or milestone, the Foundation will pay your star allocation to the Ethereum address you have provided.
37+
38+We approve and issue payments within 30 days of invoice receipt and approval, although often payment is made more quickly. If you have any questions regarding getting paid or submitting an invoice, please contact `~marfun-pacpet` for assistance.
content/articles/2022-09-24_urbit-courts-daos-crypto.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Urbit Courts DAOs, Crypto Teams in Quest to Make Internet P2P Again"
3+publication = "Coindesk"
4+author = "March Hochstein and Daniel Kuhn"
5+date = "2022-09-24"
6+URL = "https://www.coindesk.com/layer2/2022/09/24/urbit-courts-daos-crypto-teams-in-push-to-make-internet-p2p-again/"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/coindesk.jpg"
8++++
9+
10+A wildly ambitious project to reinvent the entire internet computing stack is finally shipping usable apps after a decade-plus of laying groundwork. Can it overcome a “janky” UX?
content/articles/2022-09-24_urbit-is-web3-weird-and-wonderful.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Urbit Is Web3, Weird and Wonderful and I Don’t Care Who Made It"
3+publication = "Coindesk"
4+author = "March Hochstein"
5+date = "2022-09-24"
6+URL = "https://www.coindesk.com/layer2/2022/09/24/urbit-is-web3-weird-and-wonderful-and-i-dont-care-who-made-it/"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/coindesk.jpg"
8++++
9+
10+Software can have bugs, but it doesn’t have cooties.
content/articles/2022-09-28_college-course-on-urbit.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Why Would Anyone Take a College Course on Urbit?"
3+publication = "Coindesk"
4+author = "Daniel Kuhn"
5+date = "2022-09-28"
6+URL = "https://www.coindesk.com/layer2/2022/09/28/why-would-anyone-take-a-college-course-on-urbit/"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/coindesk.jpg"
8++++
9+
10+Neal Davis taught the first graduate-level seminar on the controversial computing platform Urbit. Here’s why.
content/articles/2022-09-29_assembly-miami-dispatch.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Urbit Assembly: If We’re All Here, Who’s Watching The Internet?"
3+publication = "Zora Zine"
4+author = "Madeline Cash"
5+date = "2022-09-29"
6+URL = "https://zine.zora.co/urbit-assembly-miami-dispatch"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/zorazine.png"
8++++
9+
10+Forever Magazine founder and Zora Zine contributor Madeline Cash reports on secret societies, subjective idealism, and digital intimacy in her dispatch from Urbit Assembly in Miami
11+
content/articles/2022-09-29_the-dream-of-digital-homesteading.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "The Dream of Digital Homesteading"
3+publication = "Compact"
4+author = "Geoff Schullenberger"
5+date = "2022-09-29"
6+URL = "https://compactmag.com/article/the-dream-of-digital-homesteading"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/compactmag.png"
8++++
9+
10+Geoff Schullenberger attends Assembly 2022 and chronicles his impressions and thoughts.
content/articles/2022-10-04_a-more-beautiful-computer.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "User Error: A More Beautiful Computer"
3+publication = "Spike Art Magazine"
4+author = "Adina Glickstein"
5+date = "2022-10-04"
6+URL = "https://www.spikeartmagazine.com/?q=articles/user-error-more-beautiful-computer"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/spike-logo-text.jpg"
8++++
9+
10+From Dimes Square to the Network State, new frontiers are in the making. Adina Glickstein attends Urbit Assembly and considers the politics of tech-augmented exit.
11+
content/articles/2022-10-13_my-weekend-with-the-martians.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "My Weekend With the Martians"
3+publication = "Astra"
4+author = "Ruby Sutton"
5+date = "2022-10-13"
6+URL = "https://astra-mag.com/articles/my-weekend-with-the-martians/"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/astra.png"
8++++
9+
10+At the Assembly, a conference of Urbit denizens, Ruby Sutton discovers a community of eccentrics who dare to dream of a different internet.
content/articles/2022-10-23_three-things.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Three Things #40: October 23, 2022"
3+publication = "Three Things"
4+author = "Lane Rettig"
5+date = "2022-10-23"
6+URL = "https://rettig.substack.com/p/three-things-40-october-23-2022"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/3things40.jpg"
8++++
9+
10+Lane Rettig outlines three unique aspects of Urbit in an attempt to answer the eternal question "What is Urbit?"
content/articles/2023-02-20_trailblazing-urbit-startup-makes-earth-shaking-acquisition.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Trailblazing Urbit Startup Makes Earth Shaking Acquisition"
3+publication = "Globe Newswire"
4+author = "Globe Newswire"
5+date = "2023-02-20"
6+URL = "https://www.globenewswire.com/en/news-release/2023/02/20/2611391/0/en/Trailblazing-Urbit-Startup-Makes-Earth-Shaking-Acquisition.html"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/globe-newswire.jpeg"
8++++
9+
10+Holium Corp closes $2.9 million in seed funding and acquires Third Earth in record pace.
content/articles/2023-05-10_urbit-a-network-older-and-weirder-than-bitcoin.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Urbit, a Network Older and Weirder Than Bitcoin, Finally Turns Toward Growth"
3+publication = "Coindesk"
4+author = "Bradley Keoun"
5+date = "2023-05-10"
6+URL = "https://www.coindesk.com/tech/2023/05/10/urbit-a-network-older-and-weirder-than-bitcoin-finally-turns-toward-growth/"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/coindesk.jpg"
8++++
9+
10+The peer-to-peer network started in 2002 says it's taking on "MEGACORP," much in the same vein as many blockchain networks. A bit more fun are the "secret code names" that users are assigned.
content/bitcoin.mdnew file+125
@@ -0,0 +1,125 @@
1++++
2+title = "Bitcoin Development on Urbit"
3++++
4+
5+### Overview
6+
7+Urbit OS currently ships with our Bitcoin wallet, %btc-wallet, released in 2021,
8+and our Lightning implementation, %volt, is almost ready for live use on the network. Several integrations with the app ecosystem are planned immediately following its release, including subscription publishing, social payments, and more.
9+
10+**The Urbit Advantage**
11+
12+- Composability: Modular userspace applications expose a consistent API format to each other locally and over the network, making seamless integration of Lightning payments, Taro assets, and other protocols easy
13+- Networking and identity: Exactly-once message delivery, NAT traversal, and E2E encryption come built into Urbit's P2P protocol, and Urbit identities are sybil-resistant, human-readable network addresses bound to BIP32 extended public keys
14+- Efficient, secure development: Urbit OS is strictly typed and purely functional, and apps have reproducible builds on all client machines, removing much of the complexity, risk, and pain points from development
15+
16+**Getting Involved**
17+
18+Interested in contributing to or supporting Bitcoin development on Urbit? GitHub repos for individual projects and information on the Urbit Foundation grant program are linked below, and dedicated Urbit groups and Bitcoin node operators on Urbit are listed in the Community section. You can also reach out to current contributors ~tondes-sitrym and ~pindet-timmut on Urbit or at urbitcoin@protonmail.com.
19+
20+### Wallet
21+
22+Urbit's Bitcoin wallet consists of two agents: %btc-provider, which communicates with an external full node; and %btc-wallet, which handles transaction generation and signing, and uses a %btc-provider instance (on the same ship or elsewhere on the Urbit network) to broadcast transactions and receive data from the Bitcoin network.
23+
24+Wallet users can receive payments using the xpub associated with their Urbit ID, allowing Bitcoin payments to be sent between ships with a persistent, human-readable network address without compromising on-chain privacy.
25+
26+**Resources**
27+
28+GitHub
29+
30+- Agents: [https://github.com/urbit/urbit/tree/master/pkg/bitcoin](https://github.com/urbit/urbit/tree/master/pkg/bitcoin)
31+- UI: [https://github.com/urbit/urbit/tree/master/pkg/btc-wallet](https://github.com/urbit/urbit/tree/master/pkg/btc-wallet)
32+- Provider utilities: [https://github.com/urbit/urbit-bitcoin-rpc](https://github.com/urbit/urbit-bitcoin-rpc)
33+
34+Writeups
35+
36+- Grant proposal: [https://urbit.org/grants/bitcoin-full-node-provider-and-wallet](https://urbit.org/grants/bitcoin-full-node-provider-and-wallet)
37+- Architecture document: [https://gist.github.com/jalehman/e0c91071427ca4c349c0673f376945cb](https://gist.github.com/jalehman/e0c91071427ca4c349c0673f376945cb)
38+- Provider setup guide: [https://subject.network/posts/pi-fullnode-urbit/#bitcoind](https://subject.network/posts/pi-fullnode-urbit/#bitcoind)
39+
40+
41+**Continuing Work**
42+
43+The current %btc-wallet implementation is not a modern BIP-157/158 light client. While users who depend on another ship's %btc-provider/full node for communication with the Bitcoin network do not risk loss of on-chain funds, their lack of visibility on the network will be more problematic for those also using it with Lightning. Funding is available for developers interested in contributing: reach out to the Urbit Foundation, ~tondes-sitrym on Urbit, or urbitcoin@protonmail.com.
44+
45+### Lightning
46+
47+Volt, Urbit's Lightning implementation, like our Bitcoin wallet consists of two agents: %volt, the primary agent that manages channels, payments, invoices, and chain monitoring; and %volt-provider, which connects to an external LND node for handling payments with endpoints outside the Urbit network.
48+
49+All Volt nodes will run %volt, and be able to operate channels with Urbit peers without maintaining an LND instance or depending on another ship that does. To transact with non-Urbit Lightning peers, and in the short term (see below) to perform multi-hop payments inside Urbit, they will need to open a channel with a node that uses %volt-provider to connect with LND. Chain monitoring likewise requires connecting to a local or remote %btc-provider agent (see Wallet above). For more details on the network architecture, see the grant proposal linked below.
50+
51+Volt implements BOLTs 2, 3, 5, and 11, and in the near future will add onion routing (variants on BOLTs 4 and 7). Because %ames, Urbit's networking module, already handles transport, guarantees required message delivery properties, and furnishes persistent, unique 'domain names', implementation of BOLTs 1, 8, and 9 is unnecessary for Volt nodes.
52+
53+Beta release of Volt is planned for the end of 2022, and additional features including multi-hop/onion routing implementation are proposed for completion by mid-2023.
54+
55+**Resources**
56+
57+GitHub: [https://github.com/dasrun-fadben/volt/tree/on-chain](https://github.com/dasrun-fadben/volt/tree/on-chain)
58+
59+Initial grant proposal and spec: [https://urbit.org/grants/volt-lightning-on-urbit](https://urbit.org/grants/volt-lightning-on-urbit)
60+
61+Proposal for further work: [https://urbit.org/grants/lightning-development](https://urbit.org/grants/lightning-development)
62+
63+**Continuing Work**
64+
65+The primary element currently missing from Volt is onion routing of multi-hop payments for full privacy and efficiency of payments to and from nodes that don't also operate LND. This has been partially specified in the second proposal linked above: funding and collaborators are available for this as well as work described there on application integrations, submarine swaps, and more, so interested developers should take a look and get in touch.
66+
67+### Roadmap
68+
69+**2022**
70+
71+- *Volt Beta Release*
72+Final work on channel sweeps, remaining safety checks, and UI development is currently ongoing and expected to be complete by EOY 2022.
73+
74+**2023**
75+
76+- *Initial Ecosystem Integrations*
77+ - Submarine swaps: Implementation of the PeerSwap protocol, fallback use of the Loop API, and UI targeted at merchant use-cases. Funded, expected completion in spring 2023.
78+ - Apps: Integration of Lightning subscription and one-time paygates into Groups, social payments and %volt-provider discovery with %pals, and app tipjar module. Specified and proposed for grant funding.
79+- *Lightning Routing*
80+Payments with multiple intra-Urbit hops and via multiple %volt-provider channels are the last remaining component for full-featured and private payments with Volt. Specified and proposed for grant funding.
81+- *Wallet Improvements*
82+Work on feature, security, and UI upgrades for the Bitcoin wallet and node provider, aimed at making the application a full-featured and BIP157/158-compliant light client, should begin before EOY 2023.
83+
84+**Future**
85+
86+- *Taro Implementation*
87+Implementation of Taproot Asset Representation Overlay, with an initial focus on using nonfungible Taro assets to represent credentials, permissions, and reputation of Urbit identities.
88+- *Atomic Streaming Payments*
89+ - Integration of Volt payments with streaming apps like %radio and the Holium WebRTC client via HTLC-DASH or similar implementation.
90+ - Generic protocol for non-media pay-to-stream data
91+
92+### Grants
93+
94+The Urbit Foundation operates a grant program aimed at new Urbit developers, network public goods, and community development. Work on the Bitcoin wallet, Lightning implementation, and submarine swaps for Volt (Urbit Lightning) users all has received funding from UF, and interesting non-technical proposals with social value to the network are also considered.
95+
96+Grants homepage: [https://urbit.org/grants](https://urbit.org/grants)
97+
98+Past Bitcoin-related grants
99+
100+- [https://urbit.org/grants/bitcoin-full-node-provider-and-wallet](https://urbit.org/grants/bitcoin-full-node-provider-and-wallet)
101+- [https://urbit.org/grants/volt-lightning-on-urbit](https://urbit.org/grants/volt-lightning-on-urbit)
102+- [https://urbit.org/grants/lightning-development](https://urbit.org/grants/lightning-development)
103+
104+## Bitcoiners on Urbit
105+
106+### Groups
107+
108+Urbitcoiners: ~pindet-timmut/urbitcoiners
109+
110+### Providers
111+
112+**Bitcoin Full Nodes**
113+
114+~tirrel
115+~zod
116+
117+**Lightning Nodes**
118+
119+~tondes-sitrym
120+~bosdys
121+
122+### Guides
123+
124+Running %btc-provider with a full node on Raspberry Pi: [https://subject.network/posts/pi-fullnode-urbit/](https://subject.network/posts/pi-fullnode-urbit/)
125+
content/blog/aesthetic-culture-1.md+1−1
@@ -5,7 +5,7 @@ date = "2020-11-11"
55
66[extra]
77description = "One of the most exciting things about Urbit is the aesthetic and design around it, developed partly by Tlon (through the design of Urbit itself) and partly by the community (by producing great Urbit art)."
8−author = "Nikolai Mallett"
8+author = "~nartes-fasrum"
99ship = "~nartes-fasrum"
1010image = "https://media.urbit.org/site/posts/essays/help-the-environment.jpg"
1111+++
content/blog/agency-daos.mdnew file+110
@@ -0,0 +1,110 @@
1++++
2+title = "The Dream of the Agency DAO"
3+date = "2022-11-04"
4+description = "As creative studios and agencies struggle for more creative freedom, DAOs and tokenization will surely take a more central role in the marketing and branding industries. Decentralization offers such entities benefits that could fundamentally reshape creatives’ relationships with clients—reducing layers of inefficiency and anti-creative incentives."
5+
6+[extra]
7+author = "Isaac Simpson"
8+ship = "~mogmet-tadnem"
9+image = "https://storage.googleapis.com/media.urbit.org/blog/skybanner.jpg"
10++++
11+
12+![Image](https://storage.googleapis.com/media.urbit.org/blog/skybanner.jpg)
13+
14+
15+Chris Callahan runs an independent brand strategy agency called [Visitor](https://visitor.agency/). Visitor wrote the line that [emblazoned](https://astra-mag.com/articles/my-weekend-with-the-martians/) the sky over the parking lot that housed Urbit Assembly. Its work focuses on Web3 blue chips and up-and-comers: dev marketing, notoriously one of the toughest niches in the branding world.
16+
17+“Devs are very sensitive to puffery and cringe,” says Callahan. “Traditional tactics like headlines and manifestos fall flat. Clarity and vision are much more important because they showcase the benefit as well as a long term potential for use.”
18+
19+Why? Because developers eschew sales. If something is good, it will rise to the top without the help of annoying salespeople. The thing is, marketing-world creatives usually agree—we’re just bogged down by salespeople of our own. So we, like devs, yearn for the day when decentralization will save us from the social climbers and “connectors” that suck up all the oxygen.
20+
21+Enter the Agency DAO. The idea—a creative agency that solicits work, receives clients, hires creatives, and makes decisions all on the blockchain—is oft-discussed because it appeals to the crunchy, anti-establishment vibe at the core of every major ad agency. A trustless, leaderless creative community where everyone has equal voice and the best creative rises naturally to the top? The dream of the ‘90s come true!
22+
23+Unfortunately, decentralization in the ad world currently occupies much more podcast time than reality.
24+
25+## Creative by Committee
26+
27+But there are some actual attempts at making the Agency DAO a reality. Koto, a top creative agency known for creating the AirBNB brand, tried it with Web3 brand Polkadot. [It pit two pitches against each other to determine the future direction of the Polkadot brand by vote](https://vote.polkadot.network/). It used a quadratic voting via Snapshot to deliver the will of the Polkadot network to four “multisig curators” who executed the vote on chain.
28+
29+While the experiment worked, it also revealed the shortcomings of the blockchain’s ability to guide creative decisionmaking.
30+
31+“To organize Polkadot token holders who wanted to participate and create the voting parameters took very long,” says Callahan. “To have the wisdom of crowds decide on two design elements was an exemplary concept for Polkadot to own. The question is, did it push the work? Or was its value in consensus alone?”
32+
33+Quadratic voting is cool, but the creative process is long and complicated. Stakeholders chose between option A and option B. At the end of the day, that doesn’t feel like a significant innovation, especially if the vote isn’t even actually happening on chain. Rebranding sprints typically take around 3 months. This process took 11. Sure, it was a good way for Koto to play ball, but it wasn’t much more than that.
34+
35+Agency DAOs face the same central problem as ordinary DAOs, which can be summed up thusly: every decentralizing force is too costly, and every cost compromise moves the system back towards traditional hierarchies. The nature of creative work even further stymies the theoretical Agency DAO. Creative products almost always suffer when anti-hierarchical principles are put in place. As David Ogivly famously said,
36+
37+_“Some agencies pander to the craze for doing everything in committee. They boast about ‘team-work’ and decry the role of the individual. But no team can write an advertisement, and I doubt whether there is a single agency of any consequence which is not the lengthened shadow of one man.”_
38+
39+So this leaves us with the question of how exactly the DAO model can help creative agencies, and what such an organization might look like, and how Urbit can help. There are roughly three paths: 1) Project Bountification 2) Talent Retention 3) Idea Valuation.
40+
41+## Project Bountification
42+
43+In the Mad Men era, a few Agencies of Record (AORs) dominated the advertising world. These massive whales took every cent of a given big brand’s yearly advertising budget and charged a simple 15% premium on all media (e.g. radio time, TV time) purchased. A very simple and very profitable system, [now long gone](https://www.genedelibero.com/the-agency-of-record-the-shift-is-on-to-specialized-agencies/).
44+
45+Today, big brands typically have many agencies—sometimes hundreds—each with a different specialty, and each fighting for their own share of the budget. I’ve been in rooms with representatives from no less than 10 agencies—digital, DEI, experiential, CSR, influencer, etc—all pitching ideas for the same holiday campaign, and all surely billing upwards of $100/hour per person to do so.
46+
47+This sounds nice for agencies, but actually it isn’t—instead of focusing on the creative work, they must dedicate their energy towards constantly re-pitching themselves to the client and fighting with procurement people on rates. The managerial class types who control the budgets care a lot less about the quality of the creative than whether you remembered their dog’s birthday.
48+
49+Crypto could provide a solution to modern agencies’ woes by creating a flatter system for project acquisition; adopting the sort of decentralized bounty system some devs already use for Web3 projects.
50+
51+“Bounties are great,” says Callahan. “Big agency players should popularize them. I feel like if there's a way to do an on-chain bounty with select members who either hold a special token that allows participation on key briefs, that would help a lot.”
52+
53+How would such a system work? First, a brand issues a bounty for a project for work it needs done. Luckily, this basically already happens in advertising, it’s called a request for proposal, or RFP. The only difference here is instead of RFP acquisition and response being 90% schmooze-fest and 10% creativity/pitching prowess, it’s a lot more like what you’ve seen on Mad Men: the client’s RFP passes trustlessly to the bold creatives who spend many drunk, sleepless nights coming up with genius ways to knock their socks off.
54+
55+“A brand issues a bounty for a stunt activation that, for example, educates the world on the psychological benefits of calm computing,” Callahan explains. “The members of Agency DAO approve it, and create their own bounty for creatives inside the DAO. Bounties burn after 10 days. Ideas submitted and sent to client in the manner set by DAO.”
56+
57+Once the job is awarded, the chosen agency will continue this pattern, effectively removing the “account guy” layer—the sales-y middle people abhorred by both creatives and devs alike—and returning more focus to creativity.
58+
59+## Talent Retention
60+
61+“Professional creative” industries, e.g. marketing, branding, etc, suffer from turnover rates orders of magnitude higher than the industries they serve. Being a creative is both kind of awesome, because a new gig is never too far away, and also scary, your current gig reliant on the slightest whims of the client.
62+
63+This means that the market for creative talent in the form of copywriters, designers, art directors, animators, producers, editors, etc, is always choppy and competitive. Staffing sucks—it’s difficult to evaluate the quality of someone’s work until you’re actually working with them, because creatives stuff their portfolios with successful projects they’ve barely touched. Beyond that, now bloated Web2 lowballers like Fiverr and Upwork bottom out the market with garbage time labor that even the biggest brands still somehow fall for. Another great opportunity for Web3 disruption.
64+
65+The Agency DAO model provides permanence. Currently, some independent agencies offer equity packages that take a long time to vest, and are only ever worth anything if the agency sells. Owning fungible tokens from day one is a much better way to incentivize both work quality and retention.
66+
67+DAOs also offer flatter and more collaborative atmospheres, which creatives at least ostensibly want.
68+
69+“There’s total transparency of who works on what. Better collaboration between members, meaning happier, more fulfilled workers. Awards will be more meaningful and accurate,” says Callahan. “Plus, the value of your tokens naturally increases or decreases based on your performance. Just by getting hired at a successful DAO you can already be doing well.”
70+
71+Finally, a system that allows democratized voting on creative products, as opposed to traditional [Hype Dad aristocracies](https://thecarousel.substack.com/p/vibe-shift-to-destroy-marketing-world), could actually foster more Darwinistic environments where the best creative has a higher chance of rising to the top.
72+
73+“Eventually group preference will select one creative over others; causing repeat elections of the same member,” says Callahan. This could occur on both the agency level—removing the Hype Dad problem, e.g. lazy incumbents making lame decisions. “There's a sort of Darwinism that is created that can determine benefits or even redundancies for those not pulling their weight or who simply aren't as talented as others.”
74+
75+## Idea Valuation
76+
77+The creative industries are perhaps the only example of a field in which the artists retain no intellectual property right for their ideas. This is why advertising creatives make so much money—an advertiser can milk a good idea for decades and we’ll never see a dime.
78+
79+The tokenization inherent to the DAO model opens up several possibilities for valuing ideas in new ways that behave more like copyright.
80+
81+“The basic thought now is starting something I’m calling General Idea; pre-created, white label ideas based on research of real creative problems that need fixing,” says Callahan. “We NFT the ideas, sell them to clients. They make them or they resell that idea to other clients or agencies. That monetary markup value on the idea trickles down the original creator. More democratic way to share ideas and defend their ownership when they’ve been recorded on the blockchain.”
82+
83+This sort of blockchain-based soft copyright is one way to value an agency’s DAOs. Another, simpler way, is to sell NFTs or NFT-related independent creations of the agency itself. Art collective/creative agency [MSCHF](https://mschf.xyz/), for example, makes its money both via brand deals and also a la carte meme-to-merch drops. Agencies with a certain amount of clout could easily tokenize the clever side projects of its creatives—making it far less reliant on client deals and more able to capitalize on its creative prowess.
84+
85+“Pool Suite [another creative studio] does a great job of being a creative company that happens to make NFTs of music and general drops and stuff,” says Callahan. “They're a studio first and then a blockchain player after. I'd still consider them a ‘diet-DAO.’”
86+
87+[Édouard Urcades](https://fabled-faster.tlon.network/writing/stars) has designed interfaces for Tumblr and IBM, and currently serves as a design lead at Tlon. His project Structure is a “cork board” for creative projects on Urbit—sort of a “mercenary guild,” for UX/UI designers looking for work. Structure is run by a gnosis safe wallet operated by its 12 members. Beyond serving as a “soft on-ramp for Urbit-related design labor,” Ed plans to monetize Structure by selling Urbit merch designed in-house, both NFT and IRL.
88+
89+## How Urbit Can Help
90+
91+The three categories discussed above—project bountification, talent retention, idea valuation—present theoretical frameworks for the Agency DAO. However, the shortcomings of current DAO infrastructure and governance make them largely impossible. Enter Urbit.
92+
93+The creative industries rely almost entirely on reputation—so any Agency DAO without permanent pseudonymous ID is dead in the water.
94+
95+“Goodby Silverstein and Partners, for example, is widely regarded as one of the best ad agencies out there,” says Callahan. “When a big name in the creative industry goes to work there, the reputation of Goodby Silverstein increases.”
96+
97+Urbit IDs let you maintain your creative and working reputations while operating within a self-owned ecosystem that can’t be deleted. Beyond that, Urbit’s design-forward OS selects for self-expression in a way that no corporate-owned platform could.
98+
99+
100+“The sigil itself is its own design feature,” says Callahan.
101+
102+Simply put, running an Agency DAO on Discord and Google Docs would be fundamentally unserious. It’s one thing for a traditional agency to use Web2 products as _tools_ for its creatives. It’s quite another for Web2 products to be the only connection the agency has with its creatives outside of the blockchain.
103+
104+Recruitment, ideation, project sharing, and even simple chat aren’t possible on Web3 without something like Urbit to tie it all together. Sure, you could get a bunch of anonymous creatives together on a shared Figma, but there will be zero accountability and likely low participation. Whereas Urbit—particularly Holium’s forthcoming Realm—brings Urbit ID into a decentralized, permanent environment that connects members P2P, and allows on-chain transactions without leaving Urbit. All while maintaining permanent IDs.
105+
106+As creative studios and agencies struggle for more creative freedom, DAOs and tokenization will surely take a more central role in the marketing and branding industries. Decentralization offers such entities benefits that could fundamentally reshape creatives’ relationships with clients—reducing layers of inefficiency and anti-creative incentives. However, a decentralized ID layer like Urbit is needed before the Agency DAO can be practically attempted.
107+
108+–
109+
110+*Isaac Simpson is a Los Angeles based writer and the founder of the marketing agency [WILL](https://willtheagency.com/). You can read his work on his substack [The Carousel](https://thecarousel.substack.com/).*
content/blog/ares.mdnew file+51
@@ -0,0 +1,51 @@
1++++
2+title = "Ares"
3+date = "2023-06-26"
4+description = "A light technical description of Ares, the new Urbit runtime"
5+
6+[extra]
7+author = "Noah Kumin"
8+ship = "~librex-dozryc"
9+image = "https://storage.googleapis.com/media.urbit.org/blog/ares-header.png"
10++++
11+
12+![Image](https://storage.googleapis.com/media.urbit.org/blog/ares-header.png)
13+
14+## What is Ares?
15+
16+Ares is a new Urbit runtime that will be much faster and manage a much larger amount of data than previous versions of the runtime. Those new to Urbit commonly ask if they will be able to host photos and videos on their Urbit ships. Ares—a joint project from the Urbit Foundation, Tlon, and Zorp—sets the stage for us to be able to answer, simply, “Yes.” Ares is still a work in progress, but we expect to see the new binaries rolled out later this year. There are three components to the project. Let’s talk about them one by one.
17+
18+## 1. Code Generation
19+
20+Modern CPUs are extraordinarily fast. But until now your Urbit hasn’t been able to take full advantage of this fact. One way to conceptualize the problem is to imagine a train that is only able to go as fast as a track-worker can lay down track for it. In this analogy, your CPU is the train, and the track-worker is the Urbit runtime. The aim is to have large sections of track laid down ahead of time. Ares includes a codegen system that compiles Nock, Urbit’s assembly language, to machine code that the CPU can predict well.
21+
22+This system addresses what has until now been a problem: Nock is meant to invoke other code in a given Urbit computer’s “subject.” Or, in more common parlance, in the computer’s “state.” Your state changes with every new message your Urbit computer sends and receives, or with any new event in any app. That makes it hard to make the resulting machine code run fast, since the CPU needs to read from the subject while it’s running in order to figure out what machine code will be run next.
23+
24+The new code generation process in Ares solves this problem by using a system which the developers have called “subject knowledge analysis.” What does this mean? By analyzing how an Urbit subject might change over the course of a Nock computation, Ares will learn about the subject's tree shape and about its data dependencies (*i.e.*, the way that later parts of the computation depend on earlier parts of the computation). This allows those parts of the subject which are known at the time of compiling Nock to machine code to remain known at later points in the computation.
25+
26+To go back to our metaphor of train tracks, this is what allows the “track” to be laid down ahead of time. This set of known parts of the subject typically includes Nock formulas stored in [cores](https://developers.urbit.org/guides/core/hoon-school/F-cores#cores). This allows the resulting machine code to use direct jumps to perform Nock function calls. Without this “subject knowledge analysis,” the CPU would have had to perform an “indirect jump” by calculating the location to which a later instruction would jump. Now your computer’s CPU can jump directly to where it’s supposed to go.
27+
28+## 2. 2stackz Noun Allocator
29+
30+Ares will make use of what we’re calling the *2stackz noun allocator*. With the advent of Ares, your Urbit will be a virtual machine with two stacks and no heap. What does this mean? Traditionally, a program has a *stack* and a *heap*. The stack is a linear data structure within a program used for the program’s execution. The heap is a less structured region of memory that is used for storing large pieces of data or data that you want to keep around for a while without taking up space in the stack. However, the heap is slower, because its system for allocating memory is less orderly. (Imagine, say, trying to find a specific pair of socks in a heap of clothing.)
31+
32+Ares recognizes that because Nock is much more constrained than most languages, the Urbit runtime doesn’t actually need a heap. Instead you can take the function call stack and split it in two. The top of either stack can then be used as a little temporary heap. Whenever a function executes, you copy the data that gets returned from one stack to the other. And all the intermediate products that get created when running that function (*i.e.*, other functions that got called by the initial function) sit there as *garbage* (unwanted or unused data) in between the two stacks. But you don’t have to do the same sort of bookkeeping—tracking and updating these values—that you would have to do with a heap.
33+
34+Every piece of data in your Urbit computer is a noun. A noun is an atom (a positive integer or zero) or a cell (a pair of nouns). Before Ares, both allocating and freeing a noun in the Urbit runtime were processes that took a lot of time. (To *allocate* a noun is to put that noun in memory and to *free* it is to tell your urbit that you don’t need it any more.) Ares should make both of these processes much faster. This is good news because the Urbit runtime allocates nouns (particularly pairs of nouns, known as cells) like nobody’s business.
35+
36+## 3. Persistent Memory Arena
37+
38+Ares’s Persistent Memory Arena is for managing large amounts of data within your urbit in such a way that your urbit does not get slow. If you have terabytes of data within your Urbit, you can only have a very small subset of that within your hardware’s RAM at a given time. The rest of that data is going to have to live on disk—the section of your hardware that is more capacious but takes more time to access.
39+
40+To deal with this fact, your motherboard moves data back and forth between RAM and disk depending on what data needs to be accessed at a given time. This is known as *paging*, because it does so one *page* (usually four kilobytes) at a time. Traditionally operating systems will handle paging for you, but they do it in a generic way. The Persistent Memory Arena is designed specifically for managing Urbit's single-level store.
41+
42+A *single-level store* means that there’s no distinction in the operating system between data that lives in RAM and data that lives on disk. Instead of having two levels from which you can access data, you only have one, and the system itself manages which parts of the data are in RAM and which are in disk. The Persistent Memory Arena is an optimization for handling a large amount of data in a single level store. It is for nouns that persist between computations. Using the PMA, your urbit’s state can grow large without being hemmed in by the limitations of your hardware’s RAM.
43+
44+
45+## Updates and Links
46+
47+You can find the Ares GitHub repository [here](https://github.com/urbit/ares). The technical proposal is [here](https://github.com/urbit/ares/blob/status/docs/proposal/proposal-nock-performance.md). Check back at the Urbit Google Groups [listserv](https://groups.google.com/a/urbit.org/g/dev/), the [@zodisok](https://twitter.com/zodisok) Twitter account, and the Urbit Foundation [group](https://tlon.network/lure/~halbex-palheb/uf-public) for updates about the upcoming release.
48+
49+–
50+
51+*Noah Kumin is the founder and editor in chief of the [Mars Review of Books](https://marsreview.org/).*
content/blog/august-2022-grants-program.mdnew file+73
@@ -0,0 +1,73 @@
1++++
2+title = "August Grants Program Review"
3+date = "2022-08-30"
4+description = "The completion of the first cohort of Hoon School Live and the following App School Live program minted dozens of capable new Hoon developers. These developers are completing applications, closing out bounties, and putting together proposals at a rapid pace, with more to come as Assembly 2022 draws near."
5+[extra]
6+author = ""
7+ship = "~sarlev-sarsen"
8+image = "https://storage.googleapis.com/media.urbit.org/blog/b52.jpg"
9++++
10+
11+![Image](https://storage.googleapis.com/media.urbit.org/blog/b52.jpg)
12+
13+# Completed Grants
14+
15+Recently completed grant projects include Urbit micro-blogging, Hoon-native Discord bridging, Urbit’s first arcade-style game, Port application improvements, Ethereum bookkeeping and eth-provider infrastructure.
16+
17+* [Trill](https://urbit.org/applications/~sortug/trill) and sister application [Urbit Feed Aggregator](https://urbit.org/applications/~sortug/ufa) give you a way to escape from Twitter’s algorithms while still being able to share your shower thoughts with your followers.
18+* [Faux](https://urbit.org/applications/~midsum-salrux/faux) is a transformation of the python-based Urbit to Discord bridge, turning it into a Hoon native app and offering a front-end that takes you through the setup experience, letting you to bring your Discord friends a little taste of Urbit.
19+* [Slam](https://urbit.org/applications/~hanfel-dovned/slam), everyone’s favorite new arcade game, integrates with [Gora](https://urbit.org/applications/~dalten/gora) and [pals](https://urbit.org/applications/~paldev/pals), utilizing a mechanism whereby the number of gorae held by your pals will influence the way your game is played.
20+* The [Ethereum Provider](https://urbit.org/grants/eth-provider) grant gets the network a step closer to decentralized Ethereum access, particularly for those who don’t wish to rely on an infura node.
21+* A bounty for [Port Maintenance](https://urbit.org/grants/port-maintenance) delivered iterative improvements to the Port application for those who run their ships on a local machine.
22+* And Quartus delivered [Books](https://urbit.org/applications/~doller-doller-rabsef-bicrym/books), an Ethereum address and transaction manager for you to easily append notes and memos to your on chain transactions without having to rely on a third party (as a friendly reminder, [Urbit is not yet a secure environment so please be careful](https://twitter.com/pcmonk/status/1563634078779592709?s=20&t=FN7VVjMdjyIdukSvtg5_7g) what information you store on your ship).
23+
24+
25+# Proposals
26+
27+As the above grants wrap up, more grants are coming to life. Proposals are community generated and selected projects which offer contributors the space to build whatever tooling or applications they believe Urbit needs. Each of the following projects was funded in August:
28+
29+
30+
31+* [Herd](https://urbit.org/grants/herd) - Dependency management for Citadel
32+* [Full Stop](https://urbit.org/grants/full-stop) - A menstruation tracker for Urbit
33+* [Peat](https://urbit.org/grants/peat) - Urbit’s first backup utility
34+* [Quorum](https://urbit.org/grants/quorum) - A clone of stack exchange on Urbit
35+* [Gather](https://urbit.org/grants/gather) - an Urbit native meetup tool
36+* [Olif](https://urbit.org/grants/olif) - Olfactive rendering of Urbit address space
37+* [Urbit Interface Framework](https://urbit.org/grants/urbit-interface-framework) - Framework for alternative web browser interface
38+* [Whom](https://urbit.org/grants/whom) - A profile and contacts manager
39+
40+
41+# Apprenticeships
42+
43+Apprenticeships are also bringing opportunities for hands-on developer education and enabling seasoned contributors to share knowledge through real world projects. And contributors get to earn address space as they learn the stack and grow their network.
44+
45+Three new apprenticeships began in August:
46+
47+
48+
49+* [Loom Pointer Compression](https://urbit.org/grants/loom-pointer-compression) - Work to double the size of the loom
50+* [Build a UI for Volt](https://urbit.org/grants/volt-ui) - An interface for %volt, Urbit’s lightning wallet agent
51+* [Vere Profiling](https://urbit.org/grants/profiling) - Uncovering and visualized performance bottlenecks in the runtime
52+
53+
54+# Bounties
55+
56+August also brings with it the assignment of previously open bounties to developers looking to grow their portfolio of Urbit projects. Many of bounties that found contributors are a part of [Holium’s App Dev Summer](https://www.youtube.com/watch?v=dHyzH09QaZQ), and are slated to be completed by Assembly in Miami:
57+
58+* [Minesweeper](https://urbit.org/grants/minesweeper) - A classic desktop game, now natively in hoon
59+* [Abacus](https://urbit.org/grants/abacus) - A basic calculator app with the ability to convert units
60+* [Chronicle](https://urbit.org/grants/chronicle) - A news app that links articles from group channels
61+* [Lexicon](https://urbit.org/grants/lexicon) - A simple dictionary app with custom definitions for a group
62+* [Chess Improvements](https://urbit.org/grants/chess-bounty) - An enhanced chess experience with timing and ELO servers
63+
64+Even with all the claimed bounties, there remain a variety of projects which currently seek developers. Check out the following grants and apply to those that fit your skills and interests:
65+
66+
67+* [Trove](https://urbit.org/grants/trove) - A group file sharing tool
68+* [Urbit Native Ethereum wallet](https://urbit.org/grants/eth-wallet) - An ETH wallet for Urbit maxis
69+* [UrbitSwap](https://urbit.org/grants/urbitswap) - An Urbit-hosted Uniswap instance
70+* [Tune slaw/scot jets](https://urbit.org/grants/slaw-scot-jets) - Tuning jets for better performance
71+* [New Mars Persistent Memory](https://urbit.org/grants/persistent-memory) - Development of a persistent memory arena
72+
73+Have a project that you want to help fund and think would make a good bounty? Want to propose a project about which you are passionate? Looking for a mentor to better learn a part of the Urbit ecosystem? For more information on current projects and opportunities from the Urbit Foundation’s grant program, visit [urbit.org/grants](/grants) or reach out to ~sarlev-sarsen to get involved.
content/blog/foss-1.mdnew file+64
@@ -0,0 +1,64 @@
1++++
2+title = "Urbit's Open Source Culture, Part I"
3+date = "2023-05-31"
4+description = "How did Urbit cultivate a unique open source software culture? Let's take a look at how we got to where we are today."
5+
6+[extra]
7+author = "N E Davis"
8+ship = "~lagrev-nocfep"
9+image = "https://upload.wikimedia.org/wikipedia/commons/a/a9/SR71_factoryfloor_SkunkWorks.jpg"
10++++
11+
12+![](https://upload.wikimedia.org/wikipedia/commons/a/a9/SR71_factoryfloor_SkunkWorks.jpg)
13+
14+> “Open source is an intellectual property destroyer. I can't imagine something that could be worse than this for the software business and the intellectual-property business.” (Jim Allchin, Microsoft executive)
15+
16+A founder's personal enquiry into the foundations of practical computing grew into a skunkworks startup to build an alternative basis for principled computing, and has now evolved into a burgeoning open source platform and community.
17+
18+- [Moron Lab, “Maxwell's equations of software (Nock)” (~2010.1.9)](https://moronlab.blogspot.com/2010/01/nock-maxwells-equations-of-software.html)
19+- [Moron Lab, “Urbit: functional programming from scratch” (~2010.1.13)](https://moronlab.blogspot.com/2010/01/urbit-functional-programming-from.html)
20+
21+How did Urbit cultivate a unique open source software culture? Let's take a look at how we got to where we are today.
22+
23+Open source culture really got going in the 1980s with the restrictive Unix licensing scheme and the consequent publication of the GNU software tools. With the marriage of GNU to Linux ([“I'd like to interject for a moment”](https://copypastatext.com/id-just-like-to-interject-for-a-moment/)), a full stack, from the bare metal to the end user, was possible. Usenet and early Internet forums furthermore encouraged interested developers to start contributing actively.
24+
25+The ethos of open source software drew on a number of sources, from William Gibson's _Neuromancer_ trilogy to “A Cypherpunk's Manifesto.” Those involved were often motivated by a healthy distrust of proprietary software. The big break for open source software (OSS) came with the [Unix ownership lawsuits](https://en.wikipedia.org/wiki/Unix_wars), which gave GNU/Linux a chance to break into the bigtime for systems software. The [2001 case against Microsoft](https://en.wikipedia.org/wiki/United_States_v._Microsoft_Corp.) as a monopoly lent further credence to the open source mandate.
26+
27+During this time, Urbit began life as a personal dissertation, in a sense, to derive a minimalist practical set of computing expressions as a combinator calculus. The early concepts that became part of Urbit, such as kelvin versioning and Maxwellian code, show up during its first decade. Nock was not open source for two reasons: the founder's conviction that as software it was already public domain, and the fact that there was no one yet to collaborate with.
28+
29+It was about a decade before Tlon was started as a small bespoke programming house to work on the esoteric project of defining something usable on top of the minimalist Nock specification. No one knew about Urbit besides some blog readers, and unless you worked in or next to Tlon you had basically zero chance of following the project via software alone.
30+
31+Early Tlon did a fairly good job of putting their software out there, but the documentation and nomenclature were considered obscurantist and the project was described as performance art or a deliberate wild goose chase. These combined to make Urbit appear fairly opaque, despite open development using GitHub and the liberal MIT license. System components like Nock and Arvo were declared public domain or liberally licensed.
32+
33+To this point (let's say 2019), Urbit was by license and by code an open source project, but had a reputation for being basically impossible for an outsider, even one with a fair amount of coding experience, to really figure out what's going on without serious handholding from the core devs. (Nor is this inappropriate for a small startup at this stage—it simply is the way most nominally OSS projects function.) However, the mystery engaged others beyond Tlon to brave the wilds and figure out what this Urbit project was all about.
34+
35+Urbit’s goal has always been to produce a stable kernel for all time, referred to by a metaphor of losing heat energy and entropy. As Urbit gradually cooled from red hot slag to what we'll call a developer alpha, Tlon began a project of greater outreach to the developer community. In particular, crypto software developers saw attractive aspects in Nock's concision and apparent provability and in Urbit's functional-as-in-math approach to operating system and application state. Tlon started a Discord for onboarding and troubleshooting, including community concierges who were tasked with engaging anyone with ship troubles. This tapped into and fostered a culture of Urbiters aggressively helping others debug and troubleshoot their ships, which continues to this day. Tlon also began Hoon 101 to teach outsiders how to actually build things on Urbit.
36+
37+As Urbit slowly grew into a larger developer community, some hard strategic questions about project scope and direction came into focus. There had always been a provision for Urbit to have some sort of foundation with stewardship over the project—either the Urbit Educational Foundation or something similar. Like the Linux Foundation, this organization would serve to coordinate activity between various companies and individuals contributing to the Urbit project. The foundation would receive an endowment of galaxies earmarked to fund Urbit's development.
38+
39+Urbit's use of address space to fund development means that the builders, even those who have discovered Urbit relatively recently, are able to acquire a significant stake in the project and its success.
40+
41+In practical terms, Tlon started the Urbit Foundation internally first as `urbit.org`, then rolled it out as a standalone company with a mandate to first build itself into a viable cultivator of Urbit, then to take over Urbit core development. By early 2023, the Urbit Foundation was in a position to take over core development for the platform.
42+
43+There have been several aspects of this journey that have led Urbit to have a thriving and promising open source software culture:
44+
45+1. Urbit's nature as a functional operating system has a deep appeal to software developers and others who find appeal in a mathematically elegant system, including the guarantees made by innovations such as the scry namespace bindings and the public key infrastructure.
46+2. Hoon is a mood. What I mean by that is that Hoon's unique aesthetics, subject-oriented paradigm, and the utility of cores give coders a unique experience, like systems programming in APL would feel like.
47+3. The developer docs are finally prioritized and made publicly legible. Large swaths of the operating system and standard library are finally documented.
48+4. Third-party software distribution is made trivial. Decentralized peer-to-peer open source software distribution without having to go through a GitHub intermediary changes the game.
49+5. Urbit's educational program expands from Tlon's initial offerings to a community program (Hooniverse/Hooniversity), then to a dedicated program with specific course milestones under the auspices of the Urbit Foundation.
50+6. Urbiters start meeting in person at Assembly and other events. After the 2020 efflorescence of the Urbit community, this is the first time most of the newer people were able to meet in real life. (This is a substantially different situation than the pre-2019 Urbit environment—most people didn't know Tlonners first, they knew Urbit first and mainly online.)
51+7. Three major active groups form dedicated to all-purpose coding on Urbit:
52+ A. Hooniverse, ~hiddev-dannut/new-hooniverse, originally strictly for the community Hoon School but now for all of the UF's educational efforts.
53+ B. The Forge, ~middev/the-forge, for advanced technical discussion.
54+ C. `[battery payload]`, ~dister-dozzod-lapdeg/battery-payload, the UF's developer community group.
55+8. The Urbit Foundation begins an active grants program. At first focusing on userspace and cultural grants, this eventually leans back into kernel work.
56+9. As the Urbit Foundation takes over core development, this necessitates changing that process from being a one-company project to requiring coordination, said coordination being much easier in the open than in closed meetings. (This also enables Tlon to focus on product delivery over core development.)
57+10. The Urbit Foundation begins using a `gather.town` “Urbit Hacker House,” which puts people together for synchronous interrupts. Any community member can wander in and be a fly on the wall or an active interlocutor.
58+ A. This enables the UF to start hosting daily pull request triage and a rapid assignment of tasks in the open.
59+ B. Communications strategy meetings are also public.
60+ C. Build parties (originally conceived as app-in-a-day) demonstrate pair programming, achieve inter-programmer communication of information akin to IRL programming, and allow anyone to participate.
61+
62+We find ourselves, as Urbit developers, having grown together a strong and unique culture of open source software development verging on radical transparency. It's not just code and license being open—it's the entire ensemble of programmer culture and on-platform dogfooding (to the extent possible). The greybeards and the noobs encounter each other directly and openly all the time, in `gather.town` and in Urbit groups.
63+
64+From modest beginnings, Urbit has achieved some small traction in the world and grown an exemplary open source culture. What will it take for Urbit to succeed in the future? That's the next entry.
content/blog/foss-2.mdnew file+59
@@ -0,0 +1,59 @@
1++++
2+title = "Urbit's Open Source Culture, Part II"
3+date = "2023-06-13"
4+description = "How will Urbit continue to foster its innovative open source software culture?"
5+
6+[extra]
7+author = "N E Davis"
8+ship = "~lagrev-nocfep"
9+image = "https://spacecenter.org/wp-content/uploads/2023/02/img-apollo-mission-control-3.jpg"
10++++
11+
12+![](https://spacecenter.org/wp-content/uploads/2023/02/img-apollo-mission-control-3.jpg)
13+
14+> God watches over fools, drunks, and the United States of America. (Otto von Bismarck, apocryphal)
15+
16+In our last installment, we considered how Urbit has grown its own robust open source culture. Now we look to the future: what will it take for Urbit to succeed, not only as an exemplary open source project but as a computing platform that delivers on its promise?
17+
18+Part of what makes an open source culture vibe is remix culture, the ability to rework the source material to produce novel components or manifestations. Urbit has the raw materials for this in spades, memetically and technically. It is up to us to keep these tools in our developers’ and enthusiasts’ hands.
19+
20+The default answer, which isn't terrible, is that Urbit should keep doing what it's done to get this far:
21+
22+1. Urbit should continue to prioritize decentralized development.
23+2. Urbit should lean into ownership-based incentives. Indeed, this is the most effective lever that the Urbit Foundation has.
24+3. Urbit should maintain the developer's republic. Core developers should rub shoulders with first-time Hooners.
25+4. Urbit should continue to ship source with code, since that is how code is actually distributed. The means of open source software are _necessarily in the user's hands_ with Martian software.
26+
27+There are some areas in which we hope to improve. Our documentation continues to expand, as do our educational offerings. We have a mandate to use the Urbit Foundation’s endowment of stars to produce the mature Urbit.
28+
29+What else should we have an eye to in the near future? There’s always more to do, but by prioritizing the items on this short list we would continue to elaborate our open source bona fides as a community and a steering foundation.
30+
31+1. **Code accessibility should be a priority.** Any computer language falls on the spectrum between machine legibility (the pole of machine code and assembly language) and human legibility (the pole of [Scratch](https://scratch.mit.edu/). All code must walk this line.
32+
33+ Hoon has had a reputation for being a language of dense expressions, which we believe is now being cleared by sunshine. However, Hoon's extensive sugar syntax and irregular expressiveness can make it challenging for those relatively new to Hoon to decipher programs. We can support their learning and entry into the ecosystem by defining a subset of Hoon syntax that we adhere to in all of the docs and some of the userspace code. Even if there is a "better" way to write it, we should prefer this restricted discipline in those cases. Let's call this subset "Hoon Prime." Hoon Prime will not always be the most concise Hoon code, and it will likely fail to maintain certain well-established preferences, like heavier expressions going to the bottom, but it should encourage developers to produce generators and agents from `%base`-distributed models as quickly as possible.
34+
35+ Hoon Prime should also adopt a standard of literate programming. Several example files already display such a self-documenting nature:
36+
37+ - [`simple.hoon` for solid-state subscriptions](https://github.com/wicrum-wicrun/sss/blob/master/urbit/app/simple.hoon)
38+ - [`deco.hoon` for doccords](https://github.com/urbit/urbit/blob/develop/pkg/arvo/lib/deco.hoon)
39+ - [`pals.hoon`](https://github.com/Fang-/suite/blob/master/app/pals.hoon)
40+ - [`rudder.hoon` for serving websites](https://github.com/Fang-/suite/blob/master/lib/rudder.hoon)
41+
42+ Our userspace code accessibility model should allow contributors from widely different skill levels to interact. We need to surface and document code patterns as cleanly as possible in the code we distribute. We need to include comments and unit tests so people can see how and why code works like it does.
43+
44+ Code accessibility cannot be an afterthought. We need to upgrade as much code as possible to A standards [per the style guide](https://developers.urbit.org/reference/hoon/style#grading).
45+
46+2. We need to improve the developer experience. Part of this involves better coding support, and part of this involves better debugging support.
47+
48+ To promote better coding, we should continue to develop IDE integrations like the Hoon Language Server. We've had some significant wins here, but rust never sleeps. We should also continue to produce userspace and middleware support libraries. We need to pay attention to how developer preferences are manifesting in their workflows and tooling.
49+
50+ Better error messaging and debugging support, perhaps even a framework for line-by-line code execution, would be invaluable. Upgrading Dojo and generator support is an easy win. Any tool friction is a sin and we need to track this and think about how to improve use.
51+
52+3. We need our open source culture to continue to develop in the sunlight. We need to highlight and communicate user stories for developer tools, new and old. We need to share these from inside of companies in the ecosystem. I'm not going to call for “best practices”—it's too early and that's too corporate—but tacit knowledge and horizontal skill transfer need to be encouraged through active pair programming and utilization of build parties and the like.
53+
54+ We need to expose how bugs occur, propagate, and are corrected. The core development team has committed to public [postmortems](https://github.com/urbit/urbit/issues/6583) when things go wrong.
55+
56+4. Ultimately, Urbit has to stay playful. Urbit makes programming, even systems programming, a lot of fun. Fun is open-ended and surprising. It allows for whimsy in code and product.
57+
58+Our developer onboarding and open source culture should be a model for the entire open source world. This is neither impossible nor impractical—we've made huge strides in legibility, and we're sailing with the wind.
59+
content/blog/hoon-4-lispers.mdnew file+764
@@ -0,0 +1,764 @@
1++++
2+title = "A Perspective on Lisp and Hoon"
3+date = "2023-06-15"
4+description = "Lisp is an éminence grise of programming. How does Hoon compare?"
5+
6+[extra]
7+author = "N E Davis"
8+ship = "~lagrev-nocfep"
9+image = "https://engineering.stanford.edu/sites/default/files/styles/card_1900x950/public/images/news/john_mccarthy.jpeg?h=3751da6c&itok=6tPSih53"
10++++
11+
12+![John McCarthy, inventor of Lisp, at Stanford.](https://engineering.stanford.edu/sites/default/files/styles/card_1900x950/public/images/news/john_mccarthy.jpeg?h=3751da6c&itok=6tPSih53)
13+
14+> In the beginning, von Neumann created the machine. And the machine was with rigorous form and code, and no compiler yet moved upon the face of the tubes. And the evening and the morning were the first day.
15+>
16+> And John Backus said, Let there be FORTRAN, and there was Fortran. And Fortran ruled over the assembly.
17+>
18+> And John McCarthy saw the lambda calculus, that it was very good. And McCarthy made the LISP and divided the programmers who were for the array from the programmers who were for the list.
19+>
20+> And the Fortran and the Lisp were the second day. And God set them in the firmament to give light upon the earth.
21+
22+Two great temperaments of programming language design span these poles: Fortran as the engineer of assembler-first hard-nosed array coding and Lisp as the math professor running down to the machine room waving papers. While they have ceded some to the practicalities of the other over time, each is a trope of a particular computing paradigm. In this article, we will examine the Lisp pole in light of Urbit's development language, Hoon.
23+
24+Hoon is a statically typed functional programming language that is designed to be safe, efficient, and expressive. Hoon has a unique syntax relying heavily on symbolic expressions (using “runes”) rather than traditional keywords and operators. Hoon's underlying execution language, Nock, has been described as a “pico-Lisp“, making reference to its nature as a cell-based combinator calculus. Both languages (Nock and Hoon) follow very much in the philosophical steps of Lisp but seek to improve the genre.
25+
26+Lisp is known for its powerful macro system, which allows developers to write code that generates more code at compile time, and for its powerful `eval` function; while Hoon provides a flexible metaprogramming system that allows developers to manipulate code at compile time and hot-swap code at runtime.
27+
28+This article will contrast classical Lisp syntax and assumptions with Hoon's design. As Lisp is a family of languages rather than a single implementation, I will strive to make generally applicable statements or qualify the discussion—I welcome nuance in your responses about the different major Lisp dialects.
29+
30+Hoon's characteristic structure has arisen from these overarching design principles:
31+
32+1. Hoon must compile to Nock, and benefits from reflecting Nock's calculational worldview.
33+2. Hoon must be capable of live upgrades; that is, conscious brain surgery on itself.
34+3. Hoon should grow organically based on actual developer usage patterns.
35+
36+Our investigation of Lisp and Hoon will compare their syntax, their metaprogramming affordances, and their underlying philosophies.
37+
38+
39+## Syntax
40+
41+Hoon has many commonalities with Lisp and its most common calling convention is sugared to appear like Lisp. The conventions of Nock differ—e.g. using `[]` brackets instead of `()` parentheses—and Nock does not have non-numeric tokens or names. Hoon serves as a more human-friendly syntax which mediates common expressions and structures much as C overlays assembly language. For practical purposes, we never need to write Nock code by hand, and so while Nock informs Hoon's design choices, we don't need to understand any Nock to talk about Hoon.
42+
43+Both Lisp and Hoon are homoiconic, meaning that code and data are directly represented the same way: Lisp code is represented as Lisp data structures, and Hoon code is represented as Hoon data structures. Homoiconicity means that code can be manipulated and transformed as data at runtime. While the most compelling investigation in this article focuses on metaprogramming, we need to start with a comparative syntax and grammar so we understand how code and data are represented.
44+
45+Before all of that, let us compare a simple program implemented in both Lisp and Hoon. Both programming languages are species of functional languages for which expressions result in values, but they handle side effects differently: in Hoon side effects are strictly impossible (although a runtime workaround permits I/O and necessary effects), while in Lisp side effects are permitted (although opinions on their use vary). We will therefore not use a trivial “Hello World” example. Instead we will calculate the arithmetic mean of a set of numbers of known size.
46+
47+```scheme
48+(define (mean a)
49+ (if (null? a)
50+ 0
51+ (/ (apply + a) (length a))))
52+```
53+
54+```hoon
55+:: Common (sugared) form
56+++ mean
57+ |= a=(list @ud)
58+ ?~ a 0
59+ (div (roll a add) (lent a))
60+
61+:: Rune (unsugared) form
62+++ mean
63+ |= a=(list @ud)
64+ ?~ a 0
65+ %+ div
66+ %- roll [a add]
67+ %- lent a
68+```
69+
70+The Scheme code has the advantage that it reads almost English-like as one works through the logic, but implicitly relies on familiarity with the `if`/`then`/`else` structure and function application using `()` (on which more soon).
71+
72+The Hoon code uses the `%` function application runes (differentiated by number of arguments) to apply the function calls. With syntactic sugar, this looks similar to the Lisp call, with `++roll` instead of `apply` and `++lent` instead of `length`.
73+
74+Throughout I will use code examples for Lisp taken from [Rosetta Code](https://rosettacode.org/wiki/Category:Scheme). I will select or compose Hoon examples to be structurally similar to the Lisp code in order to facilitate comparison. I will also avoid sugar syntax that would obscure the structure of the Hoon code; in some cases this will make it slightly less readable than its equivalent in practice.
75+
76+### Syntax in Lisp
77+
78+#### Types
79+
80+Lisp types are dynamic, checked at runtime rather than on compilation. Since everything is an object, some assumptions can be made about manipulation and behavior. Most Lisp dialects share these types:
81+
82+- Numbers, including integers and floating-point numbers.
83+- Characters.
84+- Strings, as a sequence of characters.
85+- Lists, as a sequence of objects (including lists).
86+- Symbols, names used to refer to a function, variable, or other object.
87+- Arrays, a fixed-size multidimensional indexed object collection.
88+
89+Lisp code, being dynamically typed, is inclined to try a value and see if it works in a given context. However, some restrictions can be made, such as an argument type declaration on a function:
90+
91+```lisp
92+(defun add-two-integers (x y)
93+ (declare (type integer x y))
94+ (+ x y))
95+```
96+
97+Lisp types are to some extent (justly) influenced by the underlying platform architecture: Lisp is generally compiled directly to machine code (like a C program), with the notable exception of [Clojure](https://clojure.org/reference/lisps) which runs on the Java Virtual Machine.
98+
99+#### Operators, Functions, Macros, and Thunks
100+
101+Lisp syntax is characterized by its use of nested lists, called S-expressions (symbolic expressions), which consist of parentheses enclosing atoms or other S-expressions. The basic structure of an S-expression is an operator (or function) followed by its arguments, all enclosed in parentheses. For example, the following S-expression performs a simple arithmetic operation:
102+
103+```lisp
104+(+ 1 2 3)
105+```
106+
107+Lisp uses prefix notation, where the operator comes before the operands, and parentheses are used to group expressions. The S-expression is evaluated from left to right (in most Lisps save Scheme), with the operator being applied to its arguments.
108+
109+Operators in Lisp operate on values of different basic types. Lisp dialects vary in their particular base types, but typically include numbers, strings, booleans, and so forth. The core data type is the list, of course (LISP is for LISt Processing). Since Lisp biases towards list processing, many operators are comfortable receiving an arbitrary number of values as inputs, as in the code sample above.
110+
111+In Lisp, [`cons`](https://en.wikipedia.org/wiki/Cons) describes the procedure to construct a pair of objects. This seemingly modest capability is fundamental to how Lisp builds lists—and since everything is a list, `cons` has consequences. One fundamental convention is the `cons` cell, which consists of two other Lisp objects and is how lists are actually constructed.
112+
113+![](https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Cons-cells.svg/450px-Cons-cells.svg.png)
114+
115+Lisp operations are built either as functions or as macros. Functions produce results directly from their inputs. Macros by contrast are basically function-building functions, and produce expressions that can be evaluated with inputs to get a result.
116+
117+A Lisp function is created using `defun`:
118+
119+```lisp
120+> (defun square (x) (* x x))
121+SQUARE
122+
123+> (square 2)
124+4
125+```
126+
127+(Lisp dialects tend to not be case-sensitive.)
128+
129+Lisp functions are first-class objects and can be manipulated and passed like values of basic types as well.
130+
131+Before we can look at macros, we need to consider Lisp's notion of evaluation and in particular deferred evaluation. For Lisp, an expression can be marked as a literal value rather than evaluated to produce a result. The quote `'` symbol is used to mark expressions for prevented evaluation:
132+
133+```lisp
134+'(1 2 3) ; evaluates to the list (1 2 3)
135+'foo ; evaluates to the symbol FOO
136+(1 5) ; evaluates to the list (1 5)
137+'(1 (+ 2 3)) ; evaluates to the list (1 (+ 2 3))
138+```
139+
140+Backtic or backquote `` ` `` allows you to switch an expression in and out of evaluation mode, along with `,` to mark evaluated components for splicing back into the unevaluated expression.
141+
142+```lisp
143+`(1 2 3) ; evaluates to the list (1 2 3)
144+`foo ; evaluates to the symbol FOO
145+`(1 ,(+ 2 3)) ; evaluates to the list (1 5)
146+```
147+
148+A Lisp macro is essentially a compile-time function.
149+
150+```lisp
151+> (defmacro square (x)
152+ "Returns the square of the input value."
153+ `(* ,x ,x))
154+
155+> (square 2)
156+4
157+```
158+
159+(The `` ` `` notation constructs the expression with values spliced in by `,`.)
160+
161+A deferred evaluation, called a thunk, is a closure that inherits its lexical environment but is deferred for later computation. Thunks enable lazy code evaluation and separate the computation’s definition from its execution.
162+
163+```lisp
164+(defun create-thunk (function &rest arguments)
165+ (lambda () (apply function arguments)))
166+
167+(defun invoke-thunk (thunk)
168+ (funcall thunk))
169+
170+;; Creating a thunk that calculates the factorial of a number
171+(defvar factorial-thunk (create-thunk #'(lambda () (factorial 5))))
172+
173+;; Invoking the thunk to get the result
174+(print (invoke-thunk factorial-thunk)) ; Output: 120
175+```
176+
177+In this code example, `create-thunk` accepts a function and returns a thunk created using a lambda function to encapsulate the computation. `invoke-thunk` is used to invoke the thunk to get the actual result. The actual application creates a deferred factorial implementation and then finally invokes it. Without the last line, the actual calculation would never be executed.
178+
179+As Paul Graham wrote, “The unusual thing about Lisp-- in fact, the defining quality of Lisp-- is that it can be written in itself.” A Lisp program is an S-expression, and in principle we can run the equation the other way: certain S-expressions are valid Lisp programs. Although uncommon in practice due to code safety issues, the `eval` function is illustrative of Lisps’ ability to evaluate a Lisp expression that is represented as a data structure. It takes a single argument, which is a Lisp expression, and returns the value of that expression. Lisp programs can in principle generate new code—or modify existing code—and evaluate it on the fly, since code is data.
180+
181+```lisp
182+(defvar x 10)
183+(defvar y 20)
184+(defvar z '(+ x y))
185+
186+(eval z)
187+```
188+
189+Besides explicitly named functions and macros, Lisp frequently employs lambda expressions to produce functions on demand at the point of use.
190+
191+```lisp
192+> ((lambda (x y) (+ x y)) 5 10)
193+15
194+```
195+
196+Naturally, we have not covered all of Lisp, but the above should motivate how Hoon differs from Lisp. Furthermore, Lisp is really a family of languages, so there is a fair amount of variation in specifics.
197+
198+- [Paul Graham, _On Lisp_](http://www.paulgraham.com/onlisptext.html)
199+
200+### Syntax in Hoon
201+
202+#### Types
203+
204+Hoon compiles to Nock and runs on a Nock virtual machine interpreter. Nock knows only about nouns, that is to say either simple unsigned integers or pairs of other nouns.
205+
206+> To be exact, a noun is an S-expression, except that classic S-expressions have multiple atom types ("S" is for "symbol"). Since Nock is designed to be used with a higher-level type system (such as Hoon's), it does not need low-level types. An atom is just an unsigned integer of any size.
207+
208+
209+One of the biggest differences between Hoon and Lisp lies in their respective type systems: Hoon is statically typed while Lisp is dynamically typed. Furthermore, since Hoon compiles to Nock, ultimately every value, expression, and program in Hoon results in a noun (an atom or unsigned integer, or a cell or pair of nouns). (The compiler may make this process slightly opaque, but it is deterministic.) Types, if values are known, must match or nest properly at compile time.
210+
211+Hoon implements types as a metadata layer over bare Nock numbers and atoms. (The implementation details do not concern us but can be seen using the `!,` zapcom rune, which produces the abstract syntax tree of an expression.) Hoon atom types include various numeric types (signed and unsigned, hexadecimal, binary, etc.); address space identifiers (such as ~zod); IP addresses; UTF-8 text; and floating-point values, [among many others](https://developers.urbit.org/blog/literals). As these are interpretations laid over the bare integer, it is trivial to convert among them, a convenience like C affords.
212+
213+```hoon
214+:: raw unsigned decimal integer
215+> 123
216+123
217+
218+:: hexadecimal integer
219+> `@ux`123
220+0x7b
221+
222+:: UTF-8 text
223+> `@t`123
224+'{'
225+
226+:: relative datetime (a small fraction of a second)
227+> `@dr`123
228+~s0..0000.0000.0000.007b
229+
230+:: address mnemonic (ship name)
231+> `@p`123
232+~rux
233+
234+:: IPv4 address
235+> `@if`123
236+.0.0.0.123
237+
238+:: IPv6 address
239+> `@is`123
240+.0.0.0.0.0.0.0.7b
241+```
242+
243+A cell is a pair of two nouns, and of course many compound types exist, including lists (a null-terminated series of cells). A file path in Urbit is, for instance, a list of resource names (a `path`). A manipulable text string is a list of single bytes for characters (a `tape`). Maps (associative arrays), sets, and other containers round out the basic data structure types, but more complex types such as HTTP headers and app metadata are available. Even app actions have an associated type so that the set of actions is enumerable and validated. Here, for instance, are some cryptographic types from the standard library:
244+
245+```hoon
246++$ jacobian [x=@ y=@ z=@] :: jacobian point
247++$ point [x=@ y=@] :: curve point
248++$ domain
249+ $: p=@ :: prime modulo
250+ a=@ :: y^2=x^3+ax+b
251+ b=@ ::
252+ g=point :: base point
253+ n=@ :: prime order of g
254+ ==
255+```
256+
257+Hoon expressions are ultimately binary trees of cells and atoms—Hoon is homoiconic and so code is directly represented as a data structure which can be interpreted as a value as well. This facilitates Hoon's ability to upgrade itself in place, as we will see.
258+
259+Hoon commonly implements types structurally via _molds_, or functions which coerce to type or crash. A mold is a way of asserting known type information over a value, typically at compile time, in a way that allows for data transformation and data validation. This leads to some interesting cases such as the difference between a null-terminated tuple and a true list, which some functions require.
260+
261+```hoon
262+> ~[1 2 3]
263+[1 2 3 ~]
264+
265+> `(list @)`~[1 2 3]
266+~[1 2 3]
267+
268+> (snag 2 ~[1 2 3])
269+mull-grow
270+-need.[i=@ud t=%~]
271+-have.%~
272+nest-fail
273+dojo: hoon expression failed
274+
275+> (snag 2 `(list @)`~[1 2 3])
276+3
277+```
278+
279+Hoon implements a unique character literal syntax for every single atom type, allowing any value to be unambiguously interpreted by the parser per the developer's intent. You can see this somewhat in evidence in this comparison chart:
280+
281+| Type | Lisp Type | Hoon Type |
282+| --- | --- | --- |
283+| (Unsigned) integer | `1` | `1` |
284+| Signed integer | `-1`, `1` | `-1`, `--1` |
285+| Symbol | `x` | `%x` |
286+| Real/FP | `1.5` | `.1.5` |
287+| Character | `#\c` | `'c'` |
288+| Text | `"Hello"` | `'Hello'` (as atom); `"Hello"` (as list) |
289+| Rational | `2/3` | (no Hoon equivalent) |
290+| Address | (no Lisp equivalent) | `~sampel-palnet` |
291+
292+Much of Hoon's practical power derives from how it represents and manipulates nouns as data and as code.
293+
294+> The type of type is just a normal datatype in Hoon, and a lot of the system manipulates types. In particular, the `!>` rune, when applied to a piece of data, uses compile-time type reflection to produce something called a "vase": a pair of type and data, similar to a `Data.Dynamic` in Haskell, or a limited form of a dependent pair. Since the Arvo kernel does a lot of dynamic compilation, it uses vases to implement something akin to a dynamically typed language using Hoon. This allows for type-safe dynamic program loading, program execution, and data migration. (Ted Blackman ~rovnys-ricfer, [“Why Hoon”](https://urbit.org/blog/why-hoon))
295+
296+A `vase` in Hoon is a cell of type and value. Typically `vase`s are produced with the `!>` zapgar rune. We use `vase`s to carry type information where otherwise it may be lost, such as in transmission over the wire to another Urbit instance.
297+
298+```hoon
299+> !>('hello')
300+[#t/@t q=478.560.413.032]
301+
302+> !>([5 10])
303+[#t/[@ud @ud] q=[5 10]]
304+
305+> !>(`(list @)`~[1 2 3])
306+[#t/it(@) q=[1 2 3 0]]
307+
308+> !>(`(list @)`~)
309+[#t/it(@) q=0]
310+```
311+
312+A `vase` can be used at runtime to resolve a value from a dynamic context into an executable Hoon expression, and this is commonly done with web-based input, for instance, where insufficient information will be available at compile time to resolve the type correctly.
313+
314+#### Expressions
315+
316+Nock explicitly consists of binary trees, since any Nock structure or program consists entirely of atoms (bare values) and cells (pairs of nouns).
317+
318+![](https://storage.googleapis.com/media.urbit.org/docs/userspace/hoon-school/binary-tree.png)
319+
320+Expressions are oriented around runes, which act as operators to join or manipulate expressions. To construct a cell of two values like `1` and `2`, one uses the `:-` cencol rune. (Hoon cells implement what we call an “implicit `cons`”, meaning that two nouns composed together are simply unified in a shared binary tree.)
321+
322+```
323+ :-
324+ / \
325+1 2
326+```
327+
328+To invoke a function named `add`, one can provide a `%-` cenhep rune with the function name and the arguments.
329+
330+```
331+ %-
332+ / \
333+add :-
334+ / \
335+ 1 2
336+```
337+
338+We write this Hoon expression one of two ways, either separated by whitespace or using parentheses:
339+
340+```
341+> %- add :- 1 2
342+3
343+
344+> %-(add :-(1 2))
345+3
346+```
347+
348+Hoon employs “sugar syntax” for many common code patterns to make them easier to write and (sometimes) to read. Since Hoon had the advantage of knowing about Lisp's syntax beforehand, the standard invocation syntax in Hoon (formally a `%` rune) uses the irregular `()`-based syntax like Lisp. In this case, we could instead write the Lisp-like expression:
349+
350+```hoon
351+> (add 1 2)
352+3
353+```
354+
355+which results in basically the same expression once the parser is done.
356+
357+(Although Hoon ultimately compiles to Nock, it is more natural in some ways to approach the syntax of a program as an array of $n$-ary trees, where each “slot” in an expression can have zero, one, or many children. Zero children refers to a tree address containing a terminal value like a symbol or an integer.)
358+
359+Rune syntax is Hoon's answer to the Lisp proliferation of parentheses—by restricting expressions to a definite number of children, Hoon avoids needing to explicitly terminate most expressions. In some ways, runes are an ASCII-based equivalent of APL's symbolic character operators.
360+
361+```apl
362+life ← {⊃1 ⍵ ∨.∧ 3 4 = +/ +⌿ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵}
363+```
364+
365+Rather than permit polymorphic language statements, Hoon requires each rune to be extremely tightly defined. While many statements may be functionally equivalent to an `if` or a `cond` statement, for instance, Hoon allows the developer to select a particular expressive rune if desired.
366+
367+- `?:` typical `if`/`then`/`else` branch
368+- `?=` branch on type
369+- `?@` branch if atom
370+- `?^` branch if cell
371+- `?+` switch on type with default
372+- `?-` switch on type without default
373+- `?~` branch if null
374+
375+The next examples explore an interesting difference between Lisp `cond` and Hoon `?+` wutlus swtich statements: Hoon switches over _types_ not _values_, and `term` symbols as constants are instances of self-matching types.)
376+
377+```scheme
378+(define (weather f)
379+ (cond ((> f 80) 'too-hot)
380+ ((> f 60) 'nice)
381+ ((< f 35) 'too-cold)
382+ (else 'typical-midwest)))
383+```
384+
385+```hoon
386+|%
387+++ weather
388+ |= f=@ud
389+ ?: (gth f 80) %too-hot
390+ ?: (gth f 60) %nice
391+ ?: (lth f 35) %too-cold
392+ %typical-midwest
393+++ symbol-to-message
394+ |= msg=term
395+ ?+ msg 'Typical Midwest'
396+ %too-hot
397+ 'Too hot outside'
398+ %nice
399+ 'Nice outside'
400+ %too-cold
401+ 'Too cold here'
402+ ==
403+--
404+```
405+
406+Lisp expects a program to be a running series of expressions, naturally composed together as a list. Hoon, in contrast, expects everything to be an evaluable expression (no implicit `progn`, for instance): thus, series of expressions must be composed together, e.g. using `=>` tisgar to concatenate two expressions.
407+
408+This code example defines an expression and immediately evaluates another expression against it:
409+
410+```hoon
411+=> [a=1 b=2 c=3]
412+::
413+b
414+```
415+
416+Hoon code is compiled to Nock, but it is not a simple macro over Nock—multiple Hoon expressions could result in an identical Nock expression, and the same Hoon expression evaluated against different subjects could result in different Nock expressions. Hoon code is parsed to an abstract syntax tree first, which includes type metadata, then compiled into the appropriate Nock statement. Here we use the `!,` zapcom rune to turn a Hoon expression into its AST, then `!=` zaptis to compile a Hoon expression to Nock.
417+
418+```hoon
419+> !,(*hoon `@ux`+(1))
420+[ %ktls
421+ p=[%sand p=%ux q=0]
422+ q=[%ktls p=[%sand p=%$ q=0] q=[%dtls p=[%sand p=%ud q=1]]]
423+]
424+
425+> !=(`@ux`+(1))
426+[4 1 1]
427+```
428+
429+Hoon has much more syntactic sugar than Lisp. Not only is the Lisp-like `()` execution convention sugar for `%:` cencol to invoke a function, there are in fact many ways to evaluate code expressions. Consider, for instance:
430+
431+| Rune | Usage |
432+|---|---|
433+| `%-` | Evaluate a function against a single noun. |
434+| `%+` | Evaluate a function against a cell (pair of nouns). |
435+| `%^` | Evaluate a function against a trio of nouns. |
436+| `%:` | Evaluate a function with many arguments ($n$-ary, unspecified number of nouns). |
437+| `%~` | Evaluate a higher-order function to produce a function. |
438+
439+This gives a Hoon developer an extreme amount of flexibility in constructing and laying out code expressions. In fact, many Hoon programs read as a hybrid of imperative code and functional code, since the ability to lay out intent line-by-line feels rather like C.
440+
441+Hoon conventions and sugar syntax have evolved organically as core developers discovered or invented useful design patterns and appropriately concise syntax.
442+
443+#### Functions (Gates) and Cores
444+
445+The most important structural concept in Hoon is the core, which organizes code into a binary tree of `[code data]`, or as we call it in Hoon, `[battery payload]`. Since cores have a standard structure, this means that many kinds of direct manipulations (metaprogramming) are possible, such as altering the input arguments to a function or manipulating the code variance model. Cores play a role in Hoon similar to that of objects in many other languages.
446+
447+Any function (“gate” in Hoon parlance) is a core, whose `battery` is the compiled Nock code and whose `payload` includes its view of the system, including the standard library, and its input arguments. The `|=` bartis rune is most commonly used to make a gate:
448+
449+```hoon
450+:: Select the larger of two values ("max").
451+|= [a=@ b=@]
452+?: (gth a b)
453+ a
454+b
455+```
456+
457+The gate definition rune `|=` bartis has two children, a specification of the expected input and the expression. When invoked, the values of the specification (or "sample") are provided to the expression, which then evaluates to return a noun.
458+
459+One quirk of Hoon is that since everything is an address (or “axis”) in a binary tree, you can access anything in your scope (“subject”) through its axis. Most commonly you attach a face to a value (like a gate), but you don't have to. At any point, to refer to the previous statement, you can invoke the head of the tree, `-`; to wit,
460+
461+```hoon
462+> =/ a 5
463+ -
464+a=5
465+```
466+
467+The name `a` is also attached to the value and can be used to identify the value. (To the Hoon parser there is no real difference; this is a programmer quality-of-life affordance.)
468+
469+```hoon
470+> =/ a 5
471+ a
472+5
473+```
474+
475+Thus faces (names) are attached to gates (functions) within a particular scope or context, such as a `|%` core. Each core defines a collection of values and gates (collectively termed “arms”) which occupy a shared scope. For example, the following library demonstrates a few floating-point operations in Hoon. Each function can see the parent subject (including `hoon.hoon` and some other cores) as well as its neighboring arms (such as `++pow-n` called by `++exp`).
476+
477+```hoon
478+|%
479+:: Factorial, x!
480+++ factorial
481+ |= x=@rs
482+ =/ t=@rs .1
483+ |- ^- @rs
484+ ?: =(x .1) t
485+ $(x (sub:rs x .1), t (mul:rs t x))
486+:: Absolute value, |x|
487+++ absolute
488+ |= x=@rs
489+ ?: (gth:rs x .0) x
490+ (sub:rs .0 x)
491+:: Exponential function, exp(x)
492+++ exp
493+ |= x=@rs
494+ =/ rtol .1e-5
495+ =/ p .1
496+ =/ po .-1
497+ =/ i .1
498+ |- ^- @rs
499+ ?: (lth:rs (absolute (sub:rs po p)) rtol) p
500+ $(i (add:rs i .1), p (add:rs p (div:rs (pow-n x i) (factorial i))), po p)
501+:: Power, restricted to integeres only, x**n
502+++ pow-n
503+ |= [x=@rs n=@rs]
504+ ?: =(n .0) .1
505+ =/ p x
506+ |- ^- @rs
507+ ?: (lth:rs n .2) p
508+ $(n (sub:rs n .1), p (mul:rs p x))
509+--
510+```
511+
512+Ultimately, however, the faces resolve back to an axis and the code is composed by the compiler into a Hoon syntax tree and thence to Nock for the runtime interpreter.
513+
514+The nature of cores derives from Nock and is key to understanding how Hoon works. All nontrivial structures in Hoon are cores. For instance, even a gate is a regular `|%` core, with `|=` expanding to `|%`. The following code snippets are identical to the Hoon compiler after parsing.
515+
516+```hoon
517+:: increment a number by two
518+|= p=@ud
519++(+(p))
520+```
521+
522+```hoon
523+:: increment a number by two
524+=+ ^~(*p=@ud)
525+|%
526+++ $
527+ +(+(p))
528+--
529+```
530+
531+Although Lisp's `'` quoting has no direct equivalent in Hoon, there are a couple of structures that can provide a similar effect. The most important of these is the `|.` trap, which defines an expression to be evaluated at a later time—Hoon’s equivalent of Lisp’s thunk. For instance, traps are used when testing code that _should_ fail, as the expression can be defined and deferred until the test framework is ready to process it.
532+
533+```hoon
534+> =foo |.((add 1 41))
535+
536+> -:foo
537+[8 [9 36 0 2.047] 9 2 10 [6 [7 [0 3] 1 1] 7 [0 3] 1 41] 0 2]
538+
539+> (foo)
540+42
541+```
542+
543+(To understand the second entry, recall that code is the in head of the core—here, we see the Nock code for the operation defined in the `|.` trap.)
544+
545+[Wet gates](https://developers.urbit.org/guides/core/hoon-school/R-metals) present the most macro-like feature in Hoon. A regular function, or “dry gate” (as above), receives an argument (the sample); the type system tries to cast the sample to the type specified by the gate, and fails if not possible. Wet gates instead defer type evaluation and instead attempt to use the sample (or arguments) directly in the expression. This produces a parametric polymorphism. (This comes close to dynamic typing, but type is still checked at compile time.) Wet gates are commonly used as gate-building gates, such as mold-producing gates like `++list`.
546+
547+Consider a function like `++turn` which transforms each element of a list.
548+
549+```hoon
550+> `tape`(turn ~[77 97 114 115] @t)
551+"Mars"
552+```
553+
554+To use `++turn`, we need a list and a transformation function. The type of the list we produce depends on the type of the list and the type of the transformation function. The actual gate `++turn` should work to transform each element of the list for on any function and any list, so long as the function's argument is the list item.
555+
556+Wet gates are therefore used when incoming type information is not well known and needs to be preserved. This includes parsing, building, and structuring arbitrary nouns. (Beyond Lisp analogues, you can think of C++'s templates and operator overloading, and Haskell's typeclasses.)
557+
558+This example compares the Lisp deferred factorial thunk with an equivalent Hoon trap. (Hoon includes `++factorial` since it is not part of the standard library.)
559+
560+```scheme
561+(defun create-thunk (function &rest arguments)
562+ (lambda () (apply function arguments)))
563+
564+(defun invoke-thunk (thunk)
565+ (funcall thunk))
566+
567+;; Creating a thunk that calculates the factorial of a number
568+(defvar factorial-thunk (create-thunk #'(lambda () (factorial 5))))
569+
570+;; Invoking the thunk to get the result
571+(print (invoke-thunk factorial-thunk)) ; Output: 120
572+```
573+
574+```hoon
575+=>
576+|%
577+++ factorial
578+ |= n=@ud
579+ |-
580+ ?: =(n 1) 1
581+ %+ mul n
582+ %= $
583+ n (dec n)
584+ ==
585+++ factorial-5
586+ |. (factorial 5)
587+--
588+(factorial-5)
589+```
590+
591+### Subject-Oriented Programming
592+
593+Urbit programming employs a paradigm deriving from the nature of Nock (_a fortiori_ Hoon), subject-oriented programming. Every expression of Hoon is evaluated relative to its subject, a piece of data that represents the environment, or the context, of an expression.
594+
595+The subject refers to the parent binary tree of an expression, more or less, and serves as state, lexical scope, environment, and function argument. (We can be precise about the definition in all cases—e.g. the subject of a gate in a core is the core itself—but don't need to for this essay.) Lisp supports variable scope and global variables, such that any part of the program can access a particular binding. Hoon's subject-oriented programming model naturally provides its equivalent of scope: all code is evaluated against a subject and name bindings proceed by depth-first match (with permitted skips to prevent unwanted masking).
596+
597+> Subject orientation in Nock and Hoon stems partly from minimalism (there's just one subject, which serves as state, lexical scope, environment, and function argument), partly from a desire to simplify compilation (the type of the subject is a full specification of the compile-time environment for a source file), and partly in order to give the language a more imperative feel.
598+>
599+> Everything about a scope, including name bindings, aliases, and docstrings, is stored in the subject's type. This allows Hoon's compilation discipline to be similarly minimal: the compiler is a function from subject type and Hoon source to product type and compiled Nock. Running this Nock against a value of the subject type produces a vase of the result. It's hard to imagine a more streamlined formalism for compilation. (Ted Blackman ~rovnys-ricfer, [“Why Hoon”](https://urbit.org/blog/why-hoon))
600+
601+The subject is typically the core in which an expression is evaluated, but can be more narrowly defined; consider, for instance, our example from above:
602+
603+```hoon
604+=> [a=1 b=2 c=3]
605+::
606+b
607+```
608+
609+A slightly different program fails:
610+
611+```hoon
612+=> [a=1 b=2 c=3]
613+::
614+(add a b)
615+```
616+
617+because the `++add` gate is not defined in the subject against which the expression is evaluated, the first statement.
618+
619+### Comparative Examples
620+
621+#### Find in List
622+
623+```scheme
624+(define index-of
625+ (lambda (needle haystack)
626+ (let ((tail (member needle haystack)))
627+ (if tail
628+ (- (length haystack) (length tail))
629+ (throw 'needle-missing)))))
630+```
631+
632+```hoon
633+:: Produces the index of the first occurrence of nedl in hstk
634+:: as the unit of an atom.
635+++ find
636+ |= [nedl=(list) hstk=(list)]
637+ =| i=@ud
638+ |- ^- (unit @ud)
639+ =+ [n=nedl h=hstk]
640+ |-
641+ ?: |(?=(~ n) ?=(~ h))
642+ ~
643+ ?: =(i.n i.h)
644+ ?~ t.n
645+ `i
646+ $(n t.n, h t.h)
647+ ^$(i +(i), hstk +.hstk)
648+```
649+
650+#### Filter a List
651+
652+```scheme
653+(define filter
654+ (lambda (fn lst)
655+ (let iter ((lst lst) (result '()))
656+ (if (null? lst)
657+ (reverse result)
658+ (let ((item (car lst))
659+ (rest (cdr lst)))
660+ (if (fn item)
661+ (iter rest (cons item result))
662+ (iter rest result)))))))
663+```
664+
665+```hoon
666+:: Cycle through the members of a list a, passing them to a gate b
667+:: and produce a list of all of the members that produce TRUE.
668+++ skim
669+ |* [a=(list) b=$-(* ?)]
670+ |-
671+ ^+ a
672+ ?~ a ~
673+ ?:((b i.a) [i.a $(a t.a)] $(a t.a))
674+```
675+
676+- Several examples in the above section were drawn from [UW's CSE 341 course notes](https://courses.cs.washington.edu/courses/cse341/03wi/scheme/basics.html) and from [Rosetta Code](https://rosettacode.org/).
677+
678+
679+## Metaprogramming
680+
681+A Lisp program is really a list, or a list of lists (nested as much as necessary). While this can be interpreted as an $n$-ary tree, tree structure is not the preferred structural metaphor. A Hoon program is a noun, or equivalently a binary tree. Every component of it is directly addressable and thus in principle reflective. Both languages are homoiconic, with code and data representations being the same. What are the consequences of homoiconicity?
682+
683+### Metaprogramming in Lisp
684+
685+Metaprogramming is the practice of writing code that manipulates other code at either compile-time or runtime. In Lisp, metaprogramming is a core feature of the language, and it allows developers to create programs that are incredibly powerful and flexible. Lisp's metaprogramming capabilities are primarily built on two features: macros and syntax manipulation.
686+
687+Macros in Lisp are a way to define new language constructs that are more expressive and more powerful than those provided by the language itself. When a Lisp program is compiled or interpreted, macros are expanded into regular Lisp code, allowing the macro to generate new code based on its input arguments. Since Lisp code is represented as data, it can be manipulated using the same functions and operators used to manipulate other data structures.
688+
689+For instance, Lisp macros could allow you flexibility in expressing a common operation. Imagine you're working on a project that requires a lot of complex math calculations. Rather than writing out each calculation manually, you could define a macro that takes an expression in infix notation (e.g. `2 + 3 * 4`), and transforms it into a Lisp expression that can be evaluated directly. Thus you could compose math expressions in a more human-natural way without having to worry about details of Lisp syntax.
690+
691+Lisp can also manipulate its own syntax. This is sometimes done through the use of reader macros, which operate at the level of the Lisp reader, which is responsible for converting textual input into Lisp expressions. Reader macros can be used to extend the syntax of Lisp, allowing developers to define new conventions or domain-specific languages for specific types of data or operations. Beyond reader macros, Lisp can permit the developer to change the parser (and as long as the result is a Lisp expression, the interpreter or compiler will be fine with this). Top-level functions can be replaced or modified (“advised”). Symbol macros can change source code.
692+
693+Lisp's `'` quote and the `eval` statement allow single expressions to be inhibited or evaluated at will, which is incredibly useful when dealing with symbols that may not be defined yet or in the composition of macros.
694+
695+In addition to macros and syntax manipulation, Lisp dialects typically provide a number of other features that make metaprogramming easier, such as the ability to inspect and modify the runtime environment, and the ability to create or redefine functions and classes at runtime.
696+
697+### Metaprogramming in Hoon
698+
699+While Hoon explicitly avoids macros and domain-specific language specializations, there are many aspects of Hoon which allow or exploit code reflection and manipulation.
700+
701+In practice, Hoon is intended as a systems programming language for the Urbit Nock VM. Hoon's metaprogramming has as a consequence mainly focused on aspects of core manipulation (such as code building and wet gates) and on live code upgrades (what I'll call hot-swapping code). Hoon eschews macros and in particular has a philosophical stance against domain-specific languages (DSLs). (There are some exceptions, notably Sail, Hoon's XML/HTML syntax; and JSON reparsing.)
702+
703+Hoon has the ability to parse arbitrary text strings (typically files) into executable ASTs and Nock. Symbols can be directly converted to and from regular text strings.
704+
705+As the programming language for a “hundred-year computer”, Hoon needs the ability to hot-swap code at runtime. Elements of cores can be removed or replaced. (Really, Hoon code is immutable: the system is actually making a copy with a specified change.) Every app and even the OS itself can define a state transition function and upgrade along a deterministic pathway.
706+
707+Hoon is in principle extremely reflective as it simply compiles to a Nock noun. Since everything is a stationary tree, it is straightforward to manipulate any object. There are no magic binary blobs or opaque data types: if you have a file handle or an Ethereum block or a websocket connection object, it is a tree and you can work with it directly. (Cf. [“Why Hoon”](https://urbit.org/blog/why-hoon).) Obtaining—or changing—details about gate sample or core behavior becomes a routine part of the Hoon developer’s toolkit. Given such regularity, it would be desirable to expose further capabilities of code reflection and introspection explicitly for the interpreter and IDE.
708+
709+One of the most common design patterns in Hoon is that of the higher-order function, or what Hoon calls “gate-building gates”. These are gates (functions) that produce gates (functions). For instance, as Hoon is statically typed a list must have an associated element type at compile time. `++list` is a gate builder that produces a type gate, which can then be applied to the actual values:
710+
711+```hoon
712+list :: gate builder
713+(list cord) :: gate for list of cords (strings)
714+`(list cord)`~['a' 'b' 'c'] :: list type applied to value
715+```
716+
717+Hoon represents a “hyperlambda” with respect to anonymous function creation: one very often defines gates at their point of use, particularly when operating on each member of a list or set. Similar to Lisp's frequent use of `lambda`, the one-time-use function is available at the point of call as an anonymous gate. (More generally, every gate is anonymous and we have to attach a name to it as a search path, but that's a bit out of scope here.)
718+
719+```scheme
720+((lambda (x1 x2)
721+ (* (- x1 x2) (- x1 x2)))
722+ 2 -5)
723+```
724+
725+```hoon
726+%- |= [x1=@ x2=@]
727+ (pro:si (dif:si x1 x2) (dif:si x1 x2))
728+[--2 -5]
729+```
730+
731+Like Lisp, Hoon yields a lot of power to the user–developer. One could implement a fairly regular Lisp on top of Hoon with very few changes—and perhaps even implement a pure-Hoon discipline yielding a statically-typed Lisp à la TypeScript from JavaScript.
732+
733+- [~tacryt-socryp, “Hick, a more traditional Lisp than Hoon”](https://gist.github.com/tacryt-socryp/b08dc66b7bcc760e914c4db5c9fd7ba7)
734+
735+
736+## Philosophy
737+
738+Hoon's focus on atoms, static typing, and symbolic expressions make it a highly expressive and efficient language for building applications on the Urbit platform, while Lisp's flexible syntax and macro system make it a popular choice for a wide range of programming tasks.
739+
740+Lisp has evolved greatly since John McCarthy's founding. Like Unix, a complicated family tree has finally settled down into a few strong contenders: Scheme, Common Lisp, Clojure, Racket.
741+
742+Lisp has tended to be fractious: as many have noted, and [Mark Tarver eloquently expressed](http://web.archive.org/web/20080803193859/http://www.lambdassociates.org/blog/bipolar.htm), the Lisp platform appeals to idiosyncratic visions for completist platforms. There's a looseness in the community's coherence as a result.
743+
744+For a few reasons, the Urbit community has managed to avoid such splintering (the [Urbit Classic joke](http://urbit-classic.org/) aside). With a single sponsoring organization, first Tlon Corporation and since 2022 the Urbit Foundation, to steward the ecosystem and a philosophical commitment to protocol-as-platform, Urbit should avoid partition into competing bazaars.
745+
746+Urbit's governing philosophy as a technical program is laid out in the [Precepts](https://urbit.org/blog/precepts). A sampling:
747+
748+> A.13. If you don't completely understand your code and the semantics of all the code it depends on, your code is wrong.
749+
750+> A.16. Explicit state is better than implicit state.
751+
752+> A.20. One hundred lines of simplicity is better than twenty lines of complexity.
753+
754+> D.3. Not being qualified to solve a problem is no reason not to solve it.
755+
756+There is significant overlap here with the ideals of the Lisp developer community present. Scheme like Hoon aims at minimalism and ample use of lambda expressions. [Clojure](https://www.clojure.org/about/rationale) aims at strengthening Lisp by building it on a modern platform (the JVM); it would agree with Urbit's disdain for nondeterminism: “pervasive, unmoderated mutation simply has to go”. Racket was designed for production systems and to some extent with a hope to unify parts of the developer stack.
757+
758+In many ways, Hoon is more Lisp-y than Lisp: that is, it represents a point more polar towards the telos of Lisp than any extant Lisp. By shedding the skin of lists and focusing on binary trees, Urbit achieves a deeper conceptual unification within itself. Hoon doesn't properly supersede Lisp—it requires running on a particular VM architecture, for instance—but Hoon's focus on typing, the nature of Hoon's binary-tree homoiconicity, and its employment of pure functional concepts make it a strong new tool for those to whom Lisp already appeals.
759+
760+Hoon goes farther than Lisp, however. Hoon is an accessible and practical, if unconventional, tool for simplifying the developer stack, ultimately to a single language. Ultimately, Urbit is a technical project to encode human digital freedom into the very protocol we use—with Hoon its nose-to-tail _lingua franca_. Hoon carries the torch that Lisp kindled into a new user-oriented future.
761+
762+To close, I quote Urbit Foundation CTO Ted Blackman on why Urbit follows its particular design discipline:
763+
764+> The promise of Urbit lies in its reimagination of the digital world using components that are as constrained and limited as possible. By adhering firmly to principle and doubling down on minimalism at every turn, we get an OS that provides far stronger guarantees than Unix with a thousand times less code. Given the complexity of modern software, this is what's required to put personal computing back into the hands of people. (Ted Blackman ~rovnys-ricfer, [“Why Hoon”](https://urbit.org/blog/why-hoon))
content/blog/interplanetary_commerce.md+2−1
@@ -2,6 +2,7 @@
22title = "Interplanetary Commerce"
33date = "2021-04-08"
44description = "OS-level commercial primitives."
5+tags = ["bitcoin"]
56
67[extra]
78author = "Christian Langalis"
@@ -33,4 +34,4 @@ The Urbit Foundation is soliciting contributors to this project through Urbit Gr
3334
3435## An Ocean
3536
36−After honing our commercial tools on these use-cases, we’ll sail into a blue ocean. On the horizon: beautiful products, deployable at scale, built with the robust primitives of Urbit OS. Extensibility is Urbit’s promise to middle-men: every Web2.0 service they use to scalp us will find its P2P analog on Urbit. We invite developers and entrepreneurs of all stripes to join in the feeding frenzy. Ideas are constantly nucleating in [Urbitcoiners](web+urbitgraph://group/~pindet-timmut/urbitcoin-cash) and [Urbit Community](web+urbitgraph://group/~bitbet-bolbel/urbit-community/graph/~darrux-landes/business-building-on-urbit).
37+After honing our commercial tools on these use-cases, we’ll sail into a blue ocean. On the horizon: beautiful products, deployable at scale, built with the robust primitives of Urbit OS. Extensibility is Urbit’s promise to middle-men: every Web2.0 service they use to scalp us will find its P2P analog on Urbit. We invite developers and entrepreneurs of all stripes to join in the feeding frenzy. Ideas are constantly nucleating in [Urbitcoiners](web+urbitgraph://group/~pindet-timmut/urbitcoiners) and [Urbit Community](web+urbitgraph://group/~bitbet-bolbel/urbit-community/graph/~darrux-landes/business-building-on-urbit).
content/blog/io-in-hoon.md+2−2
@@ -132,9 +132,9 @@ When inventing a new system, you should consider which of these you intend to su
132132
133133So much for exploring the space of IO solutions. In terms of deployed code on Earth, the split is about 90% imperative, 5% monadic, and 5% state machine. In Urbit, the split is about 90% state machine and 10% monadic. This is what I intend to explain and defend.
134134
135−Urbit's OS is called Arvo; it has several "kernel modules" called vanes, and it has userspace applications. Colloquially these are called "apps," but when speaking about them abstractly, it's helpful to use their more specific name: ["agents"](https://urbit.org/docs/tutorials/arvo/gall/#agents). Arvo, the vanes, and agents are all structured as explicit state machines.
135+Urbit's OS is called Arvo; it has several "kernel modules" called vanes, and it has userspace applications. Colloquially these are called "apps," but when speaking about them abstractly, it's helpful to use their more specific name: ["agents"](https://developers.urbit.org/reference/glossary/agent). Arvo, the vanes, and agents are all structured as explicit state machines.
136136
137−In addition, there are ["threads"](https://urbit.org/docs/tutorials/arvo/gall/#threads), which are structured as monadic IO. Note there's only a superficial resemblance to Unix threads: they are not executed in parallel and they don't share memory, or at least not any more than agents do. They're simply a computation that takes an argument and produces a result, possibly after doing some IO, structured monadically.
137+In addition, there are ["threads"](https://developers.urbit.org/reference/glossary/thread), which are structured as monadic IO. Note there's only a superficial resemblance to Unix threads: they are not executed in parallel and they don't share memory, or at least not any more than agents do. They're simply a computation that takes an argument and produces a result, possibly after doing some IO, structured monadically.
138138
139139As you can see, all the lowest levels of Arvo are explicit state machines, and only the highest layer supports monadic IO. To see why this is the case, let's list advantages and disadvantages to each type. Note that, while I'm speaking specifically of agents and threads in the context of Urbit, these are fundamental properties of monadic and state machine IO.
140140
content/blog/pin-the-face-that-launches-a-thousand-ships.mdnew file+146
@@ -0,0 +1,146 @@
1++++
2+title = "Pin the Face that Launches a Thousand Ships"
3+date = "2023-04-07"
4+description = "A guest post by ~nospex-larsut"
5+[extra]
6+image = "https://storage.googleapis.com/media.urbit.org/blog/6a0120a85dcdae970b016766c94c14970b-800wi.jpg"
7+author = ""
8+ship = "~nospex-larsut"
9++++
10+_The original article can be found [here](https://nospex-larsut.arvo.network/blog/whyhoon) using [%blog](https://urbit.org/applications/~hanrut-sillet-dachus-tiprel/blog)._
11+
12+![](https://storage.googleapis.com/media.urbit.org/blog/6a0120a85dcdae970b016766c94c14970b-800wi.jpg)
13+
14+## Pin the Face that Launches a Thousand Ships[^1] ##
15+_A short piece addressing some of the standard hesitations to learning Hoon, considered in light of all of the recent exciting network activity._
16+
17+### Setting The Table ###
18+One can draw many distinctions between the Urbit apps that were available this time last year and those released thus far in 2023, but the most important of these may be that the former were apps noticed and used almost exclusively by users already on Urbit, where the latter - notably Pongo, Realm, Tirell Studio, Groups 2, Portal, etc - are apps that are _creating Urbit users_.
19+
20+Prior to the start of 2023, the superficial, yet incomplete, take was something to the effect that much of Urbit’s appeal was largely an affinity with the ideas and principles surrounding the project.
21+
22+People who found their way to Urbit latched on to philosophical entry points, among them values such as calm computing, decentralized/privacy/data-ownership maximalism, or aspirations of replacing a generations-deep legacy computing system that entrenched an ethos of doing things fundamentally inefficiently & incorrectly, in ways that not only hobbled the potential of the internet, but resulted in outright harm to its users through establishing platform models and incentives that consciously sought to manipulate the behavior of those users in countless subtle and not-so-subtle ways.
23+
24+Urbit was a nexus, collecting people from disparate backgrounds & disciplines to something like a spiritual oasis, yes, though one seemingly situated a million miles from anywhere familiar to the outside world; its appeal was more a function of the shared ethos of the community and a shared sense of its potential rather than the existence of new & immediately useful alternatives for day-to-day compute tasks.
25+
26+The energy of Assembly '22 was palpaple; it almost seemed that widespread adoption was around the corner. Inevitably, some of the post-Assembly ‘22 buzz seemed to fizzle as the ensuing months went by; many ships launched during that time went dormant, wondering if the potential hinted at would materialize; the shallow criticisn/meme for getting on to Urbit became, “I’m here… um, now what.”
27+
28+This whole time though, the project was simultaneously also an incredibly busy construction site.
29+
30+Remarkably short-lived, “I’m here… um, now what?’ is unraveling with the realization that this universe has always been accelerating, and this new wave of apps establishes a very visible & powerful reference point for truly appreciating that acceleration and the distance traveled; after what seemed like a brief post-Assembly fizzle, the network is again kinetic and crackling with energy, but in reality it was never slowing down.
31+
32+The latest generation of apps marks an important shift in the trajectory of Urbit adoption. Much of this is possible thanks to the proliferation of hosting options - whether [Native Planet’s](https://nativeplanet.io/) self-hosted solutions or through turnkey models - which collectively have vastly streamlined the Urbit onboarding process such that getting on the network is no longer the equivalent of scaling a forbidding & remote mountain peak, arriving at the threshold of a silent monastery, heaving its heavy door ajar to find it seemingly abandoned only a thin sliver of light to illuminate your path, nobody there to acknowledge your arrival much less offer a tour. The thrill of having finally gotten there dampened by the increasing sense that all of its life is subterranean and the real journey is just beginning.[^2]
33+
34+Single-click onboarding and preloaded apps & groups may not seem like a lot for newcomers, but these things have increased tremendously the ability to get on Urbit compared to just six months ago.
35+
36+And just as a selection of competing hosting providers expanded the number of possible onramps, this new crop of Urbit apps likewise provides a complimentary function as entry points - hidden doors to Urbit embedded in the Apple/Android app stores - in ways that Urbit apps never enjoyed previously, all helping to further reduce the friction of onboarding by orders of magnitude. A user searching for a Telegram alternative stumbles across Pongo; new eyes find Urbit without ever intentionally seeking it out.
37+
38+The animating ideas behind the project, I think, remain as alive as ever - Urbit does not need to jockey to become the ‘current thing’ if it can much more efficiently become the undercurrent thing; without having to waste a single breath converting users at the margin on the necessity or virtue of recreating the web in a decentralized & privacy-oriented manner, new users are able to become advocates for apps that provide practical utility for day-to-day compute, creative, and communication needs - but that also happen to be built on such infrastructure. The yew tree doesn’t propagate itself by trying to convince the bird that it is desirable that there be more yew trees in the world, it just wraps its seed in a tasty & nutritious berry and lets the bird carry it off.
39+
40+Compelling apps, built on continually-improving and innovative infrastructure & development tooling is one piece of the adoption curve. These things bring users, who bring perspectives, feedback, ideas, wants, and needs. It brings their attention to earn it. If they are spending time on Urbit apps, they will also be exposed to whatever else is being shared on Urbit through those apps – what will catch their attention that maybe they are not seeing elsewhere? Suffice to say this is all basically network effects 101, so on to the question of learning Hoon.
41+
42+### Some Grains of Salt ###
43+Perhaps that was a lot of table-setting to get to the original inspiration of this piece, in which I wish to present some arguments to the standard objections or concerns that seem to arise for people thinking of learning Hoon. My aim is not to twist any arms or legs, but only to offer some considerations for those on the fence. Hopefully the preceding bit of history at least reveals some shred of the potential opportunities for Hooners (and other creatives - we absolutely need those as well).
44+
45+But first the grain of salt with which you should take the following:
46+I currently Hoon at something approximating a tenth-grade level. I am by no means a natural born developer, nor am I moving towards a dynamic career switch to full-time Urbit dev. Not by any stretch of the imagination. While I am interested in continuing to learn Hoon for a variety of reasons, none are likely to reverberate very far beyond my own ship.
47+
48+My Hoon education began in the summer/fall ’22 cohort of Hoon School Live. In my early 40’s, I walked into it slightly intimidated by its reputation, and with a personal technical background not much deeper than writing Excel formulas, a little Python, and building simple websites (like, 20 years ago). At the moment, I am much better at reading it than writing it, but thanks to HSL & ASL (and everyone involved with those efforts), it does make sense to me.
49+
50+So despite not exactly practicing what all I am about to preach, the foregoing, combined with having talked to enough people on the fence about learning Hoon, I feel somewhat qualified to at least offer some perspective for those considering the question.
51+
52+### The Standard Hesitations ###
53+The following hesitancies seem to be the recurring ones, and we’ll take them one at a time, although they share a significant degree of overlap.
54+<ol>
55+<li> But I already know languages x, y, z, etc and can build things with them now.</li>
56+<li> I hear Hoon is very difficult / weird / etc.</li>
57+<li> Urbit’s future is uncertain; investing in learning Hoon seems risky.</li>
58+<li> I don’t see many immediate jobs for Hoon devs.</li>
59+</ol>
60+
61+__Hesitancy 1: But I _already know_ languages x, y, z, etc and can build things with them _now_.__
62+
63+A valid contention in that one has invested in skills they are eager to put to use or continue to use. But can you build what you want to build - and where you want to build it? And what is the cost in terms of personal satisfaction to working on something which doesn’t truly excite you?
64+
65+There is something of the sunk-cost fallacy is at work here. It is not always a bad impulse, and opportunity costs are very real. But if there is something compelling about Urbit - and the fact that one is at least seriously considering learning Hoon suggests this is the case - and one is willing to view their existing proficiency in some other language as a demonstration of their capability to learn any programming language, then existing knowledge should not act as a barrier to pursuing new knowledge, particularly if there is a suspicion that working on Urbit may afford more intellectually stimulating and enjoyable opportunities.
66+
67+Consider also that a person working on things that truly animate them, despite maybe being relatively less experienced in the language, nonetheless has much more room to grow in a smaller pool where they may create closer connections, have more access to the perspectives of experienced devs, and get noticed for their contributions faster than those that may exist for a person working on things they are decidedly less passionate about amidst a pool of thousands.
68+
69+Yet another upside of working in Urbit is the sheer amount of projects yet to be built (not all require Hoon, btw); projects that may be intriguing to a developer but which already exist in some other language/product have yet to be built on here, and there is a need for them. The amount of still low-hanging fruit and infrastructure work remaining to be done, let alone potential app and utilities, is substantial, and this is a community that generally speaking, respects anybody who can come in and start contributing with minimal direction or permission.
70+
71+And is time spent learning Hoon really time spent not building things? Are you not building skills, reputation, friendships, problem-solving skills, camaraderie - building a better self - throughout the learning process? One can easily present the argument that the cost in this regard is much less than it may seem at first glance.
72+
73+Since one can only try to subjectively weigh the opportunities open to them with their current skills against the nebulous costs of _not_ pursuing something that has piqued their interest, the dilemma often cannot but remain unanswered until one takes the steps to find out; until then, it remains a persistent, nagging 'what if'?. It may take several months to feel really comfortable writing Hoon, but there is a relatively low cost to spending a few weeks to dive in and see if one has an aptitude or affinity for it.
74+
75+__Hesitancy 2: Hoon is difficult and/or weird.__
76+
77+Recognizing that there are a lot of runes, and that Hoon is odd compared to other languages,
78+
79+- learning just a handful[^3] of them along with the basic families (create cores with | runes, call functions with % runes, conditionals statements are built with ? runes, etc) will get one well on their way. </li>
80+- if Hoon is not your first language, you have already demonstrated a capacity for becoming comfortable working within a framework of structure and syntax that was, relative to your previous inexperience, alien and weird. And while there are additional wrinkles in dealing with a functional language, the majority of CS concepts remain relevant and are transferable.
81+
82+And if Hoon is your first language, it is all uncharted territory anyway and not having anything to compare it to means one is essentially in the same situation as in learning any new language, and in that respect it mirrors almost any endeavor to grasp new modes of problem-solving under a unique set of conditions and constraints. Even if you do not stick with Hoon, the new perspectives in problem-solving experience are valuable, and most of the fundamental concepts will be transferable to other languages.
83+
84+You might also consider how to use Hoon’s reputation for difficulty to your advantage from the standpoint that, if you are firmly convinced that it is or will be unduly difficult, then that should yield a much deeper satisfaction after proving you are in fact capable of learning it.
85+
86+And from a more opportunistic standpoint, realize that others who allow this reputation to dissuade them create outsized opportunities for those who are willing to learn it. One can very usefully calibrate expectations here to use the reputation to provide some cover - if it really is that hard, iit is ok to not get it at first, and you can succeed where others gave up or failed to even try.
87+
88+Speaking from my own experience, the sheer amount of terminology was somewhat overwhelming at first, and this was true of both HSL & ASL (more so the latter, IMO). Many of the names seem arbitrary, but like anything, making it familiar is largely a function of effort.
89+
90+Recognize that Hoon's unique syntax and functional paradigm are integral to its design and purpose. Instead of trying to force parallels between Hoon and other languages or concepts you already know, just immerse yourself in it with an open mind and willingness to grasp its distinct features and the reasoning behind them.
91+
92+<div class="polaroid">
93+ <img src="https://storage.googleapis.com/media.urbit.org/docs/userspace/hoon-school/binary-tree-bottom-row-full.png" alt="Tree">
94+ <div class="container">
95+
96+ <p>See - it's easy!</p>
97+ </div>
98+</div>
99+
100+__Hesitancy 3: Urbit’s future is uncertain; investing in learning Hoon seems risky.__
101+
102+Much of the table-setting for this piece was an attempt to frame the potential opportunity for devs of any level. Keeping things in perspective, Urbit is just about to hit [3,000 active ships](https://twitter.com/urbitfoundation/status/1637931937351491584). There are several reasons why recent activity may be much more indicative of even greater future growth than one might assume from looking at the chart:
103+<ul>
104+<li>a. Maybe very obviously, the growth of the last three months is not simply a 1:1 reflection of the work of the last three months, but of the many preceding years of core development that made a significant increase in percentage terms within a very short interval possible. The stage is set for much faster growth.</li>
105+<li>b. Previously mentioned, but all these threads are interconnected in that, the more eyes on Urbit, the more ideas, talent and additional users will be introduced to, and recognize the depth, of the opportunity here. A steadily stabilizing building environment (thanks to a)) that attracts and can support more users should continue to build momentum. </li>
106+</ul>
107+
108+Remaining sober about reality, 3,000 users is not exactly a ton in web 2 terms; for Urbit, it is simultaneously very many and very little. But with better apps providing more reasons to be on Urbit, working in unison with better UX and onboarding, those users have more reason to stay engaged with Urbit once they are on, which means anything an aspiring Hooner or creator can think of to give them compelling reasons to make them even more engaged is an opportunity.
109+
110+Deliberately twisting the fomo screws a little, it is as true for learning Hoon as it is of anything else that the more widely adopted a platform or language becomes, the safer a bet it will be in terms of stability and longevity. With the accretion of that stability however, the window for realizing the benefits of gaining early experience and exposure in a less-crowded space diminishes accordingly as the sense of perceived riskiness in staking ground there decreases. Like any investment, uncertaintly about the future carries the gift of a difficult to quantity but very real species of camaraderie, credibility, and respect that is only available to those willing to get involved at early stages, and which is lost as the project starts to look increasingly like a 'sure thing.' Hard to value, but weigh that aspect when considering if one should begin learning now or wait until things look ‘slightly more certain’ - what is the bar for this certainty? What is ‘certain enough’?
111+
112+Urbit, by (beautiful) design, is a very low-time preference project in some respects, but it is growing quickly. And the longer you’ve been watching Urbit grow, the more perspective you have of how much can happen in a very short time.
113+
114+When there are 10,000, 100,000 active ships it will be a trip in itself to remember that you started learning Hoon back when there were "only" 3,000, and contributed in maybe some non-trivial way to attract some quantity of new ones by building something you were excited about building.
115+
116+__Hesitancy 4: I don’t see many immediate jobs for Hoon devs.__
117+
118+_Not yet you don’t_. Much of the response to Objection 3 is also relevant here.
119+
120+The pool of Urbit companies is not fixed. It is not an insurmountable obstacle to start up a small-scale dev shop with a handful of talented devs.
121+Money flowing into Urbit is being reported with increasing frequency, and this is only the incoming money that you _hear about_. As Urbit grows, money will chase money, bringing more jobs and more opportunities. For better, or worse, of course, money changes things - more money will necessarily mean more discipline, more focus on shipping product, etc. But not having money changes things too. Money comes here in no small part because it sees the energy and intensity with which this community has been building out Urbit - regardless of whether money was flowing in or out of it - it attracted devs because the project itself was an ambitious worthwhile good in itself.
122+
123+There is much opportunity here for bright, motivated developers willing to make the effort to learn. One only has to bump the total current dev headcounts up against the growing momentum of the project to see the opportunity, whether it be in core projects, apps, or novel pairings with creators to determine ways to distribute and produce content on Urbit. The speed of deployment on Urbit compared to other projects and relative exposure to other platforms affords a significant advantage to motivated, talented people in terms of visibility - when an app gets published on Urbit, everyone sees it.
124+
125+### Wrapping Up ###
126+Hopefully the above provides some perspetive on reframing some of the standard hesitancies. None of them are irrational. However, if none of the above sways you, ask what projects or features might materialize on Urbit that would make you wish you started learning Hoon a year ago (which, in the grand scheme, would make you a reasonably well-experienced Hooner) and then consider that you could wait for that thing to materialize, or play an active part in making it a reality that will attract many other users to the network, along with making others feel like they should have started learning Hoon a year ago.
127+
128+And if the Hoon question is indeed a recurrent & nagging one, attempt to replace it with the question, “two months from now (approximately the duration of an HSL cohort), would I rather have tried learning Hoon and discovered that I don’t like it and be done with the question, or still be sitting here wondering if I should learn Hoon?”
129+
130+The resources for learning Hoon are growing:<br>
131+● [Hoon School Live](https://developers.urbit.org/courses/hsl)<br>
132+● [App School Live](https://developers.urbit.org/courses/asl) <br>
133+● [App Workshop Live](https://developers.urbit.org/courses/awl) <br>
134+● An upcoming [Core Dev course](https://developers.urbit.org/courses/csl)<br>
135+● The growing corpus of [documentation](https://developers.urbit.org/reference/hoon/overview)<br>
136+● And of course the most valuable resource of all is all the people on the network who are willing to answer questions and help one learn. Find them in the Hacker House.
137+<p>
138+
139+If something about Urbit is drawing you toward it, if the project resonates with you in a way that other things in tech do not - if you are truly intrigued by it and want to be here - it is reasonable to assert that the process of learning Hoon is not simply a tax with questionable upside, but a productive process in and of itself; that the very process of learning it will embed you deeper into a space you want to be in.
140+
141+So learn Hoon. Not only is it fun, but as an Urbiter, it is something of a cultural heritage, and the conduit between reality and whatever your endless imagination conceives Urbit’s potential to be - space here is wide open, and any of today’s aspiring Hooners has the potential to pin the face that launches a thousand ships.
142+
143+----------------
144+[^1]: To 'pin a face' is to declare a variable in Hoon.
145+[^2]: Maybe some slight dramatization; this aspect also made it fun for those not in need of immediate gratification.
146+[^3]: [See 'Rune Utilization in Hoon'](https://developers.urbit.org/blog/rune-frequency-202212)
content/blog/urbit-and-bitcoin.md+1−1
@@ -2,7 +2,7 @@
22title = "Urbit and Bitcoin"
33description = "A sound money deserves a sound computer."
44date = "2019-10-16"
5−
5+tags = ["bitcoin"]
66[extra]
77author = "Christian Langalis"
88ship = "~pindet-timmut"
content/blog/urbit-creator-daos.mdnew file+74
@@ -0,0 +1,74 @@
1++++
2+title = "Urbit + Creator DAOs with Justin Murphy"
3+date = "2022-10-05"
4+description = "Creator DAOs are blank slates, new foundational cryptographic patterns just beginning to take shape. Justin Murphy thinks Urbit is the most obvious place to start building one."
5+
6+[extra]
7+author = "Isaac Simpson"
8+ship = "~mogmet-tadnem"
9+image = "https://storage.googleapis.com/media.urbit.org/blog/creatordao-3.jpg"
10++++
11+
12+![Image](https://storage.googleapis.com/media.urbit.org/blog/creatordao-3.jpg)
13+<div style="font-size:13px; text-align: center; color: #999">Photo by <a href="https://unsplash.com/@nathynmasters
14+">Nathyn Masters</a></div>
15+
16+# Other Life: Proto Creator DAO
17+
18+Justin Murphy runs a creator network. As a thinker, writer, and podcaster, he works to grow value within this network in order to stay independent. No ads. No branded content. Just varying degrees of membership, with members enjoying private channels and cohort-based courses all under the header “Philosophy and technology for the ungovernable.”
19+
20+Murphy’s “personal media company,” called Other Life, is composed of a newsletter, podcast, Youtube channel. It also extends to Urbit; [Other Life](https://urbit.org/groups/~hatryx-lastud/other-life) is one of the largest groups on the network. Followers and friends of Other Life create and share their own work within the network, aided by a catalog of courses. Murphy’s next logical step is building what we’re calling a Creator DAO: all the same stuff, but instead of a la carte memberships you secure your spot via ERC-20 tokens. In exchange, you get access to all levels of his community and content and attain the rights and responsibilities inherent to any DAO member.
21+
22+![Image](https://storage.googleapis.com/media.urbit.org/blog/otherlife.png)
23+
24+Since Creator DAOs are blank slates, primordial cryptographic objects just beginning to take shape, Murphy thinks Urbit is the most obvious place to start building one. Urbit lets creators spin up flexible DAOs to find, manage, keep members engaged in entirely new ways.
25+
26+
27+# Democratized Publishing
28+
29+In contrast to centralized programs like Discord, Urbit offers creators far more flexibility in interacting with their fanbases. Say, for example, you want to set up a trustless contribution program for guest writers. The Urbit app [Straw](https://urbit.org/applications/~pocwet/straw) supports group curation with voting on proposed articles. To increase guest engagement and expand participation while also maintaining quality control, Murphy can use Straw to initiate votes on his own pieces or potential guest pieces, which automates publication to the clear web when a vote passes.
30+
31+“Imagine I want to publish to the [Studio](https://urbit.org/applications/~tirrel/studio) newsletter, and when I go to click publish it first gets sent as a proposal to Straw, and it only actually gets published if a majority of the group agree that it passes the quality bar. As Straw develops, you can imagine that if the proposal is passed, two things happen. One: the post in the Urbit notebook gets sent to the email newsletter through Studio. Two: money is transferred.”
32+
33+Indeed, future functionality will enable automated payments after publication.
34+
35+![Image](https://storage.googleapis.com/media.urbit.org/blog/straw.jpg)
36+<div style="font-size:13px; text-align: center; color: #999;">The Straw App</div>
37+
38+“I’ll offer bounties, making a list of topics that I want people in the group to write about,” says Murphy. “They can publish permissionlessly to the group blog, through Studio and anyone in the group could potentially publish on any set of topics, kind of replicating a multi-author magazine.”
39+
40+Straw opens up a whole new way to decide what—and who—creators publish next. We’re the last to advocate art-by-democracy, but the potential is huge.
41+
42+# Decentralized Kicking and Adding
43+
44+Urbit also offers a novel solution with regards to vetting group members and weeding out bad ones. As Murphy points out, Holium’s Urbit app Ballot—which works like a decentralized [Snapshot](https://snapshot.org/#/) for Urbit Groups—allows creators to decentralize the expulsion process. A shift which many who run creator networks would much prefer.
45+
46+> If someone makes a proposal in [Ballot](https://urbit.org/applications/~lomder-librun/ballot), and maybe the owner gets to decide the threshold where if a certain amount of people want to kick someone out, they're kicked. It's actually a really annoying burden, in some ways, to know who to kick out. How bad does someone have to bet? You can have all the rules and regulations you want and try to be as objective as possible, but ultimately the owners and the admins have to use their judgment to decide. I would frankly much rather not have that responsibility. I would love for it to be hardwired such that only a super majority, or something like that, could do it. You can imagine that as a custom action on Ballot.
47+
48+One can imagine this custom action with a combination of Ballot and the [Forms](/applications/~donpub-datdux/forms) app. Since the form data is all on Urbit, it would be a simple matter for an app like Ballot to automatically access that information. With a few forms to vote on membership, this would make adding members equally simple, automated, and trustless as kicking them.
49+
50+“I think the Forms App is cool. You can use it on certain channels where if you want to get in, you fill out a form, then it's evaluated by Ballot. So the content of a form submission gets plugged into a proposal. People vote on the information supplied in the form and if the vote is approved, then the person gets added to the channel or group.”
51+
52+# An Owned Space
53+
54+These use cases help with DAO flexibility, usability, and decentralized automation. But another important reason to build a DAO on Urbit is that you’re building your network on P2P “real estate.” On Urbit, both creators and their communities own the address space and every action taken in it—it can’t be canceled or deleted or made inoperable, a far cry from other platforms where you can be suspended for arbitrary Terms of Service violations.
55+
56+“The main positive is you and your community getting to own the real estate that you operate on,” says Murphy. No other app, even dapps like Agora or Snapshot, allows for a genuinely P2P offchain operating environment. Your Urbit ID is self-owned and portable, and you build your community P2P. Your creations are yours and you can continue building them without corporate middlemen ripping your canvas out from under you, or changing your tools or access without notice.
57+
58+![Image](https://storage.googleapis.com/media.urbit.org/blog/otherlifegroup.png)
59+<div style="font-size:13px; text-align: center; color: #999">~hatryx-lastud/other-life</div>
60+
61+Furthermore, the more work you put into building your Creator DAO on Urbit, the more valuable the Urbit address space becomes. When you use Facebook, you’re relegated to the role of a content serf. The more you produce, the more Facebook grows in value. On Urbit, the more your produce, the more Urbit grows in value—and you are an owner of Urbit.
62+
63+![Image](https://storage.googleapis.com/media.urbit.org/blog/justinmurphy.jpg)
64+<div style="font-size:13px; text-align: center; color: #999">Murphy already offers his members access to the Other Life urbit group.</div>
65+
66+Finally, Murphy cites Urbit’s durability.
67+
68+> The second most important Urbit trait after ownership is durability. The creator economy tools change all the time. Every time you try to move your people from one new app to another app, you lose a lot, right? You want to be an influencer, you want to be an important thinker and speaker. All of a sudden, you’ve got to be on Clubhouse! This means telling the people on your newsletter, telling your Patreon subscribers, telling the people on your podcast, hey, download this cool new app called Clubhouse and find me there. It's going to be awesome. It's so cringe and corny and only a small number of them will even make it over there. Then all of a sudden, no one's on Clubhouse and no one wants to use Clubhouse anymore. This is a major problem for people navigating the creator economy. I think one of the big selling points of Urbit is—this is the one place that I’ll always be. I (will have) been working on my Urbit for over 10 years. This thing is going to be the nuclear bunker of the internet.
69+
70+Creator DAOs are perhaps the smallest, most nimble type of DAO—a creator, his followers, and the content they share between them. For that reason, they’ve been underplayed as archetypal DAOs. But their small size and flexibility may make them the perfect candidate to realize the possibilities of immensely improved DAO experiences.
71+
72+—
73+
74+*Isaac Simpson is a Los Angeles based writer and the founder of the marketing agency [WILL](https://willtheagency.com/). You can read his work on his substack [The Carousel](https://thecarousel.substack.com/).*
content/blog/using-urbit-in-2023.mdnew file+55
@@ -0,0 +1,55 @@
1++++
2+title = "Using Urbit in 2023"
3+date = "2023-02-06"
4+description = "There are more ways to run Urbit than ever, and more options coming soon."
5+[extra]
6+image = "https://storage.googleapis.com/media.urbit.org/blog/usingurbit-2023.jpg"
7+author = "Josh Lehman"
8+ship = "~wolref-podlex"
9++++
10+
11+![](https://storage.googleapis.com/media.urbit.org/blog/usingurbit-2023.jpg)
12+
13+Recent years have seen several iterations on ways to run an Urbit node and join the network. [Port](https://github.com/latterbolden/port) and support for running Urbit from Windows were added a couple of years ago and have previously been recommended ways of running Urbit. We no longer recommend these options for the vast majority of users in favor of better options that are now available.
14+
15+Read on to learn about the background underpinning these decisions and your options for joining the network going forward.
16+
17+
18+
19+# Background
20+
21+With the introduction of Landscape in 2020 the demand for being on the network rose substantially from what it had been, yet the only way of running Urbit was through the command line, which was a significant barrier for entry.
22+
23+In 2021 Port and a native Windows binary were both introduced via contributions from the open source community: Port was built via our [grants](https://urbit.org/grants/cross-platform-desktop-urbit-app) [program](https://urbit.org/grants), and the Windows binary was contributed via a [pull request](https://github.com/urbit/urbit/pull/4675). Together, these two projects enabled users to run Urbit locally without requiring command-line knowledge. Port was summarily added as an officially recommended way to run Urbit.
24+
25+Over the course of 2022 it became clear that, while often useful for trying Urbit out, the experience of running Urbit locally via Port was fundamentally limited: Urbit runs best as a server, and laptops provide neither a stable running environment nor consistent web-based access from other devices.
26+
27+Windows presented further challenges, particularly around maintenance: our team of runtime engineers has had their progress stymied by the need to support Windows, which has substantially different requirements from macOS and Linux. It’s ultimately much more important to our team that we make progress on the versions of the runtime that run well in a server environment, which is the best way to use Urbit, than for local installations.
28+
29+Going forward we no longer recommend Port as an officially supported option for joining the network, and have dropped support for the native Windows binary as of version [1.16](https://groups.google.com/a/urbit.org/g/dev/c/3S6A8Qf8Qzg) of the runtime. That said, it’s worth noting that Port *is not deprecated*! It is still actively [maintained here](https://github.com/latterbolden/port) by the same people that have been maintaining it since the beginning.
30+
31+Let’s move on and talk about your options for getting on the network going forward.
32+
33+
34+# Joining the Network Today
35+
36+Over the course of 2022 many companies emerged and built products that will get you on Urbit, and their teams are constantly working to provide you with a great experience.
37+
38+If you’re not comfortable at the command line you should use a [hosting provider](https://urbit.org/getting-started/hosted). Hosting providers run your Urbit for you and take care of any ongoing maintenance required. If you eventually want to transition to running Urbit yourself, they’ll let you pack up your node and run it however you want: whether that’s at a different hosting provider or your own infrastructure. Learn about [recommended hosting providers in our getting started guide.](https://urbit.org/getting-started/hosting-providers)
39+
40+For more technical users the [command line](https://urbit.org/getting-started/cli) is still a reliable option. For casual testing you can boot a planet or comet on your local macOS or Linux-based machine, and for more serious usage you should refer to our [cloud hosting guide](https://urbit.org/getting-started/cloud-hosting) to get set up on a VPS. A newer option for self-hosting is [Native Planet’s](https://nativeplanet.io) suite of [software](https://www.nativeplanet.io/software) for turning a local computer into an Urbit server complete with DNS.
41+
42+
43+# Coming soon
44+
45+New options for joining Urbit are just around the corner.
46+
47+Word has it that [Tlon](https://tlon.io/hosting) will soon allow you to invite your friends to groups directly from within their [suite of applications](https://tlon.io/landscape), with onboarding handled seamlessly through their hosting service.
48+
49+[Holium’s Realm app](https://www.youtube.com/watch?v=gdu4QtFR-Bs), a collaborative desktop computing environment available on macOS (for now), allows users to sign up with an existing Urbit or brand new hosted one — all seamlessly surfaced through Realm’s signup flow. You can sign up for the private alpha [here](https://holium.com).
50+
51+Tirrel’s [Scene](https://planet.one/scene) is a desktop application with built-in hosting, like Realm, that works on macOS, Windows and Linux, and it’s available now. Hosting is powered by their [Planet One](https://planet.one) service.
52+
53+For the self-hosting enthusiasts out there Native Planet has created [purpose-built Urbit home servers](https://www.nativeplanet.io/hardware) that [make self-hosting easy](https://twitter.com/jmrphy/status/1616196970384887808) and look great doing it.
54+
55+Joining Urbit has never been easier, and it’s constantly getting easier. See you on the network!
content/bounties.md+18−12
@@ -1,15 +1,15 @@
11+++
22title = "Guide to Bounties"
3−date = "2022-02-16"
3+date = "2023-01-04"
44weight = 1
55description = "A guide to posting and claiming bounties"
66+++
77
8−Bounties are opportunities to do work on Urbit in exchange for address space or other funding. Bounties can be provided by companies, DAOs or individuals ("benefactors") in the Urbit universe. To the extent that they benefit the rest of the universe, the Urbit Foundation will [chip in on funding](#funding).
8+Bounties are opportunities to do work on Urbit in exchange for address space or other funding. Bounties can be provided by companies, DAOs or individuals ("sponsors") in the Urbit universe. To the extent that they benefit the rest of the universe, the Urbit Foundation will [chip in on funding](#funding).
99
10−For **workers**, bounties offer substantial funding opportunities and, like [apprenticeships](/grants/apprenticeships), are a good way to get hired by other organizations. Learn how to [work on a bounty here](#work-on-a-bounty).
10+For **workers**, bounties offer substantial funding opportunities and, compared to [apprenticeships](/grants/apprenticeships), are a way to take on larger challenges in a more autonomous manner. Learn how to [work on a bounty here](#work-on-a-bounty).
1111
12−For **benefactors**, bounties allow you to scale your workforce through the Urbit community, get critical tools built, or just fund cool projects that you want to see exist. Learn how to [post a bounty here](#post-a-bounty).
12+For **sponsors**, bounties allow you to scale your workforce through the Urbit community, get critical tools built, or just fund cool projects that you want to see exist. Learn how to [post a bounty here](#post-a-bounty).
1313
1414## Work on a Bounty
1515
@@ -17,29 +17,35 @@ You can see [open bounties here](/grants?program=bounty&open=true&wip=false&comp
1717
1818### How it works
1919
20−After applying, the Urbit Foundation will circulate the details of your application to the benefactor and schedule a follow-up interview should your application be accepted &mdash; think of it like a job application.
20+After applying, the Urbit Foundation will circulate the details of your application to the sponsor and schedule a follow-up interview to see if you would be a good fit for the project. Should your application be accepted, you will undergo a quick KYC process and recieve a contract for signature. Some bounties may also entail additional direct compensation from the sponsor for which the Urbit Foundation is not responsible for managing; please discuss these parameters directly with your sponsor.
2121
22−The benefactor of the bounty is ultimately responsible for signing off on completed work. They'll also be the primary point of contact while work is underway, although the Urbit Foundation may assign personnel to assist on bounties that it is particularly invested in.
22+The sponsor of the bounty is ultimately responsible for signing off on completed work. They'll also be the primary point of contact while work is underway, although the Urbit Foundation may assign personnel to assist on bounties that it is particularly invested in.
2323
24−Benefactors are vetted by the Urbit Foundation as trustworthy to ensure their ability to fund the work that they post. The Urbit Foundation also collaborates heavily with benefactors to ensure that the bounty is [well-specified](#well-specified-bounties), which ensures that your project is both properly scoped and technically viable.
24+Sponsors are vetted by the Urbit Foundation as trustworthy to ensure their ability to fund the work that they post. The Urbit Foundation also collaborates heavily with sponsors to ensure that the bounty is [well-specified](#well-specified-bounties), which ensures that your project is both properly scoped and technically viable.
25+
26+### Getting Paid
27+
28+After you've finished your work on a given milestone, you will need to get signoff from your sponsor. To do this, contact your sponsor with the details of the milestone completed, any relevant instructions, github repos, or app download links, and solicit review from your sponsor. They can submit their approval to the Foundation by contacting `~marfun-pacpet`, at which point you are ready to [submit an invoice](https://airtable.com/shrXXCs1uaxtNSBcg). Once the Urbit Foudnation receives approval from your sponsor and an invoice for the amount agreed upon in your grant or milestone, the Foundation will pay your star allocation to the Ethereum address you have provided.
29+
30+We approve and issue payments within 30 days of invoice receipt and approval, although often payment is made more quickly. If you have any questions regarding getting paid or submitting an invoice, please contact `~marfun-pacpet` for assistance.
2531
2632## Post a Bounty
2733
28−To get started with a new bounty, [submit it via this form](https://airtable.com/shr6ky4yshlhhqSm0).
34+To get started posting a new bounty, [submit it via this form](https://airtable.com/shr6ky4yshlhhqSm0).
2935
30−We at the Urbit Foundation ensure that all bounties have [clear specifications](#well-specified-bounties) &mdash; this ensures that they get what you pay for. If your bounty submission is missing details or could be otherwise improved, we'll provide that feedback and work with you to refine your bounty.
36+We at the Urbit Foundation will work with you to ensure that all bounties have [clear specifications](#well-specified-bounties) &mdash; this ensures that they get what you pay for. If your bounty submission is missing details or could be otherwise improved, we'll provide that feedback and work with you to refine your bounty.
3137
3238### Well-specified Bounties
3339
3440A well-specified bounty generally has these elements:
3541
3642- **Overview**: A clear description of what the worker will do to complete this bounty. It's a good idea to include a problem statement or rationale for the work.
37−- **Project Requirements**: An articulation of what constitutes complete work. User stories, Figma designs, interface specifications, and other technical constraints are all examples of requirements.
43+- **Project Requirements**: An articulation of what constitutes complete work. User stories, Figma designs, interface specifications, and other technical constraints are all examples of requirements. It is recommended to reference any specific requirements &mdash; such as key user stories &mdash; on a milestone level to ensure clarity in which requirements need to be met at each stage of the project.
3844- **Worker Requirements**: A description of the skills and/or qualifications required of a prospective worker. Technologies or skills known, years of experience, work schedule (e.g. time availability), and demonstrable accomplishments are all examples of this.
3945- **Milestones**: Logical segments of work that can be considered done on their own. Breaking the project up into smaller pieces will help a new worker pick up the work should that be necessary, keeps the worker motivated with incremental achievement and remuneration, and is generally a sign of a clear specification. Milestones don't always make sense; sometimes there's only one.
40−- **Timeline**: If you're trying hit a certain deadline, make sure to specify absolute dates on the milestones. Otherwise, use relative dates (e.g. _two months_) to give the worker an idea of how long each milestone will take. This helps form an agreement between benefactor and worker on volume of work, and grounds to seek other arrangements should schedules be missed.
46+- **Timeline**: If you're trying hit a certain deadline, make sure to specify absolute dates on the milestones. Otherwise, use relative dates (e.g. _two months_) to give the worker an idea of how long each milestone will take. This helps form an agreement between the sponsor and worker on volume of work, and grounds to seek other arrangements should schedules be missed.
4147
42−The more detail in the bounty's specification, the better the results.
48+The more detail in the bounty's specification, the better the results and the smoother your working relationship will be with a contributor. Once a contributor has been selected, parameters such as absolute dates or other open ended questions will be updated prior to contract to ensure there are clear expectations for all parties involved
4349
4450### Funding
4551
content/campus/_index.mdnew file+37
@@ -0,0 +1,37 @@
1++++
2+title = "Software Developers"
3+slug = "software-developers"
4+description = "Getting started as a software developer on Urbit"
5+sort_by = "weight"
6++++
7+
8+
9+Urbit offers foundational primitives that make it easy to build decentralized applications. This means developers can focus on creativity and application logic instead of operations to make sure the server or database doesn't go down.
10+
11+
12+Here are a few links to resources for developers:
13+
14+
15+### [Urbit Developers Overview](https://developers.urbit.org/)
16+An overview of using Urbit for development.
17+
18+### [Lightning Tutorials](https://developers.urbit.org/guides/quickstart/intro)
19+Get a feel for the process of making and deploying an Urbit app in half an hour, no previous experience required.
20+
21+### [Core Curriculum](https://developers.urbit.org/guides/core)
22+Learn the Urbit stack at your own pace.
23+
24+The Foundation also regularly runs a series of cohort-based live courses that go over the core curriculum, free and open to all. One lesson per week over the course of about eight weeks.
25+
26+### [Live Courses](https://developers.urbit.org/courses)
27+Learn the Urbit stack as part of a group.
28+
29+### [New Hooniverse](https://urbit.org/groups/~hiddev-dannut/new-hooniverse)
30+Discussion group for learning the Urbit stack. Open to beginner, intermediate, and advanced developers.
31+
32+
33+### [TomeDB](https://holium.gitbook.io/tomedb/)
34+A framework for building Urbit apps solely with Javascript.
35+
36+### [Grants](https://urbit.org/grants)
37+Build on Urbit and take ownership of the network in the process.
content/campus/blockchain-enthusiasts.mdnew file+35
@@ -0,0 +1,35 @@
1++++
2+title = "Blockchain Enthusiasts"
3+slug = "blockchain-enthusiasts"
4+description = "Learn how sound computing and sound money fit together"
5+weight = 4
6+[extra]
7+flatten_pagination = "true"
8+hide_next_title = "true"
9+hide_previous_title = "true"
10+image = "https://media.urbit.org/site/understanding-urbit/urbit-id/urbit-id-cards%402x.png"
11++++
12+
13+We have yet to see the promised Cambrian explosion of general-purpose decentralized applications promised by blockchains. What happened?
14+
15+While blockchains are good for some problems, there remain others where a more general purpose computing solution is more useful. This is precisely what Urbit is for. Urbit’s vision of sound, easy-to-use, decentralized computing dovetails neatly with that of sound, easy-to-use, decentralized money.
16+
17+Learn more on how Urbit and blockchains work together:
18+
19+### [Bitcoin on Urbit: The Sovereign Stack](https://urbit.org/bitcoin)
20+How Urbit and Bitcoin fit together
21+
22+### [Azimuth](https://developers.urbit.org/reference/azimuth/azimuth)
23+Urbit’s PKI system on Ethereum
24+
25+### [Uqbar](https://uqbar.network)
26+The Urbit-native blockchain
27+
28+The leader in this space is Uqbar, an Urbit-native layer 2 blockchain that settles on Ethereum.
29+
30+From their [clearpaper](https://uqbar-network.gitbook.io/uqbar-clearpaper/uqbar-clearpaper/uqbar-clearpaper):
31+
32+>Leveraging Urbit’s peer-to-peer infrastructure, Uqbar provides a blockchain-native decentralized operating system uniquely positioned to deliver the composable primitives necessary to build a rich, functional distributed application layer. It fuses the trusted settlement of Ethereum with the decentralization, security, and interoperability benefits of full-scale peer-to-peer networking, unlocking the latent power of programmable blockchains.
33+
34+
35+
content/campus/creatives.mdnew file+21
@@ -0,0 +1,21 @@
1++++
2+title = "Creatives"
3+slug = "creatives"
4+description = "Urbit for everyone"
5+weight = 5
6+[extra]
7++++
8+
9+Urbit offers creatives the means to truly own the distribution of their work. An application becomes a tool you own rather than a service whose terms can change overnight. And with digital ownership on a decentralized network, the incentives of advertising based centralized services and an attention economy no longer apply.
10+
11+What would the world look like with more decentralized digital ownership? Check out the links below for a preview.
12+
13+### [Tirrel Studio](https://urbit.studio)
14+
15+Host, publish, and earn on Urbit. See the [Mars Review of Books.](https://marsreview.org/)
16+
17+
18+### [Meetup Grant](https://urbit.org/grants/community-meetups)
19+
20+Through our Grants program, the foundation rewards community-builders who
21+host regular meetups and help people learn about the project.
content/communities/urbit-austin.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Urbit Austin"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-austin.png"
5++++
6+
7+Curious about Urbit? Questions about Hoon syntax? Fed up with the current state of the internet? Join us to talk about the internet's future.
8+
9+––
10+
11+[Meetup page](https://www.meetup.com/Urbit-Austin/)
content/communities/urbit-berlin.mdnew file+16
@@ -0,0 +1,16 @@
1++++
2+title = "Urbit Berlin"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-berlin.png"
5++++
6+
7+If you are sick of the current state of the web, of handing over your data and entire online presence to a handful of American corporations, of a web fueled with ads, then Urbit might be for you.
8+
9+Are you curious about Urbit and want to try it? Are you an Urbit OG looking to find to find others? Do you want to build your own peer-to-peer apps and leave the centralized web behind?
10+
11+We meet regularly in Berlin, and we try to have a theme or presentation for each meetup.
12+
13+
14+––
15+
16+[Meetup page](https://www.meetup.com/urbit-berlin/)
content/communities/urbit-christchurch.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "Urbit Christchurch"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-christchurch.jpg"
5++++
6+
7+Curious about Urbit? Questions about Hoon syntax? Fed up with the current state of the internet? Join us to talk about the internet's future.
8+
9+––
10+
11+[Eventbrite](https://chchurbit.eventbrite.com)
12+
13+[Telegram](https://t.me/chchurbit)
content/communities/urbit-cph.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Urbit København"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-cph.png"
5++++
6+
7+~norsyr-torryn/nordics
8+
9+––
10+
11+[Twitter](https://twitter.com/UrbitCPH)
content/communities/urbit-dc.mdnew file+19
@@ -0,0 +1,19 @@
1++++
2+title = "DC Metro Urbit Meetup Group"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-dc.png"
5++++
6+
7+This is a DC/Northern Virginia/Southern Maryland Urbit discussion group.
8+
9+It is for Urbit users or the urbit-curious or people who like to think and talk about decentralization, independence, and freedom on the internet.
10+
11+We will socialize, discuss urbit and related topics, and support lab and learning activities.
12+
13+Find us on urbit chat at ~tillys-fasryp/nova-urbit-meetup-lobby-3347
14+
15+––
16+
17+[Meetup page](https://www.meetup.com/dc-urbit-meetup-group/)
18+
19+[Twitter](https://twitter.com/dcurbit)
content/communities/urbit-denver.mdnew file+19
@@ -0,0 +1,19 @@
1++++
2+title = "Urbit Denver"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-denver.png"
5++++
6+
7+While Urbit is the animating force behind this group, people of all interest levels & familiarity with the project - be they long-time users, or newcomers simply wondering what the heck Urbit is - are welcome & encouraged to attend these meet-ups. The conversations are lively and span a wide variety of topics, ranging from Urbit to philosophy, tech, crypto, the arts, health and well-being, and much more.
8+
9+Our goal is simply to build a community of people interested in the project and the future it envisions, in which members can freely connect and discuss the project and the various ideas & values adjacent to it.
10+
11+And for those wondering what the heck is Urbit? Urbit is an ambitious reimagining of what the internet can be; it is a virtual computer and peer-to-peer network, built on a philosophy of human-scale computing, where you own all your data and identity. Urbit strives to once again make the computer a useful tool under the control of the user, and not vice versa. Still confused? Stop by and we'll (try to) explain it.
12+
13+––
14+
15+~nospex-larsut/mile-high-mars
16+
17+[Meetup page](https://www.meetup.com/mile-high-mars-denver-urbit-group/)
18+
19+[Organizer's Twitter](https://twitter.com/OnAPersonaLevel)
content/communities/urbit-london.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "Urbit London"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-london.jpg"
5++++
6+
7+Urbit London is a monthly, occasionally biweekly, meet-up series aiming to establish a long-lasting community within the London tech and cultural scene.
8+
9+––
10+
11+~tichus-holnet/urblon
12+
13+[Twitter](https://twitter.com/urblon)
14+
15+[Telegram](https://t.me/urblon)
content/communities/urbit-mst.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "Urbit MST (Utah)"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-utah.png"
5++++
6+
7+Are you looking for more than the options presented to you?
8+
9+Come to our Urbit (MST) meetup. All are welcome. Bring a computer and we can onboard you with a planet and hosting for free on site. Whether you are new to Urbit or fluent in Hoon, come and meet others in Utah interested in Urbit.
10+
11+––
12+
13+[Website](https://urbitmst.org/)
content/communities/urbit-ny.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Urbit NY"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-ny.png"
5++++
6+
7+We love experimenting with Urbit & tinkering with Arvo, Hoon, & Nock
8+
9+––
10+
11+[Meetup page](https://www.meetup.com/Urbit-New-York/)
content/communities/urbit-paris.mdnew file+23
@@ -0,0 +1,23 @@
1++++
2+title = "Urbit Paris"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbitparis.png"
5++++
6+
7+Join us for our monthly Urbit meetups in Paris!
8+
9+Whether you're a tech enthusiast, an established Urbit aficionado, or a newcomer to the scene, our community is meant to welcome and engage everyone.
10+
11+If you're confused about what Urbit is, no worries, most people are at first. Drop by and we'll give you our best explanations of what Urbit is and how it's going to change the internet as we know it.
12+
13+We'll introduce Urbit, help you boot your own ship, and make sure you go back home all set!
14+
15+See you there!
16+
17+––
18+
19+~solsup-soplyd/urbit-paris
20+
21+[Twitter](https://twitter.com/urbitparis)
22+
23+[Meetup](https://www.meetup.com/urbit-paris/)
content/communities/urbit-seattle.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Urbit Seattle"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-seattle.png"
5++++
6+
7+Urbit is a simple, durable computer that you own 100% and forever. In this group, we'll discuss ongoing project developments, technical details, and how to use Urbit. With occasional speakers that will present on various topics.
8+
9+
10+––
11+
12+[Meetup page](https://www.meetup.com/urbit-seattle/)
13+
14+[Twitter](https://twitter.com/SeattleUrbit)
content/communities/urbit-sf.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "Urbit SF"
3+description = ""
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-sf.png"
5++++
6+
7+Want to own and control the server side? Your digital identity, data and computation?
8+
9+So do we — so we're building Urbit. We set this group up for anyone excited about this kind of stuff, even those who think we're totally crazy.
10+
11+Come join us to talk about what the future of the internet might look like.
12+
13+––
14+
15+[Meetup page](https://www.meetup.com/urbit-sf/)
content/community/_index.mddeleted−5
@@ -1,5 +0,0 @@
1−+++
2−title = "Community"
3−sort_by = "weight"
4−template = "list.html"
5−+++
content/community/community-grants.mddeleted−14
@@ -1,14 +0,0 @@
1−+++
2−title = "Community Grants"
3−description = "Select Urbit address space grants for your group or community."
4−weight = 3
5−[extra]
6−hideprevious = "true"
7−hidenext = "true"
8−+++
9−
10−Interested in getting your community on Urbit? We are currently accepting applications for select groups to get started on Urbit together using an [invite pool](/using/id/creating-an-invite-pool).
11−
12−To get started, fill out the application below. Any information you share will be held privately, and only for the purpose of consideration for the grant.
13−
14−<iframe src="https://docs.google.com/forms/d/e/1FAIpQLSf_uD5fUw6xqoxtzUhSwURFYO57XQl067N3vEdy7_rTD8T2VQ/viewform?embedded=true" width="640" height="1394" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
content/community/governance.mddeleted−25
@@ -1,25 +0,0 @@
1−+++
2−title = "Governance"
3−description = "On the governance of the project, including both the senate of galaxies and the core developers."
4−aliases = ["/governance"]
5−weight = 4
6−[extra]
7−hideprevious = "true"
8−hidenext = "true"
9−+++
10−
11−Our goal is to design Urbit simply, such that as many decisions as possible are made by the architecture of the system itself – that is, code should be law whenever possible. Code can’t anticipate every eventuality, however, and so the system design must include mechanisms that allow decisions to be made outside of the code.
12−
13−Within Urbit, this form of governance is conducted by two groups: the senate of galaxies, and the body of core developers. The senate of galaxies is empowered to make changes to the solidity contracts which define Azimuth, Urbit’s PKI, by majority vote. This process is defined by the contracts themselves.
14−
15−An owner of a galaxy (or a delegate) can propose a new iteration of the contract logic. The proposal can then be voted on for a period of thirty days. Once that period is over, if at least a quarter of the galaxies has voted, and the majority is in favor, the old logic contract will hand over the reigns to the new one.
16−
17−In a similar process, document hashes can be proposed. While their off-chain documents can't be "technically enforced", this mechanism is useful for the Senate to record more abstract decisions.
18−
19−For off-chain process around proposals, as suggested by core developers, please see [senate.md](https://github.com/urbit/azimuth/blob/master/senate).
20−
21−The group of core developers manages Urbit’s [GitHub repository](https://github.com/urbit/), which controls Arvo, Urbit’s operating system. Changes and upgrades are decided upon by consensus.
22−
23−You can participate in the governance of the senate by acquiring a galaxy. If you would like to be involved with the governance of Arvo, check out our [developer guide](/docs/development/develop) to learn how you can contribute to core development.
24−
25−
content/community/hosting-a-meetup.mddeleted−82
@@ -1,82 +0,0 @@
1−+++
2−title = "Hosting a Meetup"
3−description = "Best practices for hosting your Urbit meetups."
4−weight = 2
5−[extra]
6−flatten_pagination = "true"
7−hidenext = "true"
8−hide_previous_title = "true"
9−+++
10−
11−There are already [a few](/community/meetups) Urbit meetups that take place in cities around the United States. Want to start a meetup in your home town? Consider these best practices.
12−
13−### Create the Meetup Group Online
14−
15−The most straightforward way to start a meetup group online, like on [meetup.com](www.meetup.com). Services like this offer messaging, calendaring, payments, discussion boards, and basic group profiles.
16−
17−There are other options available but, regardless of what you choose, there should be a public place on the Web for people to access the group.
18−
19−Group suggestions:
20−
21−- Meetup.com
22−- Google groups
23−- Dedicated Website
24−
25−### Spread the word
26−
27−It’s not much fun if people don’t actually show up, so it’s important to get the word out. Use your existing network to tell people about your event. Remember it takes time to build a community, so don’t be discouraged if only a few people show up at first. Post to social media and email your friends. Also, be sure to email [support@urbit.org](mailto:support@urbit.org), and we'll promote your meetup.
28−
29−Outreach methods:
30−
31−- Post to social media
32−- Email your friends
33−- Put up signs
34−
35−### Format
36−
37−Meetups are about sharing ideas and meeting like-minded people. There are a few formats that can help achieve this goal. As the organizer, take the lead and prepare ahead of time. Think of some topics for the group to discuss, and try to ensure that the conversation isn’t dominated by one or two people.
38−
39−Presentations and guided group discussions are great ways to share ideas. If you have a speaker for your event, coordinate ahead of time and make sure they have everything they will need to make a great presentation and ask them to arrive early to the event. If you have a speaker, be sure to record the talk so that it can be posted online.
40−
41−Format considerations:
42−
43−- Guided group discussion
44−- Presentation
45−
46−### Venue
47−
48−Your meeting location can determine the success of your event. Ideally, you’d want to be away from congested areas and find locations with good parking and transit options nearby. However, this isn’t always possible, so just do your best to accommodate. It’s also a good idea to locate the event near bars or restaurants so people can continue the conversation after the event officially ends.
49−
50−Location considerations:
51−
52−- Easily reachable
53−- Consider parking and distance to transit
54−- Check out public libraries
55−- Coworking spaces
56−- [peerspace.com](https://www.peerspace.com/)
57−
58−### Date and time
59−
60−Most people are able to attend meetups after work on non-holiday weekdays, between about 6-8pm. This isn’t true for everyone but it’s a good rule of thumb. It’s also a good idea to avoid holidays and days when there are large sporting events happening.
61−
62−Date considerations:
63−
64−- Weekdays
65−- Between 6pm and 8pm
66−- Avoid holidays and weekends
67−
68−### Stay consistent
69−
70−Like basically anything worth doing, meetups take time, patience, and consistency. Come prepared to engage with people and have a good time. The more often you can meet the stronger the community can become, so schedule meetups regularly.
71−
72−### Bonus
73−
74−Here are a few tips and tricks to consider with hosting a meetup. You don’t have to have all these things at your first meeting, but try adding them in as you go.
75−
76−- Names tags
77−- Door signs
78−- Projector
79−- Extension cords and power strips
80−- Video camera
81−- Lapel microphone
82−- Bring your own internet
content/community/meetups.mddeleted−47
@@ -1,47 +0,0 @@
1−+++
2−title = "Meetups"
3−aliases = ["/meetups"]
4−description = "Information on Urbit meetups and other community-led, Urbit IRL groups."
5−weight = 1
6−[extra]
7−flatten_pagination = "true"
8−hideprevious = "true"
9−hide_next_title = "true"
10−+++
11−
12−![](https://media.urbit.org/site/meetup1.jpg)
13−
14−Turns out that getting Urbit fans together in one room is pretty fun. Here's an incomplete list of community-led Urbit IRL groups. These events are generally informal and very approachable – feel free to dive in.
15−
16−Interested in hosting an Urbit event of your own? Follow our [guide to meetup best-practices](/community/hosting-a-meetup). Send an email to [support@urbit.org](mailto:support@urbit.org) and we'll list your meetup on this page.
17−
18−### Asia
19−
20−| Location | Contact information |
21−| :--------- | :------------------------------------------------ |
22−| Moscow, RU | [Timepad](https://urbitmoscow.timepad.ru/events/) |
23−
24−### Europe
25−
26−| Location | Contact information |
27−| :------------- | :---------------------------------------------------------------------------------------------- |
28−| Copenhagen, DK | [Twitter](https://twitter.com/UrbitCPH), [Meetup.com](https://www.meetup.com/Urbit-Copenhagen/) |
29−
30−### North America
31−
32−| Location | Contact information |
33−| :---------------- | :----------------------------------------------------------------------------------------------- |
34−| Phoenix, AZ | [Twitter](https://twitter.com/UrbitPHX), [Meetup.com](https://www.meetup.com/urbit-phx/) |
35−| San Francisco, CA | [Meetup.com](https://www.meetup.com/urbit-sf/) |
36−| New York, NY | [Meetup.com](https://www.meetup.com/Urbit-New-York/) |
37−| Toronto, ON | [Twitter](https://twitter.com/UrbitToronto), [Meetup.com](https://www.meetup.com/Urbit-Toronto/) |
38−| Eugene, OR | [Twitter](https://twitter.com/EugeneUrbit) |
39−| Austin, TX | [Meetup.com](https://www.meetup.com/Urbit-Austin/) |
40−| Denton, TX | [Twitter](https://twitter.com/UrbitDFW) |
41−| Seattle, WA | [Meetup.com](https://www.meetup.com/urbit-seattle/) |
42−
43−### Oceania
44−
45−| Location | Contact information |
46−| :--------- | :------------------------------------------------ |
47−| Sydney, AU | [Meetup.com](https://www.meetup.com/Urbit-Sydney) |
content/ecosystem/spotlight/july-2022.md → content/ecosystem/spotlight/2022-august.mdrenamed+1−1
@@ -1,5 +1,5 @@
11+++
2−title = "July 2022"
2+title = "August 2022"
33date = "2022-07-27"
44
55[featured-1]
content/ecosystem/spotlight/2022-december.mdnew file+40
@@ -0,0 +1,40 @@
1++++
2+title = "December 2022"
3+date = "2022-11-29"
4+
5+[featured-1]
6+title = "UF Public"
7+description = "The best place to get the latest updates from the team at the Urbit Foundation."
8+image="https://interstellar.nyc3.digitaloceanspaces.com/battus-datsun/2022.11.07..19.39.22-Sig.png"
9+content = """
10+Join the new and improved Urbit Foundation group to get updates from the Urbit Foundation spanning infrastructure development, developer activity, ecosystem news, announcements, and ways to get involved.
11+
12+
13+"""
14+
15+[featured-2]
16+title = "Groups"
17+description = "The new Groups application from Tlon is officially available."
18+content = """
19+
20+Test drive the future of Urbit now with Tlon's initial release of of Groups. This version features improved discoverability with features like searching by nickname, and creating public, private, or secret groups.
21+
22+Groups is part of the new Landscape suite of applications, and integrates seamlessly with Talk, Gallery, and Notes.
23+
24+Join the [Tlon group](/groups/~nibset-napwyn/tlon-public) for more information.
25+
26+![](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/groups.jpg)
27+
28+"""
29+
30+[featured-3]
31+
32+title = "Scene"
33+image=""
34+description = "Explore Urbit with tirrel's desktop app, Scene."
35+content = """
36+
37+Tirrel is developing an outside-the-browser Urbit experience geared towards content creators. Check out their vision for Urbit as a desktop application.
38+
39+"""
40++++
content/ecosystem/spotlight/2022-november.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+title = "November 2022"
3+date = "2022-10-28"
4+
5+[featured-1]
6+title = "radio"
7+description = "Join or create shared environments for chatting and DJing with YouTube."
8+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/radio-card.jpg"
9+content = """
10+Assembly Capital recently released radio, an app that lets you create or tune into rooms where you can collaboratively DJ with other users on the network.
11+
12+Radio turns the algorithm-driven institution that is Youtube into an experience that's more like watching an old TV with just a few channels with your friends.
13+
14+Developer ~nodmyn-dosrux writes "Radio is the first urbit app with presence built in. Accurate presence data creates a socially charged experience ... Presence gives people reason to engage with each other. Our natural social impulses disincentivize “lurking”, but this doesn’t work when software makes us invisible."
15+
16+
17+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/radio.png)
18+
19+"""
20+
21+[featured-2]
22+title = "Three Things #40: October 23, 2022"
23+description = "What the heck is Urbit?"
24+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/articles/3things40.jpg"
25+content = """
26+
27+Lane Rettig takes on the challenge of defining Urbit.
28+
29+
30+"""
31+
32+[featured-3]
33+
34+title = "E12 - The Gang Does an Urbit Maxi Episode"
35+image=""
36+description = "Ted Blackman joins the Uqbar crew to discuss Assembly 2022, composability and the future of Urbit."
37+content = """
38+
39+This episode of [Uqbar](/organizations/uqbar)'s podcast asks important questions like "How do we evaluate Urbit?" and "Is Urbit ready for outside investment?" in this unique episode with long-time Urbit core developer Ted Blackman.
40+
41+"""
42++++
content/ecosystem/spotlight/2022-october.mdnew file+41
@@ -0,0 +1,41 @@
1++++
2+title = "October 2022"
3+date = "2022-10-03"
4+
5+[featured-1]
6+title = "Uqbar Development Suite"
7+description = "Write smart contracts and blockchain applications in an integrated development suite."
8+image=""
9+content = """
10+At Assembly 2022 Uqbar debuted their brand new developer toolkit: Ziggurat. Ziggurat provides a unified development interface where programmers can write contracts, receive compiler feedback, and test on a fake chain. This promises a huge improvement on the developer experience for smart contracts and blockchain application development alike. Note: As Ziggurat is in active development and undergoing frequent updates, Uqbar recommends installing Ziggurat on a moon rather than your primary ship.
11+
12+
13+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/uqbar-code.png)
14+
15+"""
16+
17+[featured-2]
18+title = "Tlon"
19+description = "The organization that created Urbit is now focused on building the best possible foundational user experiences on Urbit."
20+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/tlonlogos.png"
21+content = """
22+
23+Tlon is the organization responsible for the genesis of Urbit and now focused on creating lasting and effective tools for Urbit. Formerly rather quiet about its development activity, Tlon has recently launched a [beautiful public website](https://tlon.io) and is sharing more of its process in the new [Tlon public group](/groups/~nibset-napwyn/tlon-public).
24+
25+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/tlonio.png)
26+
27+
28+"""
29+
30+[featured-3]
31+
32+title = "The Dream of Digital Homesteading"
33+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/compact-thumb2.png"
34+description = "Compact Magazine's managing editor Geoff Shullenberger attended Assembly 2022 and tuned into both the event vibes and Urbit's technical aspirations."
35+content = """
36+
37+Compact Magazine provides a clear-eyed view of both the social and technical visions of the Urbit community as well as the literary milieu around it.
38+![](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/thedreamofdigitalhomesteading.png)
39+
40+"""
41++++
content/ecosystem/spotlight/2022-september.mdnew file+45
@@ -0,0 +1,45 @@
1++++
2+title = "September 2022"
3+date = "2022-08-29"
4+
5+[featured-1]
6+title = "sphinx"
7+description = "Browse your urbit network with Urbit's first submission and search engine."
8+image=""
9+content = """
10+Sphinx is Urbit’s first search engine. Unlike traditional web search engines, sphinx uses a gossip mechanism originally found in ~paldev’s rumors, so that anything you and your pals post is shared to your pals, as well as pals of pals.
11+
12+You can currently submit and search for applications, groups, and content (notebooks and collections), as well as browse by tag.
13+
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/sphinx2.png)
15+
16+"""
17+
18+[featured-2]
19+title = "peat"
20+description = "Back up your urbit with peat, Urbit's first backup utility."
21+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/peat-thumb.png"
22+content = """
23+
24+Peat is Urbit’s first backup utility. Prior to Peat, there was no easy way to backup content from groups from your ship aside from copying your entire urbit. Peat makes it easy to export all your data from Groups, which uses the graph-store data structure, and in the future will provide support for the new structure in Tlon’s upcoming Groups revamp.
25+
26+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/peat.png)
27+
28+
29+"""
30+
31+[featured-3]
32+
33+title = "Josh Lehman: Urbit – The Peer-to-Peer Network Re-Decentralizing the Internet"
34+description = "Urbit Foundation Executive Director Josh Lehman and Epicenter host Brian Crain have a wide ranging discussion on Urbit's history and future."
35+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/epicenterjoshthumb.jpg"
36+
37+content = """
38+
39+In this podcast Urbit Foundation Executive Director Josh Lehman provides a broad overview of that state of Urbit as of 2022, and what people can expecture in the near future and beyond.
40+
41+{% iframe height="150" src="https://www.youtube.com/embed/DqqUM-L_-2s" title="YouTube video player" width="100%" /%}
42+
43+
44+"""
45++++
content/ecosystem/spotlight/2023-february.mdnew file+48
@@ -0,0 +1,48 @@
1++++
2+title = "February 2023"
3+date = "2023-02-01"
4+
5+[featured-1]
6+title = "Realm"
7+description = "Realm is a desktop Urbit interface from that offers a variety of integrated features."
8+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/realm-hero.png"
9+content = """
10+
11+Realm proposes an Urbit experience that is outside the browser, running as a full-screen cross-platform native application. It offers features like shared application suites, built-in audio chatrooms, an integrated crypto wallet, as well as its own web browser.
12+
13+![](https://media.urbit.org/site/featured/realm-screenshot.jpg)
14+
15+Realm is the flagship product of Holium, who are also building out several collaboration tools akin to a cloud productivity suite for Urbit and Realm. These applications can be bundled together into unique spaces – desktop environments that have been configured for communities and teams.
16+
17+![](https:///media.urbit.org/site/ecosystem/applications/app-suite.png)
18+
19+Realm is currently in private alpha. Visit [holium.com](https://holium.com) to sign up for the invitation waitlist. In the meantime, you can also enjoy an [entertaining podcast](/podcasts/2023-01-24_reject-triviality) in which Holium founder `~lomder-librun` talks about his vision for Realm, amongst many other interesting topics.
20+
21+"""
22+
23+[featured-2]
24+title = "Native Planet"
25+description = "Native Planet is building Urbit-native hardware as well software which enables standalone Urbit home servers."
26+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/native-planet-thumb.jpg"
27+content = """
28+
29+Native Planet is Urbit's first dedicated hardware company. Their first product, the [Tellurian](https://www.nativeplanet.io/hardware), is a turnkey Urbit computer that you can run at home and access anywhere thanks to Native Planet's open-source [software](https://www.nativeplanet.io/software).
30+
31+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/getting-started/native-planet.jpg)
32+
33+What's the point of having a physical Urbit computer, besides the fact that they look very cool?
34+
35+You get the best of both worlds: the accessibility of cloud hosting, with the ownership of running Urbit locally. Groundseg and Startram make your Urbit accessible to any networked device without the need to trust any cloud service provider.
36+
37+
38+"""
39+
40+[featured-3]
41+title = "Urbit for Idiots | Galen Wolfe-Pauly, Tlon Corporation"
42+description = "Tlon CEO Galen Wolfe-Pauly talks to the Boys Club ladies and expounds on the fundamentals of Urbit."
43+image=""
44+content = """
45+
46+Is Urbit a computer? Is owning 'space' on the internet valuable? What is Urbit? How is it different from the the existing internet? Galen and Boys Club get to the bottom of these evergreen topics.
47+"""
48++++
content/ecosystem/spotlight/2023-june.mdnew file+40
@@ -0,0 +1,40 @@
1++++
2+title = "June 2023"
3+date = "2023-06-05"
4+
5+[featured-1]
6+title = "Labyrinth DAO"
7+description = ""
8+image=""
9+content = """
10+
11+Labyrinth DAO is a new decentralized autonomous organization for investing in Urbit projects. Supported by [Tribute Labs](https://tributelabs.xyz/), Labyrinth DAO will foster the growth and development of Urbit as it paves the way for the new internet. Find Labyrinth DAO on [Twitter](https://twitter.com/labyrinth_dao) or connect at labyrinthdao.io to get involved.
12+
13+
14+"""
15+
16+[featured-2]
17+title = "Osmosis"
18+description = ""
19+image=""
20+content = """
21+
22+Holium’s AJ LaMarc (~larryx-woldyr) has built Urbit front-ends for Uniswap, Osmosis, and Safe. This means that you can now swap or hold tokens and access your multi-sig from the comfort of your Urbit. You don’t have to rely on centralized services to provide interfaces for your favorite web3 platforms. You can download these apps on your Urbit today.
23+
24+Get
25+[Osmosis](/applications/~larryx-woldyr/osmosis) |
26+[Uniswap](/applications/~larryx-woldyr/uniswap) |
27+[Safe](/applications/~larryx-woldyr/safe)
28+
29+"""
30+
31+[featured-3]
32+title = "Zorp"
33+description = ""
34+image=""
35+content = """
36+
37+Zorp has built a secure-by-design zero-knowledge virtual machine (zkVM) with a uniquely minimal software supply chain which utilizes Nock as its instruction set. Nock, Urbit’s low-level language, is a famously simple instruction set. That property aligns itself well with what you might create if you were designing a language from first principles to do zero-knowledge proofs. Zorp’s zkVM could unlock new possibilities for crypto and more. Check back at Zorp’s [website](https://zorp.io/) and [Twitter](https://twitter.com/ZorpZK) for more info.
38+
39+"""
40++++
content/ecosystem/spotlight/2023-may.mdnew file+50
@@ -0,0 +1,50 @@
1++++
2+title = "May 2023"
3+date = "2023-05-01"
4+
5+[featured-1]
6+title = "The Mars Review of Books"
7+description = "The Mars Review of Books is a magazine in print and on Urbit. The third issue is now available in print and on online."
8+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/mrb3-thumb.png"
9+content = """
10+
11+The *Mars Review of Books*, a magazine in print and on Urbit, recently put out its third issue — with pieces from Sean Thor Conroe, Marc Hochstein, Miles Routledge, Peter Nimitz and more. And now for the first time, the *MRB* is selling digital and print subscriptions exclusively through Urbit.
12+
13+![Mars Review in Print](https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/mrb3.png)
14+
15+Using payment rails from [Studio](http://localhost:3000/applications/~tirrel/studio) by [Tirrel](https://tirrel.io/), you can now plug in your credit card and subscribe directly to content hosted on an Urbit owned and operated by the people producing the content (in this case, the ~bidbel star).
16+
17+Visit marsreview.org to subscribe to the magazine, buy a print copy of Issue 3, or read selected unpaywalled pieces online.
18+
19+
20+"""
21+
22+[featured-2]
23+title = "Portal"
24+description = "Find and curate Urbit apps, groups, and media from fellow Urbit users"
25+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/portal.svg"
26+content = """
27+
28+Portal is a lot like this ecosystem section of the Urbit website, except *on Urbit*. It’s a great place to find Urbit apps, Urbit groups, and recent media about your favorite Urbit developers and community members.
29+
30+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/portal-screenshot.png)
31+
32+Because Portal is on Urbit, networking among peers is built in. Anyone using Portal can curate their own list of apps and groups, and display that to other Portal users. It’s a great proof of concept for the way decentralized curation can work, a lot of fun to use, and the perfect place to start for anyone trying out Urbit for the first time.
33+
34+You’ll have to check it out on Urbit at ~worpet-bildet/portal
35+
36+"""
37+
38+[featured-3]
39+title = "%blog"
40+description = "Host a blog on your urbit with this application from ~dachus-tiprel."
41+image="https://storage.googleapis.com/media.urbit.org/site/ecosystem/spotlight/blog-thumb.png"
42+content = """
43+
44+Blog is just what it sounds like. A new tool from Uqbar, the app lets anyone on Urbit spin up and customize a blog that displays to the net at an auto-generated URL. Nothing could be breezier. Plus it’s got payments through Uqbar and group-blogging settings on the roadmap. Find out more about it on its [creator's blog](https://dachus-tiprel.tlon.network/blog/introducing-blog).
45+
46+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/ecosystem/applications/blog.png)
47+
48+Download it at ~hanrut-sillet-dachus-tiprel/blog and let the world know what’s on your mind. Bonus feature: a simple command allows you to automatically publish the URL of your latest blog entry to the notorious [Rumors](applications/~paldev/rumors) app.
49+"""
50++++
content/events/2021-04-27-bitcoin-launch.md+2−1
@@ -9,6 +9,7 @@ description = "Bitcoin is coming to Urbit! With the upcoming release of the Bitc
99timezone = "America/Los_Angeles"
1010starts = "2021-04-27T20:00:00.000-07:00"
1111dark = true
12+tags = ["bitcoin"]
1213
1314[[hosts]]
1415name = "Urbit Foundation"
@@ -23,4 +24,4 @@ We’d like to take a moment to show it off, and discuss the future of commerce
2324
2425The event will have a live stream on Youtube, and a live-chat on Urbit, links to come.
2526
26−Join the Bitcoin dev conversation in the Urbitcoiners group: [~pindet-timmut/urbitcoin-cash](web+urbitgraph://group/~pindet-timmut/urbitcoin-cash)
27+Join the Bitcoin dev conversation in the Urbitcoiners group: [~pindet-timmut/urbitcoin-cash](web+urbitgraph://group/~pindet-timmut/urbitcoiners)
content/events/2022-09-15-developer-call-IoT.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Developer Call: Sovereign smart home"
3+starts = "2022-09-15T09:00:00"
4+ends = "2022-09-15T10:30:00"
5+timezone = "America/Los_Angeles"
6+location = "Online Event"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/%202022-09-15-Developer-Call.jpg"
8+registration_url = "https://www.meetup.com/urbit-sf/events/288072398"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = "TKfcdF43cak"
13+
14+[[hosts]]
15+name = "Neal Davis"
16+patp = "~lagrev-nocfep"
17+
18+[[guests]]
19+patp = "~pilwyc-fastec"
20+
21++++
22+
23+Join us on September 15th to talk to ~pilwyc-fastec about Communal Computing and the Internet of Things (IoT). ~pilwyc-fastec has been studying how Urbit and Internet of Things (IoT) devices can complement each other securely. Connected devices open up new frontiers of integration and automation, but have tradeoffs in security and control worth considering as users and developers.
24+
25+~pilwyc-fastec is an IoT hobbyist, smart home enthusiast, Alexa skill builder, and most recently was product manager for the identity platform, biometric recognition machine learning, and voice assistant integration for Facebook’s Portal. He recently published [a blog post on Communal Computing](https://urbit.org/blog/smart-home-of-the-future).
26+
27+We'll discuss how Urbit and Communal Computing ideas complement each other, and where work remains to be done. The smartest home is one you still control yourself.
content/events/2022-09-22-assembly.md+2−4
@@ -1,16 +1,14 @@
11+++
2−title = "Assembly"
2+title = "Assembly 2022"
33starts = "2022-09-22T09:00:00"
44ends = "2022-09-25T19:00:00"
55timezone = "America/New_York"
66location = "In Person Event"
77image = "https://storage.googleapis.com/media.urbit.org/site/events/2022-09-24-Assembly.jpg"
88description = "Urbit Assembly 2022 is the second ever Urbit confluence coming to you this year from Miami Beach."
9−dark = true
109
1110+++
1211
1312Last year we showcased the release of software distribution which enabled other developers to use Urbit as infrastructure for their creations. This year we’ll be showcasing an entire ecosystem of New World Energy.
1413
15−Visit assembly.urbit.org for information on speakers, scheduling, and registration.
16−
14+Visit assembly.urbit.org for information on speakers, scheduling, and registration.
content/events/2022-10-13-devcon-bogotá-urbit-meetup-22.mdnew file+36
@@ -0,0 +1,36 @@
1++++
2+title = "Devcon Bogotá: Urbit Meetup Colombia"
3+starts = "2022-10-13T20:00:00"
4+ends = "2022-10-13T23:00:00"
5+timezone = "America/Bogota"
6+location = "Cra. 8 #66-18 Carrera 8 #66-18 · Bogotá"
7+registration_url = "https://www.meetup.com/urbit-sf/events/288827515/"
8+description = "Devcon Urbit Meetup"
9+dark = false
10+
11+[[hosts]]
12+patp = "~wolref-podlex"
13+
14+[[hosts]]
15+patp = "~riprud-tidmel"
16+
17+[[hosts]]
18+patp = "~lagrev-nocfep"
19+
20+[[hosts]]
21+patp = "~rovnys-ricfer"
22+
23+[[hosts]]
24+patp = "~datder-sonnet"
25+
26+[[hosts]]
27+patp = "~lasnup-fabful"
28+
29+[[hosts]]
30+patp = "~dinleb-rambep"
31+
32+[[hosts]]
33+patp = "~dalweb-donfun"
34++++
35+
36+Urbit Foundation and Tlon invite you to an evening at [Bar Continental](https://www.google.com/maps/place//data=!4m2!3m1!1s0x8e3f9b3980826eb5:0x66696deb3877b7b?source=g.page.share) in Bogotá, Colombia. We’ll meet at 8pm for snacks and drinks, and maybe a cigar in the lounge upstairs. Interested friends and the Urbit-curious are always welcome!
content/events/2022-11-01-developer-week.mdnew file+75
@@ -0,0 +1,75 @@
1++++
2+title = "Urbit Developer Week"
3+starts = "2022-11-14T09:00:00"
4+ends = "2022-11-18T17:00:00"
5+timezone = "America/Los_Angeles"
6+location = "Online Event"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/developer-week.jpg"
8+registration_url = "https://www.meetup.com/urbit-sf/"
9+description = ""
10+
11++++
12+
13+It's been almost two months since Assembly and the last cohort of Hoon School Live has just finished. The year is drawing to a close and the Urbit developer community is getting bigger every day. This calls for a celebration.
14+
15+From the 14th through the 18th of November the Urbit Foundation is organizing a week full of announcements, thoughtful conversations, launches, and more.
16+
17+## Schedule
18+| Date – Time* | What | Meetup | Youtube |
19+|---------------|-------------------------------|-----------------------------------------------------------|------------------------------------------------------|
20+| 11/14 – 10:00 | Urbit Foundation | [here](https://www.meetup.com/urbit-sf/events/289623363/) | [here](https://www.youtube.com/watch?v=xCxHvkS9o8g ) |
21+| 11/15 – 10:00 | The Network State's Ministry of Education| [here](https://www.meetup.com/urbit-sf/events/289629398/) | [here](https://www.youtube.com/watch?v=dTpw2DG6WBc) |
22+| 11/15 – 13:00 | Volcano Summit | [here](https://www.meetup.com/urbit-sf/events/289629419/) | [here](https://www.youtube.com/watch?v=ckFsPr-DXNE) |
23+| 11/16 – 08:00 | Encode Club x Urbit Hackathon | [here](https://www.meetup.com/urbit-sf/events/289646836) | [here](https://www.youtube.com/watch?v=Mn_kGE9Ndbw) |
24+| 11/16 – 10:00 | Speed Hooning | [here](https://www.meetup.com/urbit-sf/events/289629435/) | [here](https://www.youtube.com/watch?v=eRz3s9dQZe8) |
25+| 11/17 – 12:00 | Core Roadmap | [here](https://www.meetup.com/urbit-sf/events/289629450/) | [here](https://www.youtube.com/watch?v=BJaRloyA02Y) |
26+| 11/17 – 13:00 | Core Dev AMA | [here](https://www.meetup.com/urbit-sf/events/289629467/) | [here](https://www.youtube.com/watch?v=SI_B7H8tSRE) |
27+| 11/18 – 10:00 | So you want to work on Urbit? | [here](https://www.meetup.com/urbit-sf/events/289629483/) | [here](https://www.youtube.com/watch?v=j96Gb6dXaNs) |
28+| 11/18 – 12:00 | Engine Pattern | [here](https://www.meetup.com/urbit-sf/events/289629506/) | [here](https://www.youtube.com/watch?v=T4VyW72zX0w) |
29+
30+**times are in Pacific Time*
31+
32+### Developer Week: Urbit Foundation
33+Want to know what’s new at the Urbit Foundation? On Monday Josh Lehman and Ted Blackman will kick-off Urbit Developer Week with a look back at the first year of the Urbit Foundation’s existence and share some exciting news with you. Make sure to tune in and ask your questions.
34+
35+[Meetup](https://www.meetup.com/urbit-sf/events/289623363/) | [Youtube](https://www.youtube.com/watch?v=xCxHvkS9o8g )
36+
37+### Developer Week: The Network State's Ministry of Education
38+In the last year Hoon Education has taken-off and hundreds of people have gone through Hoon School including Dr. Murphy himself. Tune in to watch the two post-academics talk about education on Urbit, opportunities for developers, and what the future has in store for new Hooners.
39+
40+[Meetup](https://www.meetup.com/urbit-sf/events/289629398/) | [Youtube](https://www.youtube.com/watch?v=dTpw2DG6WBc)
41+
42+### Developer Week: Volcano Summit
43+Assembly is barely two months out and there is already a new event waiting for us. The Urbit Foundation and Tlon have teamed up with AlephDAO to organize a new developer summit. Writing runes in magma has never been so comfortable.
44+
45+[Meetup](https://www.meetup.com/urbit-sf/events/289629419/) | [Youtube](https://www.youtube.com/watch?v=ckFsPr-DXNE)
46+
47+### Developer Week: Encode Club x Urbit Hackathon
48+A new Hackathon for developers is being launched in just a few weeks. If you haven’t signed up for it yet, make sure to do so quickly. During this event we will let you know all the ins and outs about the Encode Club x Urbit Hackathon so you are ready to sign up and start preparing. More information about the hackathon can be found [here](https://www.encode.club/urbit-hackathon).
49+
50+[Meetup](https://www.meetup.com/urbit-sf/events/289646836) | [Youtube](https://www.youtube.com/watch?v=Mn_kGE9Ndbw)
51+
52+### Developer Week: Speed Hooning with Quartus
53+Nobody is quicker than Quartus. In this workshop ~rabsef-bicrym will build a reminder application from scratch that integrates with the new %homestead and show you how you can do it as well. Are you up for the challenge?
54+
55+[Meetup](https://www.meetup.com/urbit-sf/events/289629435/) | [Youtube](https://www.youtube.com/watch?v=eRz3s9dQZe8)
56+
57+### Developer Week: Core Roadmap
58+Urbit Core Development is opening up to the world. Want to see where it is going? Join Philip Monk and Ted Blackman to listen to the new vision on core development, their plans for the future and what is in the pipeline already.
59+
60+[Meetup](https://www.meetup.com/urbit-sf/events/289629450/) | [Youtube](https://www.youtube.com/watch?v=BJaRloyA02Y)
61+
62+### Developer Week: Core Dev AMA
63+Have a burning question for the core developers of Urbit about what's going on or where things are going? Urbit’s core developers will be available to answer any questions you have. Join ~rovnys-ricfer, ~wicdev-wisryt, ~palfun-foslup & ~master-morzod on Thursday right after the Roadmap presentation.
64+
65+[Meetup](https://www.meetup.com/urbit-sf/events/289629467/) | [Youtube](https://www.youtube.com/watch?v=SI_B7H8tSRE)
66+
67+### Developer Week: So you want to work on Urbit?
68+Just finished Hoon School? Or always wanted to work for an Urbit company but don’t know where to start? In this session ~poldec-tonteg will lead a panel with several Urbit companies about their open positions, hiring strategies, and explain how you can join them.
69+
70+[Meetup](https://www.meetup.com/urbit-sf/events/289629483/) | [Youtube](https://www.youtube.com/watch?v=j96Gb6dXaNs)
71+
72+### Developer Week: Engine Pattern
73+The "engine pattern" in Hoon programs is a newer design pattern that extends working with cores to higher-level domain-specific abstractions. Join Neal Davis and Ted Blackman in their conversation about this little-known piece of magic.
74+
75+[Meetup](https://www.meetup.com/urbit-sf/events/289629506/) | [Youtube](https://www.youtube.com/watch?v=T4VyW72zX0w)
content/events/2022-11-19-urbit-irl.mdnew file+18
@@ -0,0 +1,18 @@
1++++
2+title = "Urbit SF Meetup ~2022.11"
3+starts = "2022-11-19T13:00:00"
4+ends = "2022-11-19T17:00:00"
5+location = "Alamo Square Park"
6+registration_url = "https://www.meetup.com/urbit-sf/events/289653432/"
7+description = "Please join us for a park meetup (picnic optional!) at Alamo Square Park in San Francisco, on Saturday, 11/19."
8+guests = ""
9+timezone = "America/Los_Angeles"
10+
11+[[hosts]]
12+name = "Tlon"
13++++
14+
15+Please join us for a park meetup (picnic optional!) at Alamo Square Park in San Francisco, on Saturday, 11/19. We'll meet at 1:00PM and stay as long as people want to chat. Bring a jacket and your choice of food/drink.
16+Interested friends and the Urbit-curious are always welcome!
17+
18+We'll meet in the SW corner of the park, on Hayes St near the dog area.
content/events/2022-19-10-developer-call-herd-dependency.mdnew file+25
@@ -0,0 +1,25 @@
1++++
2+title = "Developer Call: herd – dependency management"
3+starts = "2022-10-19T09:00:00"
4+ends = "2022-10-19T10:30:00"
5+timezone = "America/Los_Angeles"
6+location = "Online Event"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/devcall-web1.jpg"
8+registration_url = "https://www.meetup.com/urbit-sf/events/288936277"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = "xtlF7ME0Xws"
13+
14+[[hosts]]
15+name = "Neal Davis"
16+patp = "~lagrev-nocfep"
17+
18+[[guests]]
19+patp = "~midsum-salrux"
20+
21++++
22+
23+The big winner of our Hackathon will show off herd in this month's developer call. Herd is a dependency management tool for hoon. With herd, you don't have to include all the libraries you use on your application desk; instead, you get them from other desks on your ship. This talk is a walkthrough of creating a desk with herd, adding new dependencies, and running and distributing your application.
24+
25+~midsum-salrux is a full-stack hoon developer. In addition to herd, he has written tendiebot (a chatbot that fetches stock and crypto prices), faux (a bridge between urbit groups and discord) and tracks (an upcoming dashboard app).
content/events/2023-01-28-urbit-meetup-christchurch.mdnew file+21
@@ -0,0 +1,21 @@
1++++
2+title = "Urbit Meetup - Christchurch"
3+starts = "2023-01-28T10:30:00"
4+ends = "2023-01-28T12:00:00"
5+timezone = "Pacific/Auckland"
6+location = "363 St Asaph Street, Christchurch"
7+image = "https://silo.sgp1.digitaloceanspaces.com/silo/dinnul-namrud/2023.1.20..04.41.17-kishan-modi-9Pq4o76GpAo-unsplash.jpg"
8+registration_url = "https://chchurbit.eventbrite.com"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~dinnul-namrud"
16+
17++++
18+
19+The first meetup in Christchurch is at The Lotus Heart on the 28th January at 10:30am. Stick around afterwards for a drink and bite to eat if you desire.
20+
21+Please RSVP to the Meetup. Friends are most welcome!
content/events/2023-01-31-urbit-meetup-krakow.mdnew file+26
@@ -0,0 +1,26 @@
1++++
2+title = "Urbit Meetup - Kraków"
3+starts = "2023-01-31T19:00:00"
4+ends = "2023-01-31T22:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "HEVRE - Beera Meiselsa 18, 31-058 Kraków, Poland"
7+image = "https://kongres-magazine.eu/wp-content/uploads/2021/11/hevre_krakow-1.png"
8+registration_url = "https://www.meetup.com/urbit-sf/events/291029359?utm_medium=referral&utm_campaign=share-btn_savedevents_share_modal&utm_source=link"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~dalweb-donfun"
16+
17+[[hosts]]
18+patp = "~wistec-bisrum"
19+
20++++
21+
22+The first meetup in Poland will be in Kraków on Tuesday the 31st of January. You are welcome to join ~dalweb-donfun and ~wistec-bisrum at the Hevre bar from 19:00 for some drinks and good Urbit discussions. Wether you are new to Urbit or already a full-time Hooner be welcome and bring some friends.
23+
24+Please RSVP to the Meetup.
25+
26+There is a planet waiting for you at Hevre.
content/events/2023-02-23-urbit-meetup-berlin.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Urbit Meetup - Berlin"
3+starts = "2023-02-23T20:00:00"
4+ends = "2023-02-23T23:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "c-base - Rungestraße 20 · Berlin, Deutschland"
7+image = "https://upload.wikimedia.org/wikipedia/commons/6/60/Dr._MeTaMiNd_robolab_c-base_spacestation_hackerspace_Berlin_%2812933669604%29.jpg"
8+registration_url = "https://www.meetup.com/urbit-berlin/events/291660889/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~bithex-topnym"
16+
17++++
18+
19+The first Urbit Berlin meetup at our new location: c-base!
20+
21+If you are new to Urbit, this is a great time and place to learn more.
22+
23+For this first meetup we will simply meet, mingle and discuss new and exciting things happening on the network, like: App School Live, Uqbar, Scene, Native Planet, and the upcoming Volcano Summit in El Salvador.
24+
25+The vibe at c-base is great and retro-technological, there is an bar and we have a table booked just for us. There will be other Meetups on various technological and futuristic topics happening at the same time if you like to mingle around.
26+
27+Please RSVP to the Meetup.
content/events/2023-03-05-meetup-el-salvador.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+title = "Urbit Meetup – El Salvador"
3+starts = "2023-03-05T19:00:00"
4+ends = "2023-03-05T22:00:00"
5+timezone = "America/El_Salvador"
6+location = "Urbit Mansion - San Salvador"
7+image = "https://elsalvador.travel/img/slide04.jpg"
8+registration_url = "https://www.meetup.com/urbit-sf/events/290917526"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~nilrun-mardux"
16+
17+[[hosts]]
18+patp = "~rovnys-ricfer"
19+
20++++
21+
22+Just before we all gather for the [Urbit Volcano Summit](https://summit.urbit.org) we are inviting all Urbit people that are already in town and curious locals to an Urbit meetup at the Urbit Mansion in San Salvador. The exact location will be shared with the registered attendees a few days before.
23+
24+Drinks will be provided. See you there.
content/events/2023-03-25-urbit-meetup-christchurch.mdnew file+21
@@ -0,0 +1,21 @@
1++++
2+title = "Urbit Meetup - Christchurch"
3+starts = "2023-03-25T10:30:00"
4+ends = "2023-03-25T12:00:00"
5+timezone = "Pacific/Auckland"
6+location = "363 St Asaph Street, Christchurch"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-christchurch.jpg"
8+registration_url = "https://chchurbit.eventbrite.com"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~dinnul-namrud"
16+
17++++
18+
19+The next meetup in Christchurch is at The Lotus Heart on the 25th March at 10:30am. Stick around afterwards for a drink and bite to eat if you desire.
20+
21+Please RSVP to the Meetup. Friends are most welcome!
content/events/2023-04-18-urbit-lisbon.mdnew file+19
@@ -0,0 +1,19 @@
1++++
2+title = "Urbit Meetup - Lisbon"
3+starts = "2023-04-20T19:00:00"
4+ends = "2023-04-20T22:00:00"
5+timezone = "Europe/Lisbon"
6+location = "Quiosque São Paulo – Praça São Paulo, 1200-194 Lisboa"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/lisbon.jpeg"
8+registration_url = "https://www.meetup.com/urbit-sf/events/292978187"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~dalweb-donfun"
16+
17++++
18+
19+Around in Lisbon this Thursday? ~dalweb-donfun will be hosting a meetup at 7pm. Come by for a drink with other urbiters. RSVP to the meetup event or send ~dalweb-donfun a message on the network. See you on Thursday!
content/events/2023-04-27-urbit-meetup-berlin.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Urbit Meetup - Berlin"
3+starts = "2023-04-27T20:00:00"
4+ends = "2023-04-27T22:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "MUTED HORN – Flughafenstraße 49, 12053 Berlin"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/DSCF1208_09_10.jpg"
8+registration_url = "https://www.meetup.com/urbit-berlin/events/293050078/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~bithex-topnym"
16+
17++++
18+
19+If you are new to Urbit, this is a great time and place to learn more.
20+
21+Topic: open grants – what do they say about the future of Urbit and what kind of knowledge do you need to start building on them?
22+
23+As always, we are also helping new people get on Urbit to try it out, answer technical questions and discuss philosophical questions around Urbit.
24+
25+We have temporarily changed locations to Muted Horn, one of the best craft beer pubs in Northern Europe. It is also possible to order food from nearby restaurants and eat there. If the weather is great we will be sitting outside.
26+
27+Please RSVP to the Meetup.
content/events/2023-04-27_urbit-austin-meetup-consensus.mdnew file+16
@@ -0,0 +1,16 @@
1++++
2+title = "Urbit Austin – Consensus 2023"
3+starts = "2023-04-27T18:30:00"
4+ends = "2023-04-27T20:00:00"
5+timezone = "America/Chicago"
6+location = "Garage – 503 Colorado St · Austin, TX"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/garage-austin.jpg"
8+registration_url = "https://www.meetup.com/urbit-austin/events/293135783"
9+description = "Urbit Austin meetup @ Consensus 2023 presented by the Urbit Foundation"
10+dark = true
11+
12++++
13+
14+Come hangout, drink cocktails at our open bar and talk Urbit during Consensus 2023. We will most likely have a short presentation or two from leaders of the top projects being built. We expect attendance from the Urbit Foundation, Tlon, Zorp, Uqbar, Holium, Assembly Capital and more. Rumor has it there might be free Urbit hats too.
15+
16+If you haven't joined the network yet, bring a computer and we will help you get set up. Other than that we'll have some food and good tunes as well. See you there!
content/events/2023-05-10_urbit-meetup-berlin.mdnew file+25
@@ -0,0 +1,25 @@
1++++
2+title = "Urbit Meetup - Berlin"
3+starts = "2023-05-10T20:00:00"
4+ends = "2023-05-10T22:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "MUTED HORN – Flughafenstraße 49, 12053 Berlin"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/DSCF1208_09_10.jpg"
8+registration_url = "https://www.meetup.com/urbit-berlin/events/293192363/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~bithex-topnym"
16+
17++++
18+
19+We didn't get to cover all we wanted last time and there were lots of outstanding questions, so let's do another extra meetup, rather than wait another month!
20+
21+Tentative topic: Urbit identity, art, and culture. What kind of expression is Urbit uniquely suited for? What would be some cool grants we could apply for?
22+
23+We have temporarily changed locations to Muted Horn, one of the best craft beer pubs in Northern Europe with a cozy vibe. It is also possible to order food from nearby restaurants and eat there. If the weather is great we will be sitting outside.
24+
25+Please RSVP to the Meetup.
content/events/2023-05-14_urbit-meetup-london.mdnew file+23
@@ -0,0 +1,23 @@
1++++
2+title = "Urbit Meetup - London"
3+starts = "2023-05-14T18:00:00"
4+ends = "2023-05-14T20:00:00"
5+timezone = "Europe/London"
6+location = "Cleopatra's Needle – London"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-london.jpg"
8+registration_url = ""
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~tichus-holnet"
16+[[hosts]]
17+patp = "~dalweb-donfun"
18+
19++++
20+
21+This Sunday we'll be doing a meeting up at cleopatra's needle. You'll recognise us by Urbit caps and citing Hoon outloud. See you all on Sunday, byob. Rach out to us on Urbit in case you can't find us.
22+
23+![Picture](https://storage.googleapis.com/media.urbit.org/site/events/2023-05-11%2011.45.27.jpg)
content/events/2023-05-18_urbit-denver-meetup.mdnew file+19
@@ -0,0 +1,19 @@
1++++
2+title = "Urbit Meetup - Denver"
3+starts = "2023-05-18T18:30:00"
4+ends = "2023-05-18T20:30:00"
5+timezone = "US/Mountain"
6+location = "Avanti Food & Beverage - 3200 N. Pecos St, Denver, CO"
7+image = "https://urbits3bucket.fra1.digitaloceanspaces.com/UrbMeet6.jpg"
8+registration_url = "https://www.meetup.com/mile-high-mars-denver-urbit-group/events/293433336/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~nospex-larsut"
16+
17++++
18+Group will meet at the upstairs tables towards the rear of the venue - just take a left when you get to the top of the stairs. Message on the meetup app or through Urbit/Pongo (~nospex-larsut) if unsure.
19+Please RSVP to the Meetup.
content/events/2023-05-18_urbit-miami-meetup.mdnew file+20
@@ -0,0 +1,20 @@
1++++
2+title = "Urbit Meetup - Miami"
3+starts = "2023-05-18T21:00:00"
4+ends = "2023-05-19T03:00:00"
5+timezone = "America/New_York"
6+location = "Eagle Room @ The Broken Shaker 9PM - 3AM"
7+image = "https://i.imgur.com/8x7hpNv.jpg"
8+registration_url = "https://www.meetup.com/urbit-miami/events/293537002/"
9+description = "Miamese Martian congregation parties all night long. Drinks, Food, DJ. Semi-formal attire."
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~wolfun-batrex"
16+
17++++
18+Group will meet in the Eagle Room. Ask the hostess for directions. Event Space Aesthetic is Spectral South-Beach. DJ comes at 10PM. Bring proof of planet for Miamese Martians.
19+
20+Please RSVP to the Meetup page by clicking the RSVP button above.
content/events/2023-05-27_urbit-meetup-london.mdnew file+21
@@ -0,0 +1,21 @@
1++++
2+title = "Urbit London x Giga"
3+starts = "2023-05-27T19:00:00"
4+ends = "2023-05-27T00:00:00"
5+timezone = "Europe/London"
6+location = "HAMPTON TOWER - CANARY WHARF"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/Screenshot%202023-05-26%20at%2007.14.48.png"
8+registration_url = "https://lu.ma/a2ksogr8"
9+description = "urbLon × giga present: Water Wellness Retreat"
10+dark = true
11+darken_image = "true"
12+
13+
14+[[hosts]]
15+patp = "~tichus-holnet"
16+[[hosts]]
17+patp = "~narpel-machul"
18+
19++++
20+
21+Next Saturday, make your way to Hampton Tower in Canary Wharf. You will be escorted to the Giga Corp premises, in which the 7th Urbit London meet-up will take place. Expect drinks, discussion, and much more. https://t.me/urblon
content/events/2023-05-27_urbit-meetup-mst.mdnew file+20
@@ -0,0 +1,20 @@
1++++
2+title = "Urbit Meetup - Utah MST"
3+starts = "2023-05-28T17:00:00"
4+ends = "2023-05-28T19:00:00"
5+timezone = "America/Phoenix"
6+location = "LION'S PARK – 950 W 1280 N ST, PROVO, UTAH"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-utah.png"
8+registration_url = "https://urbitmst.org/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+patp = "~sonmeg-tomdex"
15+
16++++
17+
18+Are you looking for more than the options presented to you?
19+
20+Come to our Urbit (MST) meetup. All are welcome. Bring a computer and we can onboard you with a planet and hosting for free on site. Whether you are new to Urbit or fluent in Hoon, come and meet others in Utah interested in Urbit.
content/events/2023-06-03-urbit-meetup-christchurch.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+title = "Urbit Meetup - Christchurch"
3+starts = "2023-06-03T10:30:00"
4+ends = "2023-06-03T12:00:00"
5+timezone = "Pacific/Auckland"
6+location = "363 St Asaph Street, Christchurch"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-christchurch.jpg"
8+registration_url = "https://www.meetup.com/urbit-christchurch/events/293265373"
9+description = ""
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+patp = "~dinnul-namrud"
15+
16++++
17+
18+The next meetup in Christchurch is at The Lotus Heart on the 3rd June at 10:30am. Stick around afterwards for a drink and bite to eat if you desire.
19+
20+Please [RSVP](https://www.meetup.com/urbit-christchurch/events/293265373) to the Meetup. Friends are most welcome!
21+
22+
23+
24+
content/events/2023-06-08_urbit-meetup-berlin.mdnew file+25
@@ -0,0 +1,25 @@
1++++
2+title = "Urbit Meetup - Berlin"
3+starts = "2023-06-08T20:00:00"
4+ends = "2023-06-08T22:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "MUTED HORN – Flughafenstraße 49, 12053 Berlin"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/DSCF1208_09_10.jpg"
8+registration_url = "https://www.meetup.com/urbit-berlin/events/293860274/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~bithex-topnym"
16+
17++++
18+
19+If you are new to Urbit, this is a great time and place to learn more.
20+
21+Topic: App building
22+
23+We are at Muted Horn, one of the best craft beer pubs in Northern Europe with a cozy vibe. It is also possible to order food from nearby restaurants and eat there. If the weather is great we will be sitting outside.
24+
25+Please RSVP to the Meetup.
content/events/2023-06-08_urbit-meetup-prague.mdnew file+39
@@ -0,0 +1,39 @@
1++++
2+title = "Urbit Meetup Prague"
3+starts = "2023-06-08T14:00:00"
4+ends = "2023-06-08T18:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "loftbubny – U Papírny, 170 00 Praha 7-Holešovice, Czechia"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/59f4fabd-ac53-4c0d-b578-04d2fe6d4b09.webp"
8+registration_url = "https://lu.ma/urbitprague"
9+description = "Urbit Meetup during Prague Blockchain Week at L2Loft"
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+name = "Owen Barnes"
15+patp = "~locruc-fonmec"
16+
17++++
18+Urbit - A clean-slate OS and network for the 21st century.
19+
20+​The meetup takes place as part of the [L2Loft](https://lu.ma/l2loft) initiative.
21+
22+​Date: Thursday 8 June, 2023
23+Expected time: 14:00 - 16:00 (it may change!)
24+
25+**​Schedule:**
26+
27+[​Owen Barnes ](https://twitter.com/temporalwave) (~locruc-fonmec) - The Future of Apps
28+
29+​*More TBA*
30+
31+​Register for the event and stay tuned for more information! You can also join the L2Loft [Telegram group](https://t.me/l2loft) or follow [@L2Loft on Twitter](https://twitter.com/L2Loft).
32+
33+​---
34+
35+Urbit is a new kind of computer that you can own completely in ways that matter: networking, identity, & data.
36+
37+​We realized that in order to fix the internet, we had to build a new computer from scratch. Good thing we started over a decade ago.
38+
39+​Today, Urbit is a real system with thousands of users that are building all kinds of communities, software, DAOs, and more. And it’s getting better every day.
content/events/2023-06-12-developer-week.mdnew file+95
@@ -0,0 +1,95 @@
1++++
2+title = "Urbit Developer Week"
3+starts = "2023-06-12T09:00:00"
4+ends = "2023-06-16T17:00:00"
5+timezone = "America/Los_Angeles"
6+location = "Online Event"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/dev-week-gif.gif"
8+registration_url = "https://www.meetup.com/urbit-sf/"
9+description = "2nd Dev-Week – full of talks, blogs and announcements"
10+dark = true
11+
12++++
13+
14+After the success of our last developer week, we’re hosting another one this year from June 12th to June 16th. This will be a week of online only conversations, build parties, AMAs, blog posts, and other content.
15+
16+There will be watch parties for all streams in the Hacker House on gather.town. Instructions for joining can be found in the [Urbit Foundation group](/groups/~halbex-palheb/uf-public).
17+
18+## Schedule
19+### Kicking Off Developer Week
20+*Time:* Monday June 12th – 9am Pacifc | 6pm CEST
21+
22+We will kick off Urbit developer week with an introduction by ~wolref-podlex, ~lagrev-nocfep & ~dalweb-donfun. They will give you a sneak peek into what's awaiting you at Assembly this year, give you an update about the Foundation and tell you all about how to get involved with Urbit right now. Some very exciting announcements are waiting for you here.
23+
24+[Meetup](https://www.meetup.com/urbit-sf/events/293888554/) | [Youtube](https://www.youtube.com/watch?v=38K2RfaScL8)
25+
26+### %Lick by ~mopfel-winrux
27+*Time:* Monday June 12th – noon Pacifc | 9pm CEST
28+
29+~mopfel-winrux, lead developer at [Native Planet](/organizations/nativeplanet), has taken it upon himself to build a hardware vane that lets your Urbit directly communicate with the machine it's running on. This opens up an array of new possibilities. In this talk ~lagrev-nocfep will interview ~mopfel-winrux about his progress, and we might even see a demo.
30+
31+[Meetup](https://www.meetup.com/urbit-sf/events/294013274/) | [Youtube](https://www.youtube.com/watch?v=TDROdmVW7_0)
32+
33+### Core Roadmap
34+*Time:* Tuesday June 13th – 9am Pacifc | 6pm CEST
35+
36+In this talk our CTO ~rovnys-ricfer, together with ~master-morzod & ~wolref-podlex, will give an update on the Roadmap and talk about other news concerning Urbit’s core development. There are some exciting announcements coming up.
37+
38+[Meetup](https://www.meetup.com/urbit-sf/events/293893446/) | [Youtube](https://www.youtube.com/watch?v=vmqn36RtnBk)
39+
40+### Core Developers AMA
41+*Time:* Tuesday June 13th – 10am Pacifc | 7pm CEST
42+
43+Always wanted to ask the core developers something? In this AMA they will be available to answer any questions you have. Join ~rovnys-ricfer, ~wicdev-wisryt, ~palfun-foslup & ~master-morzod on Tuesday right after the Roadmap presentation.
44+
45+[Meetup](https://www.meetup.com/urbit-sf/events/293893486/) | [Youtube](https://www.youtube.com/watch?v=BolurhVR6N4)
46+
47+### Portal
48+*Time:* Tuesday June 13th – noon Pacifc | 9pm CEST
49+
50+In this talk ~foddur-hodler and ~dilryd-mopreg from [Portal](/applications/~worpet-bildet/portal) will update you on their latest developments. They are excited to share their experiences using solid state subscriptions, to present their ideas on what they're calling *the everything graph*, and to explain why they're "composability-maxxing."
51+
52+[Meetup](https://www.meetup.com/urbit-sf/events/294013283/) | [Youtube](https://www.youtube.com/watch?v=6J8-jlqz2r4)
53+
54+### Core School Preview: Jetting
55+*Time:* Wednesday June 14th – 9am Pacifc | 6pm CEST
56+
57+Core School approacheth. To whet your appetite for the inner mysteries of the kernel, we will discuss how jet-accelerated code works and how to write jets for arms. Join ~lagrev-nocfep & ~rovnys-ricfer at a preview of Core School content. And make sure to check out our [CSL page](https://developers.urbit.org/courses/csl) for more details.
58+
59+[Meetup](https://www.meetup.com/urbit-sf/events/294013289/) | [Youtube](https://www.youtube.com/watch?v=i1GRoY3QDdU)
60+
61+### %Eyre by ~palfun-foslup
62+*Time:* Wednesday June 14th – noon Pacifc | 9pm CEST
63+
64+Urbit solves a lot of problems with digital identity. But its HTTP server, Eyre, hasn't gotten the memo yet. Two new Eyre features will make identifying incoming HTTP requests much nicer, letting developers deliver richer experiences, even on publicly accessible web pages. Join ~palfun-foslup at this session about %Eyre.
65+
66+[Meetup](https://www.meetup.com/urbit-sf/events/294013295/) | [Youtube](https://www.youtube.com/watch?v=eN_oh_orCcg)
67+
68+### Native UI
69+*Time:* Thursday June 15th – 9am Pacifc | 6pm CEST
70+
71+Using JavaScript on Urbit has always felt a bit off. ~hastuc-dibtux is going to change this with his Urbit Native UI project. Rendering Hoon as a frontend? Piece of cake.
72+In this talk ~palfun-foslup will interview ~hastuc-dibtux about his project. Don’t miss the future of UIs.
73+
74+[Meetup](https://www.meetup.com/urbit-sf/events/293893568/) | [Youtube](https://www.youtube.com/watch?v=1l9dnppQO1U)
75+
76+### Integrating Uqbar Transactions
77+*Time:* Thursday June 15th – noon Pacifc | 9pm CEST
78+
79+Want to know how to integrate Uqbar smart contracts with your app? In this presentation Uqbar's lead developer ~hodzod-walrus will walk you through what it takes to integrate your app with Uqbar's smart contracts. It's easier than you think.
80+
81+[Meetup](https://www.meetup.com/urbit-sf/events/294013302/) | [Youtube](https://www.youtube.com/watch?v=Q-aZZabT6_M)
82+
83+### Vaporware
84+*Time:* Friday June 16th – 9am Pacifc | 6pm CEST
85+
86+In this talk ~harden-hardys will prove that [Vaporware](https://vaporware.network) is not actually vaporware. Get to know what he and his team are up to and you might even see a glimpse or more of their first public project, *Tharsis*.
87+
88+[Meetup](https://www.meetup.com/urbit-sf/events/294013311/) | [Youtube](https://www.youtube.com/watch?v=bh5U5q9Qp_k)
89+
90+### What to Build on Urbit and Why
91+*Time:* Friday June 16th – noon Pacifc | 9pm CEST
92+
93+AJ or ~larryx-woldyr recently launched a suite of Urbit-hosted front-ends for [Osmosis](/applications/~larryx-woldyr/osmosis), [Uniswap](/applications/~larryx-woldyr/uniswap) and [Safe](/applications/~larryx-woldyr/safe). In this talk he'll dive into why he thinks you should build on Urbit and what you should build on it. Tune in to his closing talk of Developer Week on Friday.
94+
95+[Meetup](https://www.meetup.com/urbit-sf/events/294013323/) | [Youtube](https://www.youtube.com/watch?v=AARwK5cGavw)
content/events/2023-06-15_urbit-denver-meetup.mdnew file+19
@@ -0,0 +1,19 @@
1++++
2+title = "Urbit Meetup - Denver"
3+starts = "2023-06-15T18:30:00"
4+ends = "2023-06-15T20:30:00"
5+timezone = "US/Mountain"
6+location = "Federal Bar & Grill - 2544 Federal Blvd, Denver, CO"
7+image = "https://urbits3bucket.fra1.digitaloceanspaces.com/UrbMeet7.jpg"
8+registration_url = "https://www.meetup.com/mile-high-mars-denver-urbit-group/events/293937089/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+youtube = ""
13+
14+[[hosts]]
15+patp = "~nospex-larsut"
16+
17++++
18+Will have a table reseerved to accommodate number of RSVPs; just ask for Adam.
19+Please RSVP to the Meetup.
content/events/2023-06-24-urbit-meetup-christchurch.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+title = "Urbit Meetup - Christchurch"
3+starts = "2023-06-24T10:30:00"
4+ends = "2023-06-24T12:00:00"
5+timezone = "Pacific/Auckland"
6+location = "363 St Asaph Street, Christchurch"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-christchurch.jpg"
8+registration_url = "https://www.meetup.com/urbit-christchurch/events/294172584/"
9+description = ""
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+patp = "~dinnul-namrud"
15+
16++++
17+
18+The next meetup in Christchurch is at The Lotus Heart on the 24th June at 10:30am. Stick around afterwards for a drink and bite to eat if you desire.
19+
20+Please [RSVP](https://www.meetup.com/urbit-christchurch/events/294172584/) to the Meetup. Friends are most welcome!
21+
22+
23+
24+
content/events/2023-06-29-Urbit-Paris-Meetup-1.mdnew file+30
@@ -0,0 +1,30 @@
1++++
2+title = "Urbit Meetup in Paris"
3+starts = "2023-06-29T18:30:00"
4+ends = "2023-06-29T21:30:00"
5+timezone = "Europe/Amsterdam"
6+location = "La Fièvre, 108 Rue Oberkampf, 75011 Paris"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/urbitParis-meetup-1.png"
8+registration_url = "https://www.meetup.com/urbit-paris/events/293962806/"
9+description = "Urbit Paris - Meetup #1"
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+name = ""
15+patp = "~solsup-soplyd"
16+
17++++
18+Curious what the future of the Internet looks like?
19+
20+Join us on June 29th in Paris!
21+
22+Whether you're a tech enthusiast, an established Urbit aficionado, or a newcomer to the scene, our community is meant to welcome and engage everyone.
23+
24+If you're confused about what Urbit is, no worries, most people are at first. Drop by and we'll give you our best explanations of what Urbit is and how it's going to change the internet as we know it.
25+
26+We'll introduce Urbit, help you boot your own ship and make sure you go back home all set!
27+
28+In the meantime, you can join us on [Twitter](https://wwww.twitter.com/urbitparis)!
29+
30+See you there!
content/events/2023-07-01_urbit-meetup-mst.mdnew file+23
@@ -0,0 +1,23 @@
1++++
2+title = "Urbit Meetup - Utah MST"
3+starts = "2023-07-01T10:00:00"
4+ends = "2023-07-01T11:00:00"
5+timezone = "America/Phoenix"
6+location = "Maeser Park – 451 E 600 S, Provo, UT 84606"
7+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/communities/urbit-utah.png"
8+registration_url = "https://urbitmst.org/"
9+description = "Our third meetup in Utah"
10+dark = true
11+darken_image = "true"
12+
13+[[hosts]]
14+name = "Lyman"
15+patp = "~sonmeg-tomdex"
16+
17++++
18+
19+Are you looking for more than the options presented to you?
20+
21+Come to our Urbit (MST) meetup. All are welcome. Bring a computer and we can onboard you with a planet and hosting for free on site. Whether you are new to Urbit or fluent in Hoon, come and meet others in Utah interested in Urbit.
22+
23+This will be our first morning meetup, we will have donuts. Bring your friends. You are invited.
content/events/2023-07-20-Urbit-Paris-Meetup-ethcc.mdnew file+53
@@ -0,0 +1,53 @@
1++++
2+title = "𝓣𝓱𝓮 𝓢𝓾𝓶𝓶𝓮𝓻 𝓢𝓸𝓲𝓻𝓮𝓮 - Paris ETHCC"
3+starts = "2023-07-20T19:00:00"
4+ends = "2023-07-21T1:00:00"
5+timezone = "Europe/Amsterdam"
6+location = "Le Comptoir Général"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/parisian-tweet-v2.gif"
8+registration_url = "https://lu.ma/parissoiree"
9+description = "Urbit Summer Soiree Paris @ETHCC"
10+dark = true
11+darken_image = "false"
12+
13+[[hosts]]
14+name = "Thomas"
15+patp = "~dalweb-donfun"
16+
17+[[hosts]]
18+name = "Ted"
19+patp = "~rovnys-ricfer"
20+
21+[[hosts]]
22+name = "Sam"
23+patp = "~tidren-nosryg"
24+
25+[[hosts]]
26+name = "Shad (giga)"
27+
28+[[guests]]
29+name = "Illia (co-founder Near)"
30+
31++++
32+Presented by Urbit | giga | NEAR
33+​An evening of salacious chatter and good friends under the night sky and the peering eye of the tower.
34+
35+​Join us on July 20th with other like minds as we manifest the reality around us, drinking and eating till we can no more.
36+
37+​At 19:30 we will record a live episode of the [ZeroK podcast](https://www.youtube.com/@zero-k-podcast/videos) between [Ted Blackman](https://twitter.com/rovnys) (CTO Urbit Foundation) & [Illia Polosukhin](https://twitter.com/ilblackdragon) (CEO Near).
38+
39+​RSVP necessary.
40+
41+*​NB. Due to high demand, please [signup](https://lu.ma/parissoiree) early and consider coming before 19:45 to avoid any disappointment.*
42+
43+![Foto](https://storage.googleapis.com/media.urbit.org/site/events/luma-parisian-event.jpg)
44+
45+​“In the parties which she gave, since I could not imagine the guests as having any bodies, any moustaches, any boots, as making any utterances that were commonplace, or even original in a human and rational way, this whirlpool of names, introducing less material substance than would a phantom banquet or a spectral ball, round that statuette in Dresden china which was Madame de Guermantes, kept for her palace of glass the transparence of a showcase.
46+
47+​Then, after Saint-Loup had told me various anecdotes about his cousin’s chaplain, her gardener, and the rest, the Hôtel de Guermantes had become—as the Louvre might have been in days gone by—a kind of castle, surrounded, in the very heart of Paris, by its own domains, acquired by inheritance, by virtue of an ancient right that had quaintly survived, over which she still enjoyed feudal privileges.”
48+
49+[​Urbit](https://urbit.org/) is a new kind of computer that you can own completely in ways that matter: networking, identity, & data. It's a clean-slate operating system, p2p network and persistent identity.
50+
51+[​giga](https://gigaver.se/) is a hardcore marketing and ecosystem firm bringing projects and networks to the spotlight. Email us today to learn how we take projects from the deep dark depths and put them on a pedestal.
52+
53+[​NEAR](https://near.org/) allows you to effortlessly create and distribute innovative decentralized apps across any blockchain, while helping build a more open web, with the NEAR Blockchain Operating System (BOS).
content/events/2023-08-16_reassembly.mdnew file+22
@@ -0,0 +1,22 @@
1++++
2+title = "Reassembly 2023"
3+starts = "2023-08-16T09:00:00"
4+ends = "2023-08-18T19:00:00"
5+timezone = "America/Phoenix"
6+location = "The Colony Building 211 West 19th Street Cheyenne, WY 82001 United States"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/https___cdn.evbuc.com_images_517157329_547708747059_1_original.jpeg"
8+registration_url = "https://www.eventbrite.com/e/reassembly-2023-tickets-637686015037"
9+description = "Reassembly 2023, hosted by Tacen, features focused discussions on clean-slate OS, next-generation networks, and the future of computing."
10+dark = true
11+darken_image = "true"
12+
13++++
14+Tacen is proud to host Reassembly 2023 in Cheyenne, WY! Join us August 16-18 for focused discussions and exciting presentations on clean-slate OS, next-generation networks, and the future of modern computing.
15+
16+We will be bringing world-class experts to present their big ideas and new breakthroughs regarding all things related to the Urbit universe. Don’t miss this one-of-a-kind chance to see everyone gathered all in one place.
17+
18+Breakfast, lunch and refreshments provided for attendees. Details on accommodations group rates, schedules, and online viewership to follow.
19+
20+Confirmed speakers: [~hodzod-walrus](https://urbit.org/ids/~hodzod-walrus), [~harden-hardys](https://urbit.org/ids/~harden-hardys), [~littel-wolfur](https://urbit.org/ids/~littel-wolfur), [~dachus-tiprel](https://urbit.org/ids/~dachus-tiprel), [~nomryg-nilref](https://urbit.org/ids/~nomryg-nilref) and more to come!
21+
22+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/events/FwSOS1vXsAIgmZc.jpeg)
content/events/2023-10-28_urbit-assembly-lisboa.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+title = "Urbit Assembly Lisboa 2023"
3+starts = "2023-10-28T10:00:00"
4+ends = "2023-10-29T20:00:00"
5+timezone = "Europe/Lisbon"
6+location = "Lisbon – Portugal"
7+image = "https://storage.googleapis.com/media.urbit.org/site/events/urb01_assembly23_std_1-1.png"
8+registration_url = ""
9+description = "The third Urbit Assembly & first one outside of the US"
10+dark = true
11+darken_image = "true"
12+
13++++
14+![Screenshot](https://storage.googleapis.com/media.urbit.org/site/events/urb01_assembly23_std_16-9.png)
15+
16+Urbit is coming to Europe! Save the date for Urbit Assembly 2023 & Urbit Week in Lisbon this year.
17+
18+Early-bird tickets are going live by the end of may in the [UF Public Group](/groups/~halbex-palheb/uf-public).
19+
20+We’re changing up the format this year: the first two days will be more “conference-like” with launches, presentations and panels from the Urbit ecosystem.
21+
22+Afterwards we’ll have a week of side events hosted by the community throughout Lisbon.
23+
24+Don't miss it.
content/faq.md+1−1
@@ -244,7 +244,7 @@ One day we’d really like the Urbit ID registry to be hosted on [Urbit OS](#wha
244244
245245### Why is Hoon so weird? {% #why-hoon %}
246246
247−There are things about Urbit that are weird by design, and some that are weird because we haven’t gotten around to cleaning them up. [Hoon](/docs/glossary/hoon), for the most part, is weird by design, but there are a few things about it we’d like to clean up. For a complete description of why we created Hoon, see the [Hoon overview](/docs/hoon/overview).
247+There are things about Urbit that are weird by design, and some that are weird because we haven’t gotten around to cleaning them up. [Hoon](/docs/glossary/hoon), for the most part, is weird by design, but there are a few things about it we’d like to clean up. For a complete description of why we created Hoon, see the [Hoon overview](https://developers.urbit.org/reference/hoon/overview).
248248
249249The runes are, once you get the hang of them, pretty nice. Your mileage may vary, of course, but many talented engineers have spent many, many hours writing Hoon. It’s a simple, practical language. But the learning curve can be a bit high.
250250
content/getting-started/_index.md+19−16
@@ -1,25 +1,28 @@
11+++
2−title = "Overview"
2+title = "Introduction"
33weight = 0
44description = ""
55+++
66
7−### Introduction
7+The goal of Urbit is to make peer-to-peer software easy for developers to write
8+and for users to run on their own. The code is [completely open
9+source](https://github.com/urbit), [actively
10+maintained](https://github.com/urbit/urbit/graphs/code-frequency), supported by
11+a [growing ecosystem](https://urbit.org/ecosystem), and [used daily by
12+thousands](https://network.urbit.org).
813
9−Nothing about building a new OS from scratch has been easy. Or creating an identity system that adequately replaces the IP address.
14+Urbit consists of two high-level components: an operating
15+system (Urbit OS) and an identity system (Urbit ID). Urbit OS enables its user to communicate directly with others using Urbit OS via their Urbit ID's. You can think of these like phone numbers &mdash; meaningless
16+but memorizable, and likely to identify the same person reliably through time.
1017
11−Getting on Urbit isn't always easy, either. The onboarding process hasn't been optimized by product managers in search of maximal profit. There's no checkbox for your interests—you have to discover them yourself.
18+Using Urbit requires having access to a running **ship**: an Urbit OS running
19+with a supplied Urbit ID. You can run Urbit yourself if you're comfortable at a
20+command-line or willing to learn. Otherwise you should probably use a hosting
21+provider &mdash; that is, someone that provides you with an Urbit as a service.
1222
13−But we like to think this hard work is exactly what makes Urbit special. **Consider yourself warned.**
23+## Next steps
1424
15−### Why Urbit?
16−
17−**As a user**, you can explore the people, community, and sheer novelty of the Urbit ecosystem while owning your entire experience. Your data, your messages, your apps.
18−
19−**As a developer**, you can now build apps, a protocol for a whole suite of apps, or an entire online subculture, and distribute your work directly to your users' operating systems. No middlemen, no MEGACORPs, and no lock-in.
20−
21−Someone once said, "All the smart people I know disappear into Urbit." If you're smart, you will too — not just installing and running Urbit, but taking the first step toward deploying your Final Computer.
22−
23−### Launch into Urbit
24−
25−Choose how you want to disappear into Urbit.
25+- [Run Urbit yourself](/getting-started/self-host) or select a [hosting provider](/getting-started/hosted)
26+- Meet friendly people by [joining groups](/getting-started/joining-groups)
27+- [Install apps](/getting-started/installing-applications) to experiment with
28+- Explore [interfaces](/getting-started/interfaces) for Urbit
content/getting-started/cli.md+116−57
@@ -1,67 +1,76 @@
11+++
2−title = "Command line app"
3−weight = 2
4−description = "Installation instructions for power users."
2+title = "Command-line install"
3+weight = 3
4+description = "Installation instructions for technical users"
5+tag = "selfhost"
56+++
67
7−If you're a power user, you can run the Urbit virtual machine directly using the
8−command line. This can be run on your local machine or a server in the cloud, we
9−just cover the general case here.
8+This guide covers running the Urbit runtime (Vere) using the command line. This
9+can be run on your local machine or a server in the cloud, we just cover the
10+local case here. The runtime is what interprets the Urbit kernel code (Arvo)
11+into commands your specific machine (macOS or Linux) understands.
1012
1113Note there is a much more comprehensive [cloud hosting
12−guide](https://operators.urbit.org/manual/running/hosting) which walks through
13−setting up Urbit on a [Digital Ocean](https://www.digitalocean.com/) VPS.
14+guide](/getting-started/cloud-hosting) which walks through setting up Urbit on a
15+[Digital Ocean](https://www.digitalocean.com/) VPS.
1416
15−### 1. Install Urbit
17+### 1. System Requirements {% #about-swap-space %}
18+
19+- **Processor**: 1 core
20+- **Memory**: 2GB
21+- **Storage**: At least a few GB, 40-50GB preferable
22+- **Network**: Any
23+
24+**A note on memory**: By default, the Urbit runtime needs 2GB of free memory,
25+and will fail to boot without it. Urbit usually only uses a portion of this, so
26+it's possible to use a swap file to makeup for a shortfall without degrading
27+performance. For instructions on how to configure a swap file on Linux, see
28+[this linuxize.com guide](https://linuxize.com/post/create-a-linux-swap-file/).
29+
30+**A note on storage**: Urbit saves every event it processes to its [Event
31+Log](https://developers.urbit.org/reference/glossary/eventlog). This means its
32+disk usage slowly grows over time. Until event log truncation is implemented,
33+it's advisable to have 40 or 50GB of disk space available, so you don't have to
34+worry about running out for a long time. If you don't have that much, your ship
35+will still run fine, but you may run out of space some months down the line.
36+
37+### 2. Install Urbit
1638
1739Choose your operating system and run the given command in your terminal to
18−download the Urbit runtime:
40+download the Urbit runtime, this command downloads the latest build, unpacks
41+it, and runs the binary with no arguments to show you the help output:
1942
2043{% tabs %}
2144
22−{% tab label="MacOS" %}
45+{% tab label="Linux x86_64" %}
2346
24−```bash
25−curl -L https://urbit.org/install/mac/latest | tar xzk --strip=1 && ./urbit
47+```shell
48+curl -L https://urbit.org/install/linux-x86_64/latest | tar xzk --transform='s/.*/urbit/g' && ./urbit
2649```
2750
28−> Note our Mac build is only compatible with Apple Silicon (M1/M2) via Rosetta.
29−> If you have such a machine you may need to run the following command:
30−>
31−> ```
32−> /usr/sbin/softwareupdate --install-rosetta --agree-to-license
33−> ```
34−
3551{% /tab %}
3652
37−{% tab label="Linux" %}
53+{% tab label="Linux AArch64" %}
3854
3955```shell
40−curl -L https://urbit.org/install/linux64/latest | tar xzk --strip=1 && ./urbit
56+curl -L https://urbit.org/install/linux-aarch64/latest | tar xzk --transform='s/.*/urbit/g' && ./urbit
4157```
4258
43−> Linux users may need to run this command in another terminal window to access
44−> your urbit on port 80:
45−>
46−> ```shell
47−> sudo apt-get install libcap2-bin
48−> sudo setcap 'cap_net_bind_service=+ep' ./urbit
49−> ```
50−
5159{% /tab %}
5260
53−{% tab label="Windows" %}
61+{% tab label="macOS x86_64" %}
5462
55−```winbatch
56−curl -L https://urbit.org/install/windows/latest | tar -xzkf - --strip-components=1 && urbit
63+```bash
64+curl -L https://urbit.org/install/macos-x86_64/latest | tar xzk -s '/.*/urbit/' && ./urbit
5765```
5866
59−> Windows 10 build 17063 and later includes the familiar `curl` and `tar`
60−> command-line tools. If you're running an older version of Windows, you may need
61−> to visit
62−> [https://github.com/urbit/urbit/releases/latest](https://github.com/urbit/urbit/releases/latest)
63−> in the browser, download the `windows.zip` file, extract it and execute the
64−> contained `urbit.exe` file in the command prompt.
67+{% /tab %}
68+
69+{% tab label="macOS AArch64" %}
70+
71+```bash
72+curl -L https://urbit.org/install/macos-aarch64/latest | tar xzk -s '/.*/urbit/' && ./urbit
73+```
6574
6675{% /tab %}
6776
@@ -73,7 +82,7 @@ If successful, you will see a block of output beginning with the line:
7382Urbit: a personal server operating function
7483```
7584
76−### 2. Boot Urbit
85+### 3. Boot Urbit
7786
7887An Urbit instance is intrinsically tied to a unique identity called an **Urbit
7988ID**. There are five classes of Urbit ID, but we will consider two here: comets
@@ -90,8 +99,8 @@ and planets.
9099 unlimited number of comets, planets are more scarce (preventing spamming,
91100 among other things). This scarcity means they usually aren't free (though
92101 sometimes nice people give them away). This guide will assume you've already
93− acquired a planet. If you haven't, you can refer to the ["Get a planet"
94− guide](https://urbit.org/getting-started/get-planet) before continuing.
102+ acquired a planet. If you haven't, you can refer to the ["Get an Urbit ID"
103+ guide](/getting-started/get-id) before continuing.
95104
96105Follow the instructions for your case:
97106
@@ -106,8 +115,8 @@ comet can be booted with the `-c` option:
106115./urbit -c mycomet
107116```
108117
109−> `mycomet` will be the name given to the data folder it will create. You can
110−> choose any name you like.
118+> `mycomet` will be the name given to the folder it will create.
119+> You can choose any name you like.
111120
112121It may take a while to initialize the comet (usually only a couple of minutes,
113122but it could take longer). When it's done, it'll take you to the dojo prompt
@@ -127,6 +136,14 @@ folder, so you can start it up again by doing:
127136```bash
128137./mycomet/.run
129138```
139+> Linux users need to run this command in another terminal window to access
140+> your urbit on port 80 every time you upgrade your runtime (otherwise it'll
141+> default to port 8080):
142+>
143+> ```shell
144+> sudo apt-get install libcap2-bin
145+> sudo setcap 'cap_net_bind_service=+ep' <pier>/.run
146+> ```
130147
131148Since comets are often used temporarily and then discarded, kernel updates are
132149not enabled by default. If you plan to use your comet for a while, it's a good
@@ -136,9 +153,9 @@ idea to enable updates with the following command in the dojo:
136153|ota (sein:title our now our)
137154```
138155
139−Lastly, while the dojo is quite powerful, most people use their urbit via
140−Landscape, the browser-based UI. In order to access Landscape, you need your web
141−login code. You can get this by running the following command in the dojo:
156+Lastly most people use their urbit via Landscape, the browser-based UI. In order
157+to access Landscape, you need your web login code. You can get this by running
158+the following command in the dojo:
142159
143160```
144161+code
@@ -167,7 +184,7 @@ keyfile):
167184./urbit -w sampel-palnet -k sampel-palnet-1.key
168185```
169186
170−This will create a data folder with the name of your planet and begin booting.
187+This will create a folder with the name of your planet and begin booting.
171188It may take a while to initialize the planet (usually only a couple of minutes,
172189but it could take longer). When it's done, it'll take you to the dojo prompt
173190(the dojo is Urbit's shell):
@@ -186,9 +203,17 @@ folder, so you can start it up again by doing:
186203```bash
187204./sampel-palnet/.run
188205```
206+> Linux users need to run this command in another terminal window to access
207+> your urbit on port 80 every time you upgrade your runtime (otherwise it'll
208+> default to port 8080):
209+>
210+> ```shell
211+> sudo apt-get install libcap2-bin
212+> sudo setcap 'cap_net_bind_service=+ep' <pier>/.run
213+> ```
189214
190−While the dojo is quite powerful, most people use their urbit via Landscape, the
191−browser-based UI. In order to access Landscape, you need your web login code.
215+Most people use their urbit via Landscape, the browser-based UI.
216+In order to access Landscape, you need your web login code.
192217You can get this by running the following command in the dojo:
193218
194219```
@@ -200,14 +225,14 @@ It'll spit out a code that'll look something like `lidlut-tabwed-pillex-ridrup`
200225to the clipboard.
201226
202227One last thing: The `sampel-palnet-1.key` keyfile is only needed once, when you
203−first boot your planet. Now that it's booted, it's good security practice to
204−delete that keyfile.
228+first boot your planet. **Now that it's booted, it's good security practice to
229+delete that keyfile.**
205230
206231{% /tab %}
207232
208233{% /tabs %}
209234
210−### 3. Login
235+### 4. Login
211236
212237While your urbit is running, the web interface called *Landscape* can be
213238accessed in the browser. Its URL will usually be either `localhost` or
@@ -222,10 +247,44 @@ Whichever address and port it says there is the one to open in the browser.
222247
223248Once open, you'll be presented with the login screen. Paste in the web login
224249code you copied from the dojo in the previous step and hit "continue". You'll
225−now be taken to your homescreen, with tiles for the default apps such as Groups
226−and Terminal.
250+now be taken to your homescreen, with tiles for the default apps such as Groups,
251+Talk, and Terminal.
252+
253+### 5. Runtime Upgrades
254+
255+When new versions of the Urbit runtime (Vere) are available, you'll have to
256+shutdown your urbit and then run the `next` command in order to upgrade.
257+```
258+:dojo> |exit
259+<pier>/.run next
260+```
261+Note that `<pier>` in this case is the folder that was created when you first booted
262+your urbit. When you run this command your urbit will download the latest binary
263+and place it inside the `.bin` directory inside your pier folder. You can then
264+start your ship with the following and you'll be on the latest runtime version:
265+```
266+<pier>/.run
267+```
268+> Linux users need to run this command in another terminal window to access
269+> your urbit on port 80 every time you upgrade your runtime (otherwise it'll
270+> default to port 8080):
271+>
272+> ```shell
273+> sudo apt-get install libcap2-bin
274+> sudo setcap 'cap_net_bind_service=+ep' <pier>/.run
275+> ```
276+
277+If you've been running Urbit for a while (from before runtime version 1.9)
278+and these `.run` commands don't work for you, it probably means you need to
279+[dock](https://operators.urbit.org/manual/running/vere#dock) your pier.
280+You can do this with the following command:
281+```
282+./urbit dock <pier>
283+```
284+Then `.run` should work as expected and future runtime upgrades can be done via
285+`next`.
227286
228−### Next steps
287+## Next steps
229288
230289Learn how to [get around your
231−urbit](https://urbit.org/getting-started/getting-around).
290+urbit](/getting-started/getting-around).
content/getting-started/cloud-hosting.mdnew file+468
@@ -0,0 +1,468 @@
1++++
2+title = "Cloud hosting"
3+weight = 4
4+description = "How to host your ship in the cloud so you can access it from any device"
5+tag = "selfhost"
6++++
7+
8+The goal of this guide is to have clear and easy to follow best practices for
9+deploying an Urbit node to a server you control in the cloud. Deploying in the
10+cloud allows you to access your Urbit from any device.
11+
12+Most Urbit users start out running their ship locally on one machine in order to
13+play with it, but this means when your machine is offline your Urbit node is
14+offline too (and can't get updates). You can also only access your Urbit from
15+that one machine.
16+
17+This guide uses Digital Ocean as the cloud provider, but others can be used. If
18+using another provider, the setup script provided and other server configuration
19+instructions may need to be modified or done manually.
20+
21+## 1. Create a Droplet
22+
23+Create an account on [Digital Ocean](https://digitalocean.com). Once you make an
24+account, choose "Deploy a virtual machine".
25+
26+You should see the page below where you can create your Droplet, aka Virtual Machine:
27+
28+![do screenshot](https://media.urbit.org/operators/manual/running/hosting/do-screenshot.png)
29+
30+Fill out the options like so:
31+
32+#### Image
33+
34+Ubuntu 22.04 x64
35+
36+#### Plan
37+
38+- Shared CPU: Basic
39+- CPU options: Regular with SSD
40+- 2GB / 1 CPU ($12/mo)
41+
42+You can choose a more powerful option if you'd like but the $12 option should be
43+sufficient. Note Urbit needs 2GB of memory; it's possible to choose a cheaper
44+option and run it with less memory by using swap but it will impact performance.
45+
46+#### Add block storage
47+
48+The $12 plan includes 50GB which should be sufficient for quite some time, so
49+you can skip this.
50+
51+#### Datacenter region
52+
53+Choose the region closest to you.
54+
55+#### VPC Network
56+
57+Leave this as default.
58+
59+#### Authentication
60+
61+In the "Authentication" field, select "SSH keys" and hit "New SSH Key". Run the
62+following command in the terminal on your local machine, replacing
63+`riclen-tinlyr` with the name of your ship (sans the leading `~`):
64+
65+```bash {% copy=true %}
66+SHIP="riclen-tinlyr" bash -c 'ssh-keygen -q -N "" -C $SHIP -f ~/.ssh/$SHIP && cat ~/.ssh/$SHIP.pub'
67+```
68+
69+It should spit out a long string of letters and numbers beginning with `ssh-rsa`
70+and ending with your ship name. Copy the whole thing and paste it into the "SSH
71+key content" field on Digital Ocean. In the "Name" field, enter your ship name.
72+
73+#### Additional options
74+
75+Click "+Advanced Options" check the box for "Add Initialization scripts (free)" and paste the script below into the field provided. This
76+will automatically configure the server and install necessary software.
77+
78+```bash {% copy=true %}
79+#!/bin/bash
80+
81+# configure swap
82+fallocate -l 2G /swapfile
83+chmod 600 /swapfile
84+mkswap /swapfile
85+swapon /swapfile
86+echo "/swapfile swap swap defaults 0 0" >> /etc/fstab
87+
88+# setup firewall
89+ufw allow OpenSSH
90+ufw allow www
91+ufw allow https
92+ufw allow 34543/udp
93+ufw enable
94+
95+# create and configure user
96+useradd -s /bin/bash -d /home/urbit -m -G sudo urbit
97+passwd -d urbit
98+echo "urbit ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
99+
100+# configure ssh keys for user
101+mkdir -p /home/urbit/.ssh
102+chmod 700 /home/urbit/.ssh
103+cp /root/.ssh/authorized_keys /home/urbit/.ssh/authorized_keys
104+chmod 600 /home/urbit/.ssh/authorized_keys
105+chown -R urbit:urbit /home/urbit/.ssh
106+
107+# configure sshd
108+mkdir -p /etc/ssh/sshd_config.d
109+cat > /etc/ssh/sshd_config.d/override.conf <<EOF
110+PermitRootLogin no
111+PubkeyAuthentication yes
112+PasswordAuthentication no
113+EOF
114+
115+# fetch and extract urbit binary
116+curl -L https://urbit.org/install/linux-x86_64/latest | tar xzk --transform='s/.*/urbit/g' -C /home/urbit/
117+chown urbit:urbit /home/urbit/urbit
118+
119+# install tmux
120+apt -y update
121+apt install -y tmux
122+
123+# reboot
124+systemctl reboot
125+```
126+
127+#### How many Droplets?
128+
129+1
130+
131+#### Choose a hostname
132+
133+This will be the name the server calls itself locally, you can put in whatever
134+you want. Your planet name is a good choice.
135+
136+#### Add tags
137+
138+Leave empty.
139+
140+#### Select project
141+
142+Leave as the default.
143+
144+#### Create Droplet
145+
146+Hit this button to create the droplet.
147+
148+## 2. Prepare for upload
149+
150+{% callout %}
151+
152+**Note**
153+
154+This step is necessary if you already have a ship running locally and want to
155+move it to the cloud. If you don't, you can skip this step.
156+
157+{% /callout %}
158+
159+In the Dojo, use either `"CTRL + D"` or `|exit` to shut down your ship.
160+
161+Archive your pier by running `tar cvzf riclen-tinlyr.tar.gz ~/path/to/your/pier`
162+(substitute your own ship name and pier location).
163+
164+## 3. Connect to the server
165+
166+To make connecting simple, you can add an alias to `~/.ssh/config` on your local
167+machine. Open `~/.ssh/config` in an editor (you may need to create it if the
168+file doesn't exist), and add the following to the bottom of the file (replacing
169+the ship name with your own and the IP address with that of your droplet):
170+
171+``` {% copy=true %}
172+Host riclen-tinlyr
173+ HostName 161.35.148.247
174+ User urbit
175+ IdentityFile ~/.ssh/riclen-tinlyr
176+ IdentitiesOnly yes
177+```
178+
179+{% tabs %}
180+
181+{% tab label="If you have an existing pier" %}
182+
183+
184+Copy the archived pier to the server with the following (substituting your ship
185+name and Host):
186+
187+```bash {% copy=true %}
188+scp riclen-tinlyr.tar.gz riclen-tinlyr:
189+```
190+
191+It may take a while to upload if your pier is large and/or your internet is
192+slow.
193+
194+{% /tab %}
195+
196+{% tab label="If you have a key file" %}
197+
198+If you have obtained a planet and want to boot it for the first time, you'll
199+need to upload its key file to the server. These instructions assume you've
200+received an invite. If you've got a planet by another method, you can also login
201+to [Bridge](https://bridge.urbit.org) and download the key file from there.
202+
203+If you've received a planet invite via email or a claim link like
204+`https://bridge.urbit.org/#labfur-batteg-dapnex-binsup-riclen-tinlyr`, open it
205+in a browser and you should see a page like the following:
206+
207+![claim planet screenshot](https://media.urbit.org/operators/manual/running/hosting/claim-planet.png)
208+
209+If you hit "Claim", it'll bring you here:
210+
211+![download passport
212+screenshot](https://media.urbit.org/operators/manual/running/hosting/download-passport.png)
213+
214+Hit "Download Backup (Passport)" and it'll have you download a file named like
215+`riclen-tinlyr-passport.zip`.
216+
217+Unzip the file with:
218+
219+```bash {% copy=true %}
220+unzip ~/path/to/download/folder/riclen-tinlyr-passport.zip
221+```
222+
223+It'll create a folder called `riclen-tinlyr-passport` which will contain three files:
224+
225+- `riclen-tinlyr-1.key`
226+- `riclen-tinlyr-Management Proxy.png`
227+- `riclen-tinlyr-Master Ticket.png`
228+
229+You can physically print out the two `.png` files and store them in a safe and
230+secure location. Importantly, you should ensure the *master ticket* (which will
231+look something like `~tarnes-pilryd-dassed-sogsul`) is securely and safely
232+stored. If anyone gains access to the master ticket they'll have ownership and
233+control of your Urbit ID, and if you lose it you'll irreversibly lose ownership
234+and control of your Urbit ID.
235+
236+The next screen on the claim page will ask you to re-enter the master ticket to
237+ensure you've recorded it accurately, and then the claim process is complete.
238+Once you've securely, physically backed up the master ticket and the `.png`
239+passports, it's a good idea to delete the `riclen-tinlyr-passport.zip` file and
240+the two `.png` files, so if someone gains access to your computer, your Urbit ID
241+will be safe.
242+
243+This will leave only the `riclen-tinlyr-1.key` file. The key file contains your
244+planet's private keys, which are necessary to boot it up for the first time.
245+You'll need to copy that file to the server with the following command (again,
246+replacing `riclen-tinlyr` with your own ship and Host):
247+
248+```bash {% copy=true %}
249+scp riclen-tinlyr-passport/riclen-tinlyr-1.key riclen-tinlyr:
250+```
251+
252+Note: you should keep the `riclen-tinlyr-1.key` until you've completed this
253+guide and your ship is booted to be sure it was copied successfully, but
254+afterwards you should also delete that file for security.
255+
256+{% /tab %}
257+
258+{% /tabs %}
259+
260+Once you've either uploaded your pier or uploaded your key file as the case may
261+be, you can connect to your server:
262+
263+```bash {% copy=true %}
264+ssh riclen-tinlyr
265+```
266+You'll be taken to the shell on your server.
267+
268+## 5. Boot your ship
269+
270+{% tabs %}
271+
272+{% tab label="If you have an existing pier" %}
273+
274+In the previous section you ssh'd into the server. In the same ssh session,
275+extract the pier archive you previously uploaded, then delete the archive:
276+
277+```bash {% copy=true %}
278+tar xvzf riclen-tinlyr.tar.gz && rm riclen-tinlyr.tar.gz
279+```
280+
281+You'll now have a folder called `riclen-tinlyr`, which is your pier. Urbit is
282+best run in a tmux or screen session so it's easy to keep it running when
283+you disconnect. In this case we'll use tmux, which has already been installed
284+by the setup script.
285+
286+Run tmux:
287+
288+```bash {% copy=true %}
289+tmux
290+```
291+
292+You should now be in tmux. First, dock your ship:
293+
294+```bash {% copy=true %}
295+./urbit dock riclen-tinlyr
296+```
297+
298+That will copy the `urbit` runtime inside the pier, so you can now delete the
299+separate binary:
300+
301+```bash {% copy=true %}
302+rm urbit
303+```
304+
305+{% /tab %}
306+
307+{% tab label="If you have a key file" %}
308+
309+In the previous section you ssh'd into the server. In the same ssh session,
310+start tmux:
311+
312+```bash {% copy=true}
313+tmux
314+```
315+
316+You should now be in tmux. Boot a new ship with the following command,
317+specifying the ship name and key file, as well as the Ames port that was
318+previously opened in the firewall by the setup script:
319+
320+```bash {% copy=true %}
321+./urbit -w riclen-tinlyr -k riclen-tinlyr-1.key -p 34543
322+```
323+
324+It may take several minutes to boot the new ship. Eventually, it'll take you to
325+the Dojo (Urbit's shell) and show a prompt like `~riclen-tinlyr:dojo>`. Once
326+booted, shut the ship down again by typing `|exit` in the Dojo. After it quits,
327+it should print something like "docked successfully", which means the binary has
328+been copied inside the pier. This means you can delete the separate binary:
329+
330+```bash {% copy=true %}
331+rm urbit
332+```
333+
334+The key file is only needed when you first boot the ship, so it's good practice
335+to delete it after first boot:
336+
337+```bash {% copy=true %}
338+rm riclen-tinlyr-1.key
339+```
340+
341+{% /tab %}
342+
343+{% /tabs %}
344+
345+Run the following to allow the runtime to bind ports 80 and 443:
346+
347+```bash {% copy=true %}
348+sudo setcap 'cap_net_bind_service=+ep' riclen-tinlyr/.run
349+```
350+
351+Now you can start your ship up with the following:
352+
353+```bash {% copy=true %}
354+./riclen-tinlyr/.run -p 34543
355+```
356+
357+After a few moments it'll show the Dojo prompt like `~riclen-tinlyr:dojo>`.
358+
359+## 6. Get a domain
360+
361+To make accessing the web interface convenient, you should request an
362+`arvo.network` domain name. To do so, run the following command in the Dojo,
363+replacing the IP address with your droplet's:
364+
365+``` {% copy=true %}
366+-dns-address [%if .161.35.148.247]
367+```
368+
369+This will request a subdomain of your ship like `riclen-tinlyr.arvo.network`.
370+
371+The domain should be registered almost instantly, but sometimes it takes a while
372+for it to propagate to other DNS servers. You might therefore see the following:
373+
374+```
375+> -dns-address [%if .161.35.148.247]
376+dns: request for DNS sent to ~deg
377+dns: awaiting response from ~deg
378+http: fail (13, 504): unknown node or service
379+http: fail (14, 504): unknown node or service
380+http: fail (15, 504): unknown node or service
381+http: fail (16, 504): unknown node or service
382+http: fail (17, 504): unknown node or service
383+dns: unable to access via riclen-tinlyr.arvo.network
384+XX confirm port 80
385+XX check via nslookup
386+0
387+```
388+
389+If that happens, wait five or ten minutes and then try again. You should
390+eventually see:
391+
392+```
393+> -dns-address [%if .161.35.148.247]
394+dns: request for DNS sent to ~deg
395+dns: awaiting response from ~deg
396+[%key iter=0 width=2.047]
397+[%key iter=1 width=2.047]
398+[%key iter=2 width=2.047]
399+[%key iter=3 width=2.047]
400+acme: requesting an https certificate for riclen-tinlyr.arvo.network
401+dns: confirmed access via riclen-tinlyr.arvo.network
402+0
403+acme: received https certificate for riclen-tinlyr.arvo.network
404+http: restarting servers to apply configuration
405+http: web interface live on https://localhost:443
406+http: web interface live on http://localhost:80
407+http: loopback live on http://localhost:12321
408+```
409+
410+That means the domain has been registered and an SSL certificate has been
411+installed, so you can access the web interface securely with HTTPS.
412+
413+## 7. Log in to Landscape
414+
415+In order to login to the web interface, you need to get the web login code. Run
416+the following in the Dojo:
417+
418+``` {% copy=true %}
419++code
420+```
421+
422+It'll spit out something like `ropnys-batwyd-nossyt-mapwet`. That's your web
423+login code, you can copy that and save it in a password manager or similar. Note
424+that the web login code is separate from the master ticket.
425+
426+The server configuration should now be complete, and you can access Landscape in
427+the browser. Navigate to the domain you configured previously, in this case
428+`riclen-tinlyr.arvo.network`. You should see the Landscape login screen:
429+
430+![landscape login screen](https://media.urbit.org/operators/manual/running/hosting/landscape-login.png)
431+
432+Enter the web login code and you'll be taken to your ship's homescreen. Your
433+ship is now running in the cloud, and you can access it from any device by
434+visiting its URL.
435+
436+## 8. Disconnect
437+
438+You can now disconnect from the tmux session by hitting `CTRL+b d` (that is, you
439+hit `CTRL+b`, release it, and then hit `d`). You'll be taken back to the
440+ordinary shell, but the ship will still be running in the background. If you
441+want to get back to the Dojo again, you can reattach the tmux session with:
442+
443+```bash {% copy=true %}
444+tmux a
445+```
446+
447+Finally, you can disconnect from the ssh session completely by hitting `CTRL+d`.
448+
449+## 9. Cleanup
450+
451+If you booted a new ship by uploading a key file, it's a good idea to now delete
452+the key file on your local machine.
453+
454+If you uploaded an existing pier, you should delete the old copy of both the
455+pier directory and the `.tar.gz` archive on your local machine. You might be
456+tempted to keep one of these as a backup, but note that **you must never again
457+boot the old copy on the live network**. Doing so will create unfixable
458+networking problems and require you to perform a factory reset through Bridge,
459+wiping your ship's data. We therefore don't recommend you keep duplicates of
460+your pier lying around.
461+
462+
463+## Next steps
464+
465+- Kep your Urbit runtime up-to-date to take advantage of the latest Landscape and Application over-the-air updates. See [Step #5 in the CLI guide](/getting-started/cli#5-runtime-upgrades) to update your runtime.
466+
467+- Learn how to [get around your
468+urbit](/getting-started/getting-around).
content/getting-started/desktop.md+5−70
@@ -1,76 +1,11 @@
11+++
22title = "Desktop app"
3−description = "Run Urbit locally as a desktop application"
4−weight = 1
3+weight = 4
4+description = ""
55+++
66
7−### 1. Get Port
7+In the past we recommended [Port](https://github.com/urbit/port/releases), a desktop Urbit client.
88
9−Port is a desktop GUI application that allows you to spin up, access, and manage your Urbit ships without any knowledge of the command line or Urbit binary.
9+We now recommend that users that are not comfortable with the [CLI interface](/getting-started/cli) run Urbit with a [hosting service](/getting-started/hosted) or an Urbit-native computer like [Native Planet](https://www.nativeplanet.io/).
1010
11−{% tabs %}
12−
13−{% tab label="MacOS" %}
14−
15−To install **Port** on MacOS, simply download and open the `.dmg` file.
16−
17−{% button label="Download Port" link="https://github.com/urbit/port/releases/latest/download/Port.dmg" color="bg-green-400 text-white" %}
18−{% /button %}
19−
20−{% /tab %}
21−
22−{% tab label="Linux" %}
23−
24−We use `snap` so that **Port** can stay updated automatically. If you already have `snap` installed, simply run:
25−
26−```sh
27−sudo snap install port
28−```
29−
30−Or to install `snap` for your distribution, snapcraft provides [installation instructions](https://snapcraft.io/docs/installing-snapd).
31−
32−{% /tab %}
33−
34−{% tab label="Windows" %}
35−
36−**WARNING:** Support for Windows is experimental. For the best experience, we recommend using a [cloud hosting provider](https://urbit.org/getting-started/hosted) rather than running Urbit locally.
37−
38−To install **Port** on Windows, simply download and open the `.exe` file.
39−
40−{% button label="Download Port" link="https://github.com/urbit/port/releases/latest/download/PortSetup.exe" color="bg-green-400 text-white" %}
41−{% /button %}
42−
43−{% /tab %}
44−
45−{% /tabs %}
46−
47−### 2. Boot a comet
48−
49−A comet serves as a temporary identity for the network. It works just fine for checking out the network, but to download applications and get the full functionality of Urbit ID you’ll need a to get a planet.
50−
51−Start Port and hit the **Start without an ID** button. It'll take a few minutes to spin up the new comet.
52−
53−![](https://media.urbit.org/site/getting-started/Desktop-app-1.jpg)
54−
55−### 3. Launch your ship
56−
57−Once that's finished, click **Launch Ship into Urbit** and you'll be on the network.
58−
59−![](https://media.urbit.org/site/getting-started/Desktop-app-2.jpg)
60−
61−{% callout %}
62−
63−**Want to combine the simplicity of Port with a permanent Urbit ID?**
64−
65−If you already have a planet, first get your keyfile.
66−Start Port, click the **Boot a fresh ID** option. Give your ship a name, and in the **Shipname** field, enter your planet name, like `~sampel-palnet`. For the **Key File** field, browse to the keyfile, select it, and hit **Continue**.
67−
68−Port will boot your Urbit in a few minutes!
69−
70−For more information on getting a planet, see our [Getting an Urbit ID](/guides/getting-an-urbit-id) guide.
71−
72−{% /callout %}
73−
74−### Next steps
75−
76−Learn how to [get around your urbit](/getting-started/getting-around).
11+Whichever way you run your urbit, you can also now use it with a desktop interface such as [Scene](https://tirrel.io/scene/index.html), or the soon-to-be released [Realm](https://www.holium.com/) application.
content/getting-started/get-planet.md → content/getting-started/get-id.mdrenamed+29−40
@@ -1,46 +1,45 @@
11+++
2−title = "Get a planet"
3−weight = 1
4−description = "How to acquire a planet, or an Urbit ID"
5−tag = "additional"
2+title = "Get an Urbit ID"
3+weight = 2
4+description = "How to acquire an Urbit ID"
5+tag = "selfhost"
66+++
77
8−### What's a planet?
8+### Types of ID
99
10−Planets are a type of [Urbit ID](/understanding-urbit/urbit-id) that is useful for providing individuals long-term access to the Urbit network.
10+There are [five different
11+types](https://operators.urbit.org/guides/which-id-should-i-buy) of Urbit ID, but here we'll just be discussing two types called comets and planets.
1112
12−### Where to get a planet
13+**Comets** are free, temporary identities that you can issue yourself and are best-suited for
14+short-term usage. **Planets** are permanent identities that are suitable for long-term use.
1315
14−There are a few ways to get your own planet:
16+![](https://storage.googleapis.com/media.urbit.org/site/getting-started/comet-planet.png)
1517
16−- Getting an invitation from a friend (or stranger)
17−- Purchasing a planet, including hosting, from a hosting provider
18−- Manually setting up and hosting a planet purchased from a third party marketplace
18+Planets have a unique, four syllable phonetic name and a [sigil](https://urbit.org/blog/creating-sigils), a visual representation of the name.
1919
20−### Hosting Providers {% #hosting-providers %}
2120
22−Hosting providers will often sell you a planet and run it for you. This option is very simple but will probably cost a regular fee.
2321
24−Urbit is designed to be portable. This means that if you sign up for hosting now but later want to leave your hosting provider and run your Urbit yourself, you should be able to work with them to obtain all of your data and boot your planet back up without losing anything.
22+### Where to get a planet
2523
26−Using hosting does mean that you're trusting your provider with your data, but so long as you have your planet, you'll always own your identity.
24+There are a few ways to get your own planet:
2725
28−Current hosting providers are:
26+- Receiving one from a friend
27+- Asking on Twitter (if you're lucky)
28+- Booting a comet and being friendly in [Urbit Community](https://urbit.org/groups/~bitbet-bolbel/urbit-community)
29+- Purchasing one from a marketplace
2930
30−- [UrbitHost](https://urbithost.com)
31−- [escape pod store](https://www.escapepod.store/)
32−- [Third Earth](https://third.earth/)
33−- [Tlon Corporation](https://tlon.io)
31+This guide will cover the last case and what to do after receiving one.
3432
3533### Buying a planet
3634
37−There are many places to buy a planet using either cryptocurrency or fiat.
35+There are many places to buy a planet using either crypto or fiat currency.
3836
39−Layer 1 planets are the most available through marketplaces, however they can be expensive due to Ethereum gas fees. You will need an Ethereum wallet such as Metamask to purchase these planets, and will later need to sign in to Bridge with your wallet to configure your planet.
37+Layer 1 planets are the most available through marketplaces, however they can be expensive due to Ethereum gas fees. You will need an Ethereum wallet such as Metamask to purchase planets, and will later need to sign in to Bridge with your wallet to configure your planet.
4038
41−Layer 2 planets do not require any crypto wallet management, but are at present less readily available on marketplaces.
39+Layer 2 planets do not require any crypto wallet management, but are only available on specific marketplaces.
4240
43−Don’t worry, both types work the same on the network.
41+There is no difference between Layer 1 or Layer 2 in the quality of experience
42+when using Urbit.
4443
4544Here are a few of the places where you can buy planets:
4645{% table .w-full .my-4 %}
@@ -64,7 +63,7 @@ Here are a few of the places where you can buy planets:
6463
6564**Layer 2 for planets**
6665
67−Learn more about [layer 2 for planets](/using/id/layer-2-for-planets) in the User's Manual page on the topic.
66+Learn more about [layer 2 for planets](https://operators.urbit.org/manual/id/layer-2-for-planets) in the User's Manual page on the topic.
6867
6968{% /callout %}
7069
@@ -75,7 +74,7 @@ An invitation to claim your planet comes in one of two forms.
7574
7675The first is an email invitation with an Urbit ID and a Master Ticket.
7776
78−The second, only recently made available through our [L2 solution](/using/id/layer-2-for-planets), is an activation code or a link to activate on [Bridge](https://bridge.urbit.org), which can be thought of as an Urbit account management tool.
77+The second, made available through our [L2 solution](https://operators.urbit.org/manual/id/layer-2-for-planets), is an activation code or a link to activate on [Bridge](https://bridge.urbit.org), the Urbit ID management tool.
7978
8079![](https://media.urbit.org/site/getting-started/Server-setup-1.jpg)
8180
@@ -103,22 +102,12 @@ Now that you have your planet, you can create your keyfile (eg. `sample-palnet.k
103102- **L1 Planet Purchasers**
104103 Log in to Bridge with your Ethereum wallet using Metamask or the wallet of your choice with WalletConnect. Click the “OS” box on the bottom of the page to open the OS page, and then click the **Download Keyfile** button.
105104
106−
107105### Next steps
108106
109−Got your planet?
110−
111−Get it up and running with one of these options:
112−
113−- Let a [hosting provider](/getting-started/hosted) do the hard work for you.
114−
115−- [Try Port](/getting-started/desktop), the user-friendly desktop app.
107+Now that you have a keyfile let's move on to booting the Urbit OS.
116108
117−- For power users, check out the [command line install
118− guide](/getting-started/cli) and run your urbit from the terminal.
109+- [CLI instructions](/getting-started/cli) – Set up Vere, the Urbit runtime, using the command line.
119110
120−- If you have a bit of Linux server experience, the [cloud hosting
121− guide](https://operators.urbit.org/manual/running/hosting) will help you set
122− up Urbit on a Digital Ocean VPS, so you can access it from anywhere.
111+- [Install on the cloud](/getting-started/cloud-hosting) – A step-by-step guide to setting up Urbit on a VPS.
123112
124−Remember, your planet is yours and you can always change how you run your urbit in the future.
113+- [Set up a home server](/getting-started/home-servers) – Explore options for running your own dedicated physical Urbit computer.
content/getting-started/getting-around.md+24−48
@@ -1,79 +1,55 @@
11+++
2−title = "Getting around"
3−description = "Get around your urbit"
4−weight = 4
2+title = "Overview"
3+description = "Getting around your urbit"
4+tag = "around"
5+weight = 0
56+++
67
78### 1. Get oriented
89
9−After you've logged into your Urbit for the first time, you're officially an Urbiter! You've unlocked the entire Urbit network with your newly-minted ID — the key to your new digital life.
10+After you've logged into your Urbit for the first time, you'll have an interface called Landscape – a way interact with the network and applications. You'll also see a few pre-installed applications: Terminal, Groups, and Talk. More on them in a moment.
1011
11−![](https://media.urbit.org/site/getting-started/Getting-around-1.jpg)
12+![](https://storage.googleapis.com/media.urbit.org/site/getting-started/get-oriented.png)
1213
13−You'll see your Home and a few pre-installed applications: Terminal, Groups, and Bitcoin. More on them in a moment.
14+Above those are buttons to view System Preferences and check out notifications for messages and application activity. The search bar helps you surface applications you already have installed, or discover developers and applications across the Urbit network.
1415
15−Above those are buttons to view System Preferences and Help and Support and check out notifications for newly-installed or recently-updated applications, respectively. The search bar helps you surface applications you already have installed, or discover developers and applications across the Urbit network.
16+![](https://storage.googleapis.com/media.urbit.org/site/getting-started/about-system.png)
1617
17−You'll likely want to focus on finding and joining new communities, which you can do with the **Groups** app. Click on the box to open the application.
18+You'll likely want to focus on finding and joining new communities, which you can do with the **Groups** app.
1819
19−### 2. Join a few groups with fellow Urbiters
20+### 2. Join a few groups
2021
21−No two people will ever have the same experience on Urbit. That depends entirely on who you find and where they invite you to join them. But we can set you down a good path.
22+Joining public groups is simple – just search for the group host's Urbit ID, and click join. Check out a walk-through of this process in the [Joining groups](/getting-started/joining-groups) guide.
2223
23−With Groups open, you'll see three boxes for **My Channels**, your local weather, and a stylized clock. You can dig into those later, but let's focus on joining new communities, which is likely one of the reasons you wanted to try out Urbit in the first place.
24−
25−Click on Join Group, and in that modal, enter [~bitbet-bolbel/urbit-community](/groups/~bitbet-bolbel/urbit-community) — the official Urbit community. You can either automatically join all channels by clicking the Join all channels checkbox, or leave it blank and hit Join Group right away. Your Urbit will connect to the P2P network and download information about the group, like a list of all its participants. When that's finished, click **View Group**.
26−
27−You're now looking at a single group and all of its channels. If you didn't choose to join all channels right away, click on an individual channel and then **Join Channel**, which immediately opens the feed of latest messages.
28−
29−Here are a few more useful groups to join:
30−
31−- [`~rondev/group-discovery`](/groups/~rondev/group-discovery): A group for finding other groups.
32−- [`~middev/the-forge`](/groups/~middev/the-forge): A group for sharing, discussing, and discovering new Urbit applications.
33−- [`~hocwyn-tipwex/uqbar-event-horizon`](/groups/~hocwyn-tipwex/uqbar-event-horizon): A community around [Uqbar](https://uqbar.network), a company creating applications and experiences on top of Urbit — notably EScape, which is an alternative to the default Groups application for joining communities and messaging with other Urbiters.
34−
35−### 3. Get more Urbit apps
24+### 3. Install some applications
3625
3726Groups are great, but Urbit goes way deeper with apps that are developed specifically for Urbit and use P2P networking for everything.
3827
39−We'll use [Canvas](/applications/~dister-norsyr-torryn/canvas) — a collaborative app for creating pixel art with others — as an example to show the process.
40−
41−Head back to your Urbit's home — the URL you used to log in and view your preinstalled apps. From there, click on the search bar and enter `~dister-norsyr-torryn/canvas`. Click on the first result, which shows you details about the developer, the license, a website for more information, and when the app was last updated.
42−
43−Click **Get App**, then **Get "Canvas"** to continue. Your Urbit gets to work, and once installation is finished, click Open App to see it in action.
28+Check out the [Installing apps](/getting-started/installing-applications) guide for a walk-through on the process of installing Urbit applications.
4429
45−Some popular apps to get things moving:
4630
47−- [EScape](/applications/~dister-fabnev-hinmur/escape): An alternative UI to the core groups, communities, and messaging capabilities in Urbit.
48−- [Studio](/applications/~tirrel/studio): Tools for making money on the Urbit network.
49−- [Wrdu](/applications/~magped-magped-rabsef-bicrym/wrdu): A Wordle clone.
31+### 4. Explore interfaces
5032
51−### 4. Get help
33+The default Urbit experience is using Landscape in the browser, but Urbit is also available on native mobile and desktop applications through alternative interfaces. [Learn more about Urbit interfaces](/getting-started/interfaces).
5234
53−If you need help getting around Urbit, the best place to go is the official Urbit community: [`~bitbet-bolbel/urbit-community`](/groups/~bitbet-bolbel/urbit-community). Those in the Help channel are willing to troubleshoot or provide links to resources to help you get out of a jam.
5435
55−That community isn't for every support request, however. If your question involves an app, you're better served reaching out to the developer — for example, if you have an issue with EScape's notifications feature, reach out to Uqbar in [`~hocwyn-tipwex/uqbar-event-horizon`](/groups/~hocwyn-tipwex/uqbar-event-horizon).
36+### 5. Getting help
5637
57−If you're having trouble with your planet or the hosting provider that's running your ship, try their support, as they'll have more context and resources to help solve your issue.
38+If you need help getting around Urbit, the best place to go is the official Urbit community: [`~bitbet-bolbel/urbit-community`](/groups/~bitbet-bolbel/urbit-community). Those in the Help channel are willing to troubleshoot or provide links to resources to help you get out of a jam. Note that Urbit Community can take a long time to join due to its size.
5839
59−And if you can't get through this guide and launch into Urbit, you may have luck with the [Urbit Live community](https://t.me/UrbitLiveGroup) on Telegram.
40+If your question involves an app, you're better served reaching out to the developer. Many [developers](/ecosystem?type=organizations) have dedicated groups on the network explicitly for this purpose.
6041
61−### 5. What's next?
42+If you're having trouble with your planet or the hosting provider that's running your ship, try their support, as they'll have more context and resources to help solve your issue. And you can always email support@urbit.org if you're having trouble getting onto the network.
6243
63−You made it! You did the work and now have your Final Computer.
6444
65−What you do with it is up to you. Where you go from here is up to you. No two experiences on Urbit will be the same, so we encourage you to follow your own. Explore. Discover! Get lost and find the people who make you feel like you're not lost any more.
6645
67−Still need some bumpers to guide you along the way?
46+### 6. Next steps
6847
69−**Learn more about using Urbit**: Check out the [User's Manual](/using/).
7048
71−**Get updates about Urbit**: [Subscribe](https://urbit.us11.list-manage.com/subscribe/post?u=972a03db9e0c6c25bb58de8c8&id=be143888d2) to the Urbit Newsletter for new blog posts and events from one of the primary organizations responsible for Urbit development.
49+**Learn more**: Check out the [Operators Site](https://operators.urbit.org/) to learn more about running your own Urbit and how the network functions.
7250
73−**Join an event or meetup**: Many of the organizations and people behind Urbit host virtual and in-person events on a regular basis — check out the latest on our [Events feed](/events/).
51+**Stay updated**: [Subscribe](https://urbit.us11.list-manage.com/subscribe/post?u=972a03db9e0c6c25bb58de8c8&id=be143888d2) to the Urbit Newsletter for news, blog posts, and upcoming events.
7452
75−**Learn how to build on Urbit**: If you're the kind of person who wants to build applications directly for discerning communities with built-in identity and networking primitives, or even jump into the Urbit kernel's core, we have the most phenomenally-comprehensive information to get you started.
53+**Meet up**: Many of the organizations and people behind Urbit host virtual and in-person events on a regular basis — check out the latest on our [Events feed](/events/), or a local [Meetup group](/ecosystem?type=communities).
7654
77−- Read the [Development Docs](/docs/).
78−- Check out the development-driven [Getting Started guide](/docs/development/develop).
79−- Join [Hoon School Live (HSL)](https://hooniversity.org), the cohort-driven course that teaches you Hoon, with the goal of getting you comfortable writing generators, working with core concepts, using the standard library, and distributing code using desks.
55+**Build**: If you're the kind of person who wants to build applications directly for discerning communities with built-in identity and networking primitives, or even jump into the Urbit kernel's core, visit [Urbit Developers](https://developers.urbit.org/) to learn more.
content/getting-started/home-servers.mdnew file+27
@@ -0,0 +1,27 @@
1++++
2+title = "Home servers"
3+weight = 5
4+description = "Options for hosting with a home server"
5+tag = "selfhost"
6++++
7+
8+There are a variety of tools that make running Urbit at home straightforward on dedicated hardware. If your enjoy hardware ownership and full embracing the spirit of decentralization, then these tools are for you.
9+
10+
11+## Native Planet
12+
13+[![Native Planet Tellurian](https://storage.googleapis.com/media.urbit.org/site/getting-started/native-planet.jpg)](https://www.nativeplanet.io/hardware)
14+
15+Purchase a [computer designed to run Urbit](https://www.nativeplanet.io/hardware), out of the box.
16+
17+## Groundseg & Startram
18+
19+[![Groundseg UI](https://storage.googleapis.com/media.urbit.org/site/getting-started/groundseg.png)](https://www.nativeplanet.io/software)
20+
21+Install these [Native Planet software packages](https://www.nativeplanet.io/software) to turn a Linux computer into an urbit that's accessible from anywhere in the world.
22+
23+## Umbrel
24+
25+[![Umbrel Screenshot](https://storage.googleapis.com/media.urbit.org/site/getting-started/umbrel.png)](https://umbrel.com/)
26+
27+Install the [Urbit application](https://subject.network/posts/urbit-apps-umbrel/) on a Raspberry Pi running [Umbrel](https://umbrel.com/).
content/getting-started/hosted.md+19−12
@@ -1,23 +1,30 @@
11+++
2−title = "Hosted urbit"
3−description = "Run Urbit on a managed service"
4−weight = 3
2+title = "Overview"
3+weight = 0
4+description = "Running Urbit with a hosting provider"
5+tag = "hostprov"
56+++
67
7−### 1. Select a hosting provider
8+Hosting providers are companies that offer "Urbit as a Service". They do the work of setting up your urbit in the cloud and making sure it's up to date and you don't have perform any technical steps or maintenance.
89
9−Hosting providers can sell you a planet and manage the hosting for you for a regular fee. We recommend [ThirdEarth](https://third.earth/) for quickly acquiring a planet and the hosting required to make your Urbit experience accessible from anywhere.
10+![Hosting Providers](https://storage.googleapis.com/media.urbit.org/site/getting-started/hosting-providers.png)
1011
11−Two important points about hosting providers:
12+Generally, you'll get an Urbit ID by signing up with a hosting provider, but some allow you to bring your own Urbit ID, or even your pier (all your urbit data.)
1213
13−- Because the provider has access to the resources that run your Urbit experience, you must trust them with your data.
14+While hosting providers offer convenience and customer support, hosting does
15+mean trusting your provider with your data, just as you would any internet
16+service company. Unlike typical internet services however, Urbit makes it
17+possible to leave a hosting provider with your Urbit ID, which you can then use
18+to switch hosting provider or self-host.
1419
15−- Urbit has portable data, so you should be able to work with a hosting provider to download all your data and boot up elsewhere if you choose to migrate or start self-hosting.
20+The two important points one should remember about hosting providers:
1621
17−### 2. Log in
22+- Because the provider has access to the resources that run your Urbit
23+ experience, you must trust them with your data.
24+- Urbit is designed to be portable, so your hosting provider will allow you to
25+ export all your data and boot up elsewhere if you choose.
1826
19−The exact steps for logging into your Urbit will depend on your hosting provider's infrastructure and the flow they've developed. If you have questions about logging into your hosted Urbit ship, contact their support.
2027
21−### Next steps
28+## Next steps
2229
23−Learn how to [get around your urbit](/getting-started/getting-around).
30+[Explore Hosting Providers -&gt;](/getting-started/hosting-providers)
content/getting-started/hosting-providers.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+title = "Hosting Providers"
3+weight = 2
4+description = "Companies that provide Urbit hosting as a service"
5+tag = "hostprov"
6++++
7+
8+
9+## Tlon
10+[Tlon](https://tlon.io) is the company responsible for creating Urbit, Landscape, Groups and Talk. [Tlon](https://tlon.io) offers Urbit hosting for free, which includes a planet of your choice.
11+
12+[![Tlon](https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/tlon-hosting-provider.png)](https://tlon.io/)
13+
14+## Planet One
15+
16+[Planet One](https://planet.one), a [Tirrel](https://urbit.org/organizations/tirrel) service, offers Urbit hosting for $15/month. You can also obtain hosting through their native Desktop application, [Scene](https://planet.one/scene).
17+
18+[![Planet One Hosting](https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/planetone-hosting.png)](https://planet.one/)
19+
20+## Third Earth
21+
22+[ThirdEarth](https://third.earth) offers hosting for $11.99/month. Third Earth is the only hosting provider that allows you to join with an existing Urbit ID and pier, i.e. a planet that you have already booted elsewhere. If you don't have a planet yet, they can also provide you with one.
23+
24+[![Third Earth Hosting](https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/thirdearth-hosting.png)](https://third.earth/)
content/getting-started/installing-applications.md+17−19
@@ -1,41 +1,39 @@
11+++
22title = "Installing apps"
3−tag = "additional"
3+tag = "around"
44weight = 3
55+++
66
7−### 1. Get on the network
7+Installing Urbit applications is simple. Search for the developer and download the application directly from them. We'll walk you through it.
88
9−First, you’ll need to get on Urbit. You can quickly check out the network by [downloading the Port application](https://github.com/urbit/port) and booting up a comet–a temporary Urbit ID.
9+### 1. Finding applications
1010
11−For long-term use, you’ll want to get a permanent Urbit ID and consider a running your urbit in the cloud or on a hosted service.
11+To install an application, you'll need to know the ship it is distributed from, which is often its developer's Urbit ID, *e.g.* `~paldev` or `~dister-fabnev-hinmur`. If you know the application, you can enter the full shortcode, e.g. `~paldev/pals`.
1212
13−Read our [Getting Started guide](https://urbit.org/install) for details.
13+You can find a [public directory of applications](/ecosystem?type=applications) in the Ecosystem section of urbit.org.
1414
15−### 2. Finding applications
15+Not all applications are listed on urbit.org, so you’ll discover more by actively using Urbit and meeting people.
1616
17−Urbit is still in its early stages, so you’ll need to join groups and browse around the network to discover new applications as they are being brought up.
17+However, we can get started by using a simple app from Urbit developer [`~paldev`](/ids/~paldev).
1818
19−However, we can get started a simple app from Urbit developer [`~paldev`](/ids/~paldev).
19+### 2. Search for a Developer
2020
21−### 3. Search for a Developer
22−
23−Once you’re on the network, you’ll see and large tiled interface with a few applications installed and a search bar on the top of the page.
21+Once you’re on the network, you’ll see a large tiled interface with a few applications and a search bar on the top of the page.
2422
2523Click and the search bar and search for the software provider’s Urbit ID.
2624
27−For example, to install the picture application, search for `~paldev` and then click on the result for `~paldev` to show his applications.
25+For example, to install the pals application, search for `~paldev` and then click on the result for `~paldev` to show the applications.
2826
29−![](https://media.urbit.org/site/additional-guides/Installing-apps-1.jpg)
27+![](https://media.urbit.org/site/getting-started/install-apps-1.png)
3028
31−![](https://media.urbit.org/site/additional-guides/Installing-apps-2.jpg)
29+![](https://media.urbit.org/site/getting-started/install-apps-2.png)
3230
33−### 4. Get the Application
31+### 3. Get the Application
3432
35−After selecting the “picture” app, a pane will open that shows some information about the application. Go ahead and click the “Get App” button, and confirm the following modal window to begin the installation process.
33+Select the pals app, and a modal window will open that shows some information about the application. Go ahead and click the “Get App” button, and confirm the following modal window to begin the installation process.
3634
37−Soon you’ll have a new application tile on your home screen that will let you upload and display a picture to your home screen.
35+![](https://media.urbit.org/site/getting-started/install-apps-3.png)
3836
39−![](https://media.urbit.org/site/additional-guides/Installing-apps-3.jpg)
37+Soon you’ll have a new application tile on your home screen. Now you can add people you know on the network as your pals just by entering their Urbit ID.
4038
41−![](https://media.urbit.org/site/additional-guides/Installing-apps-4.jpg)
39+![](https://media.urbit.org/site/getting-started/install-apps-4.png)
content/getting-started/interfaces.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Interfaces"
3+weight = 4
4+description = "Ways to interact with Urbit"
5+tag = "around"
6++++
7+
8+Urbit ships by default with Landscape by [Tlon](https://tlon.io), a web-based interface for managing your ship and the software installed on it, and launching other web-based applications. However, there are many ways to interact with your Urbit.
9+
10+There's [EScape](https://urbit.org/applications/~fabnev-hinmur/escape), a fork of Groups that also has an accompanying mobile application. [Scene](https://tirrel.io/scene/index.html) and the (soon to be released) [Realm](https://www.holium.com/) offer native desktop window managers for your urbit. Lastly, there's the [Dojo](https://developers.urbit.org/overview/dojo) CLI interface for developers
content/getting-started/joining-groups.md+24−28
@@ -1,58 +1,54 @@
11+++
22title = "Joining groups"
3−tag = "additional"
3+tag = "around"
44weight = 2
55+++
66
7−### 1. Get on the network
7+Joining public groups is straightforward: search for the group host's Urbit ID, and join. Some groups are private, so you'll need approval to join.
88
9−First, you’ll need to get on Urbit. You can quickly check out the network by [downloading the Port application](https://urbit.org/getting-started/desktop) and booting up a comet–a temporary Urbit ID.
9+And still other groups are secret! Which means you can't find them, and you'll need to be invited to join.
1010
11−For long-term use, you’ll want to get a permanent Urbit ID and consider a running your urbit in the cloud or on a hosted service.
11+Let's walk through the process of finding and joining a public group.
1212
13−Read our [Getting Started guide](https://urbit.org/install) for details.
1413
15−### 2. Open the Groups app
14+### 1. Open the Groups app
1615
17−Once you’re on the network, you’ll see and large tiled interface with a few applications installed: Terminal, Groups, and Bitcoin. Click on Groups.
16+Once you’re on the network, you’ll see Landscape, which is filled with large applications tiles: Talk, Terminal, and Groups. Click on Groups.
1817
19−![](https://media.urbit.org/site/additional-guides/Joining-groups-1.jpg)
18+![](https://storage.googleapis.com/media.urbit.org/site/getting-started/get-oriented.png)
2019
21−### 3. Enter the group shortcode
20+### 2. Enter the group shortcode
2221
23−We’ll start by joining Urbit Community, a friendly introductory Urbit group.
22+To join a group, you'll need to know its host Urbit ID (e.g. `~bitbet-bolbel`) or its full Urbit address, also called a shortcode (e.g. `~bitbet-bolbel/urbit-community`) .
2423
25−In the Groups app, click the “Join Group” button and enter `~bitbet-bolbel/urbit-community`.
24+Check out some public groups in the [urbit.org groups directory](/ecosystem?type=groups)
2625
27−Then confirm by clicking with the second “Join Group” button.
26+As an example, we’ll start by joining [UF Public](/groups/~halbex-palheb/uf-public), the Urbit Foundation's official group.
2827
29−![](https://media.urbit.org/site/additional-guides/Joining-groups-2.jpg)
30−![](https://media.urbit.org/site/additional-guides/Joining-groups-3.jpg)
28+In the Groups app, click on "Find Groups" in the left column and enter `~halbex-palheb/uf-public`
3129
32−### 4. Confirm join
30+Then click on the "Join" button once the group appears.
3331
34−You should see a window that provides a description and group information. If not, check the spelling of the group name and address and try again.
32+![](https://media.urbit.org/site/additional-guides/groups-2.png)
3533
36−Alternatively, the ship that is hosting the group may be offline.
3734
38−Click "Join Urbit Community".
35+### 3. Join channels
3936
40−![](https://media.urbit.org/site/additional-guides/Joining-groups-4.jpg)
37+After a few moments the default channels will load. For groups with a large backlog, such as Urbit Community (~bitbet-bolbel/urbit-community), this may take a few minutes.
4138
42−### 5. Join channels
39+![](https://media.urbit.org/site/additional-guides/groups-3.png)
4340
44−Congratulations, if you’re seeing a window like the one that appears below then you’ve joined the group!
4541
46−There two types of channels in the left column: Chats, and Notebooks. The former is self-explanatory, while the latter is like a blog with optional comments.
42+We can join more channels in the group by clicking on the "All Channels" link in the left column.
4743
48−To join a channel within the group, select a channel name from the left column, and click the Join Channel button.
44+![](https://media.urbit.org/site/additional-guides/groups-5.png)
4945
50−![](https://media.urbit.org/site/additional-guides/Joining-groups-4.jpg)
5146
52−![](https://media.urbit.org/site/additional-guides/Joining-groups-6.jpg)
5347
54−### 6. Chat and post on the network
48+### 4. Chat and post on the network
5549
56−Congratulations you’re now a part of a peer-to-peer Urbit group. Be friendly, be curious, and have fun.
50+In addition to posting text, you can now react, start threads, and reference messages by hovering over chat messages. And you can leave comments in notebooks if they are enabled.
5751
58−![](https://media.urbit.org/site/additional-guides/Joining-groups-7.jpg)
52+Remember to be nice, and have fun.
53+
54+![](https://media.urbit.org/site/additional-guides/groups-4.png)
content/getting-started/self-host.mdnew file+33
@@ -0,0 +1,33 @@
1++++
2+title = "Overview"
3+weight = 1
4+description = "Running your own urbit"
5+tag = "selfhost"
6++++
7+
8+
9+To run Urbit on your own you need to be comfortable using a command line
10+interface (CLI), and should have a basic understanding of how to interact with
11+the Ethereum blockchain.
12+
13+Urbit OS is comprised of a virtual operating system (Arvo) and a runtime called
14+(Vere). The runtime has official versions targeting Linux and macOS, although
15+workarounds exist for Windows.
16+
17+Running Urbit locally is good for experimentation, but in the long term you'll
18+want to run it as a server — always on and accessible from anywhere. The nice
19+thing about Urbit is that's easy to start local, and later move to cloud hosting
20+or a home server. Or you can start with the latter options.
21+
22+**Remember, never run your Urbit in more than one place!** Doing so will necessitate
23+a [factory reset](https://operators.urbit.org/manual/id/guide-to-resets).
24+
25+## Next Steps
26+
27+- [Get an Urbit ID](/getting-started/get-id) – Get a planet, a permanent Urbit ID, for the best networked experience.
28+
29+- [CLI instructions](/getting-started/cli) – Set up Vere, the Urbit runtime, using the command line.
30+
31+- [Install on the cloud](/getting-started/cloud-hosting) – A step-by-step guide to setting up Urbit on a VPS.
32+
33+- [Set up a home server](/getting-started/home-servers) – Explore options for running your own dedicated physical Urbit computer.
content/grants/bitcoin-node-json-rpc-api-part-1.md → content/grants/2019/bitcoin-node-json-rpc-api-part-1.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "1 star"
1313assignee = ["yosoyubik"]
1414id = "649469235"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920#### Background
content/grants/bitcoin-node-json-rpc-api-part-2.md → content/grants/2019/bitcoin-node-json-rpc-api-part-2.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "1 star"
1313assignee = ["pkova"]
1414id = "1577544668"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920#### Background
content/grants/bitcoin-node-json-rpc-api-part-3.md → content/grants/2019/bitcoin-node-json-rpc-api-part-3.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "1 star"
1313assignee = ["yosoyubik"]
1414id = "312452925"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920#### Background
content/grants/bitcoin-node-json-rpc-api-part-4.md → content/grants/2019/bitcoin-node-json-rpc-api-part-4.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "2 stars"
1313assignee = ["yosoyubik"]
1414id = "87854308"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920#### Background
content/grants/bitcoin-wallet-on-bridge.md → content/grants/2019/bitcoin-wallet-on-bridge.mdrenamed+2−1
@@ -14,7 +14,8 @@ assignee = ["yosoyubik"]
1414id = "273059635"
1515completed = false
1616canceled = true
17−link = ""
17+link = "~pindet-timmut/urbitcoiners"
18+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1819+++
1920
2021### Background
content/grants/escape.md → content/grants/2019/escape.mdrenamed

The content is the same.

content/grants/gall-api-documentation.md → content/grants/2019/gall-api-documentation.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-1.md → content/grants/2019/host-two-urbit-meetups-1.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Host two Urbit meetups in your city."
1212reward = "1 star"
13−assignee = ["sitful-hatred"]
13+assignee = ["~sitful-hatred"]
1414id = ""
1515completed = true
1616link = ""
content/grants/host-two-urbit-meetups-10.md → content/grants/2019/host-two-urbit-meetups-10.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-2.md → content/grants/2019/host-two-urbit-meetups-2.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Host two Urbit meetups in your city."
1212reward = "1 star"
13−assignee = ["Matthew Levan", "nforbes6"]
13+assignee = ["~mastyr-bottec", "nforbes6"]
1414id = ""
1515completed = true
1616link = ""
content/grants/host-two-urbit-meetups-3.md → content/grants/2019/host-two-urbit-meetups-3.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-4.md → content/grants/2019/host-two-urbit-meetups-4.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-5.md → content/grants/2019/host-two-urbit-meetups-5.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-6.md → content/grants/2019/host-two-urbit-meetups-6.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-7.md → content/grants/2019/host-two-urbit-meetups-7.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-8.md → content/grants/2019/host-two-urbit-meetups-8.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-9.md → content/grants/2019/host-two-urbit-meetups-9.mdrenamed

The content is the same.

content/grants/ragnarok-online-on-urbit.md → content/grants/2019/ragnarok-online-on-urbit.mdrenamed

The content is the same.

content/grants/udon-syntax-highlighter.md → content/grants/2019/udon-syntax-highlighter.mdrenamed

The content is the same.

content/grants/unit-tests-for-json-parsing.md → content/grants/2019/unit-tests-for-json-parsing.mdrenamed

The content is the same.

content/grants/unit-tests-for-pure-algorithms.md → content/grants/2019/unit-tests-for-pure-algorithms.mdrenamed

The content is the same.

content/grants/unit-tests-for-sha-functions.md → content/grants/2019/unit-tests-for-sha-functions.mdrenamed

The content is the same.

content/grants/unit-tests-for-zuse-cryptographic-functions.md → content/grants/2019/unit-tests-for-zuse-cryptographic-functions.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Dev Tool" ]
1010image = ""
1111description = "Write unit tests for cryptographic functions of the Zuse library."
1212reward = "1 star"
13−assignee = ["lukechampine"]
13+assignee = ["~watter-parter"]
1414id = "1097913361"
1515completed = true
1616link = ""
content/grants/a-book-about-urbit.md → content/grants/2020/a-book-about-urbit.mdrenamed

The content is the same.

content/grants/a-network-enabled-spatial-database-and-demonstration-app.md → content/grants/2020/a-network-enabled-spatial-database-and-demonstration-app.mdrenamed+2−2
@@ -10,9 +10,9 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Allow small scale spatial data to be stored and retrieved in Urbit, for use in landscape and external applications, and shared across ships."
1212reward = "4 stars"
13−assignee = ["Lumphead"]
13+assignee = ["~lomped-firser"]
1414id = "634393623"
15−completed = false
15+completed = true
1616link = ""
1717+++
1818
content/grants/antechamber.md → content/grants/2020/antechamber.mdrenamed

The content is the same.

content/grants/art-by-urbit.md → content/grants/2020/art-by-urbit.mdrenamed

The content is the same.

content/grants/bart-train-tracker-landscape-tile.md → content/grants/2020/bart-train-tracker-landscape-tile.mdrenamed

The content is the same.

content/grants/bitcoin-full-node-provider-and-wallet.md → content/grants/2020/bitcoin-full-node-provider-and-wallet.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "6 stars"
1313assignee = ["~timluc-miptev"]
1414id = "2056919898"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920## Introduction
content/grants/bitcoin-key-derivation.md → content/grants/2020/bitcoin-key-derivation.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "2 stars"
1313assignee = ["pkova"]
1414id = "794126751"
1515completed = true
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920## Overview
content/grants/boston-t-train-tracker-landscape-tile.md → content/grants/2020/boston-t-train-tracker-landscape-tile.mdrenamed

The content is the same.

content/grants/calendar-ui.md → content/grants/2020/calendar-ui.mdrenamed

The content is the same.

content/grants/calendar.md → content/grants/2020/calendar.mdrenamed

The content is the same.

content/grants/content-saver.md → content/grants/2020/content-saver.mdrenamed

The content is the same.

content/grants/cta-train-tracker-landscape-tile.md → content/grants/2020/cta-train-tracker-landscape-tile.mdrenamed

The content is the same.

content/grants/display-eth-data.md → content/grants/2020/display-eth-data.mdrenamed

The content is the same.

content/grants/docker-image-for-cloud-container-orchestration.md → content/grants/2020/docker-image-for-cloud-container-orchestration.mdrenamed

The content is the same.

content/grants/ethereum-abi-parser.md → content/grants/2020/ethereum-abi-parser.mdrenamed

The content is the same.

content/grants/go-airlock-library.md → content/grants/2020/go-airlock-library.mdrenamed

The content is the same.

content/grants/haskell-airlock-library.md → content/grants/2020/haskell-airlock-library.mdrenamed

The content is the same.

content/grants/hoon-001-learner-efficiency-and-early-learner-resources.md → content/grants/2020/hoon-001-learner-efficiency-and-early-learner-resources.mdrenamed

The content is the same.

content/grants/host-three-college-university-urbit-meetups-1.md → content/grants/2020/host-three-college-university-urbit-meetups-1.mdrenamed

The content is the same.

content/grants/host-three-college-university-urbit-meetups-2.md → content/grants/2020/host-three-college-university-urbit-meetups-2.mdrenamed

The content is the same.

content/grants/host-three-college-university-urbit-meetups-3.md → content/grants/2020/host-three-college-university-urbit-meetups-3.mdrenamed

The content is the same.

content/grants/host-three-virtual-urbit-meetups.md → content/grants/2020/host-three-virtual-urbit-meetups.mdrenamed

The content is the same.

content/grants/links-in-urbit-reference-docs.md → content/grants/2020/links-in-urbit-reference-docs.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Documentation" ]
1010image = ""
1111description = "Add links to our reference doc pages so that people can easily discover new concepts"
1212reward = "1 star"
13−assignee = ["alecbrick"]
13+assignee = ["~nolrev-motbyr"]
1414id = "45608361"
1515completed = true
1616canceled = false
content/grants/llelogram.md → content/grants/2020/llelogram.mdrenamed

The content is the same.

content/grants/matrices-in-hoon.md → content/grants/2020/matrices-in-hoon.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Add array types to Hoon."
1212reward = "5 stars"
13−assignee = ["N E Davis"]
13+assignee = ["~lagrev-nocfep"]
1414id = "611660914"
1515completed = true
1616link = ""
content/grants/matrixriotim-bridge-bot.md → content/grants/2020/matrixriotim-bridge-bot.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "This would be a python bot to connect urbit to any Matrix server. It would act as a bridge, mirroring messages between the two platforms."
1212reward = "2 stars"
13−assignee = ["modmes-livheb"]
13+assignee = ["~modmes-livheb"]
1414id = "1496457780"
1515completed = false
1616canceled = true
content/grants/open-street-maps-data-importation.md → content/grants/2020/open-street-maps-data-importation.mdrenamed

The content is the same.

content/grants/staff-the-urbit-help-desk-1.md → content/grants/2020/staff-the-urbit-help-desk-1.mdrenamed

The content is the same.

content/grants/staff-the-urbit-help-desk-2.md → content/grants/2020/staff-the-urbit-help-desk-2.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Help Urbit users with their various problems."
1212reward = "1 star"
13−assignee = ["sicbud (and i cannot stress this enough) hathes"]
13+assignee = ["~sicbud-hathes"]
1414id = "612547183"
1515completed = true
1616link = ""
content/grants/staff-the-urbit-helpdesk-west.md → content/grants/2020/staff-the-urbit-helpdesk-west.mdrenamed

The content is the same.

content/grants/the-complete-guide-to-gall-and-landscape.md → content/grants/2020/the-complete-guide-to-gall-and-landscape.mdrenamed

The content is the same.

content/grants/tor-nodes-relay-search-tile.md → content/grants/2020/tor-nodes-relay-search-tile.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "An Urbit-native Tor search-tool."
1212reward = "3 stars"
13−assignee = ["pilwex-migsun"]
13+assignee = ["~pilwex-migsun"]
1414id = "872371692"
1515completed = false
1616canceled = true
content/grants/typescript-airlock-library.md → content/grants/2020/typescript-airlock-library.mdrenamed

The content is the same.

content/grants/up-to-date-hoon-reference-card.md → content/grants/2020/up-to-date-hoon-reference-card.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Documentation" ]
1010image = ""
1111description = "I have made an up-to-date version of the Urbit Hoon reference card and will maintain it.https://github.com/natareo/hooncard"
1212reward = "1 star"
13−assignee = ["N E Davis"]
13+assignee = ["~lagrev-nocfep"]
1414id = "607772785"
1515completed = true
1616link = ""
content/grants/urbian-a-customized-linux-distribution-for-urbit-appliances.md → content/grants/2020/urbian-a-customized-linux-distribution-for-urbit-appliances.mdrenamed

The content is the same.

content/grants/urbit-event-series.md → content/grants/2020/urbit-event-series.mdrenamed

The content is the same.

content/grants/urbit-explainer-video.md → content/grants/2020/urbit-explainer-video.mdrenamed

The content is the same.

content/grants/urbit-http-api-for-kotlin.md → content/grants/2020/urbit-http-api-for-kotlin.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Write an urbit HTTP API (aka Airlock) for Kotlin."
1212reward = "3 stars"
13−assignee = ["@nrtxrmnd"]
13+assignee = ["~nortex-ramnyd"]
1414id = "865786150"
1515completed = false
1616canceled = true
content/grants/urbit-http-api-for-rust.md → content/grants/2020/urbit-http-api-for-rust.mdrenamed

The content is the same.

content/grants/urbit-http-interface-java-edition.md → content/grants/2020/urbit-http-interface-java-edition.mdrenamed

The content is the same.

content/grants/urbit-http-library-for-ruby.md → content/grants/2020/urbit-http-library-for-ruby.mdrenamed

The content is the same.

content/grants/urbit-online-meetup.md → content/grants/2020/urbit-online-meetup.mdrenamed

The content is the same.

content/grants/urbit-ship-and-star-hosting-and-troubleshooting-docs.md → content/grants/2020/urbit-ship-and-star-hosting-and-troubleshooting-docs.mdrenamed

The content is the same.

content/grants/verifying-urbit-id-on-keybase.md → content/grants/2020/verifying-urbit-id-on-keybase.mdrenamed

The content is the same.

content/grants/web-scraper.md → content/grants/2020/web-scraper.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "It is often useful for archival purposes to pull down an entire website, however many sites have a complex network of pages that would be difficult to download one at a time."
1212reward = "1 star"
13−assignee = ["tug"]
13+assignee = ["~dalsup-ridges"]
1414id = "1967189374"
1515completed = false
1616canceled = true
content/grants/analytics-script.md → content/grants/2021/analytics-script.mdrenamed

The content is the same.

content/grants/authenticate-with-urbit.md → content/grants/2021/authenticate-with-urbit.mdrenamed

The content is the same.

content/grants/azimuth-cli.md → content/grants/2021/azimuth-cli.mdrenamed

The content is the same.

content/grants/bitcoin-wallet-maintenance.md → content/grants/2021/bitcoin-wallet-maintenance.mdrenamed+3−1
@@ -10,9 +10,11 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "Help us maintain the Bitcoin Wallet."
1212reward = "3 stars"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = ["~finned-palmer"]
1515completed = true
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1618work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0032&prefill_Grant+Name=Bitcoin%20Wallet%20Maintenance"
1719+++
1820
content/grants/bridge-l2-revamp.md → content/grants/2021/bridge-l2-revamp.mdrenamed

The content is the same.

content/grants/clojure-urbit-client.md → content/grants/2021/clojure-urbit-client.mdrenamed+2−2
@@ -8,11 +8,11 @@ grant_category = ["App Dev - Other"]
88image = ""
99description = "Urbit client for the Clojure programming language"
1010reward = "3 stars"
11−champion = "~littel-wolfur"
11+champion = ["~littel-wolfur"]
1212assignee = ["~sorted-falnyd"]
1313grant_id = "P0072"
1414completed = false
15−canceled = false
15+canceled = true
1616link = ""
1717+++
1818
content/grants/comprehensive-local-server-and-mum-explanation-video.md → content/grants/2021/comprehensive-local-server-and-mum-explanation-video.mdrenamed

The content is the same.

content/grants/contacts.md → content/grants/2021/contacts.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "Contact Management App"
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = [""]
1515completed = false
1616canceled = true
content/grants/content-producer.md → content/grants/2021/content-producer.mdrenamed

The content is the same.

content/grants/cross-platform-desktop-urbit-app.md → content/grants/2021/cross-platform-desktop-urbit-app.mdrenamed

The content is the same.

content/grants/cypherscope-bot.md → content/grants/2021/cypherscope-bot.mdrenamed+1−1
@@ -10,7 +10,7 @@ description = "On-demand financial charts chat bot"
1010reward = "2 stars"
1111assignee = ["~mitten-dapper", "~ristyc-ridwyx"]
1212grant_id = "P0054"
13−completed = false
13+completed = true
1414canceled = false
1515link = ""
1616+++
content/grants/educational-guide-todomvc-urbit-edition.md → content/grants/2021/educational-guide-todomvc-urbit-edition.mdrenamed

The content is the same.

content/grants/feed-aggregator.md → content/grants/2021/feed-aggregator.mdrenamed

The content is the same.

content/grants/graph-store-documentation-guide.md → content/grants/2021/graph-store-documentation-guide.mdrenamed

The content is the same.

content/grants/guide-to-s3.md → content/grants/2021/guide-to-s3.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-11.md → content/grants/2021/host-two-urbit-meetups-11.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Urbit needs champions! The Urbit Foundation is looking for community members to host local or online meetups to spread the word."
1212reward = "1 star"
13−assignee = ["Thomas"]
13+assignee = ["~dalweb-donfun"]
1414id = ""
1515completed = true
1616link = ""
content/grants/host-two-urbit-meetups-12.md → content/grants/2021/host-two-urbit-meetups-12.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-13.md → content/grants/2021/host-two-urbit-meetups-13.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-14.md → content/grants/2021/host-two-urbit-meetups-14.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-15.md → content/grants/2021/host-two-urbit-meetups-15.mdrenamed

The content is the same.

content/grants/host-two-urbit-meetups-16.md → content/grants/2021/host-two-urbit-meetups-16.mdrenamed

The content is the same.

content/grants/json-jet.md → content/grants/2021/json-jet.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Create high performance JSON parsing/serializing jet."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = ["~finmep-lanteb"]
1515completed = true
1616canceled = false
content/grants/login-with-urbit.md → content/grants/2021/login-with-urbit.mdrenamed

The content is the same.

content/grants/machine-learning.md → content/grants/2021/machine-learning.mdrenamed+1−1
@@ -10,7 +10,7 @@ description = "Create a supervised machine learning library"
1010reward = "7 stars"
1111assignee = ["~tamdev-nocdun"]
1212grant_id = "P0059"
13−completed = false
13+completed = true
1414canceled = false
1515link = ""
1616+++
content/grants/market-interface.md → content/grants/2021/market-interface.mdrenamed

The content is the same.

content/grants/meetup-bom.md → content/grants/2021/meetup-bom.mdrenamed

The content is the same.

content/grants/minimal-urbit-os.md → content/grants/2021/minimal-urbit-os.mdrenamed

The content is the same.

content/grants/native-urbit.md → content/grants/2021/native-urbit.mdrenamed

The content is the same.

content/grants/network-explorer-data-pipeline-http-api.md → content/grants/2021/network-explorer-data-pipeline-http-api.mdrenamed

The content is the same.

content/grants/nuck-jet.md → content/grants/2021/nuck-jet.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Create new high performance string parser jet."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = [""]
1515completed = false
1616canceled = true
content/grants/overhaul-the-urbitorg-website.md → content/grants/2021/overhaul-the-urbitorg-website.mdrenamed

The content is the same.

content/grants/planet-sales.md → content/grants/2021/planet-sales.mdrenamed

The content is the same.

content/grants/pokur.md → content/grants/2021/pokur.mdrenamed

The content is the same.

content/grants/ra-debugging-tools.md → content/grants/2021/ra-debugging-tools.mdrenamed+4−4
@@ -8,10 +8,10 @@ grant_category = ["App Dev", "Arvo"]
88image = ""
99description = "Debugging Tools"
1010reward = "2 stars"
11−mentor = "~master-morzod"
12−assignee = ["~nosmes-sibwyx", "~topfet-parmed"]
13−completed = false
14−canceled = true
11+mentor = ["~master-morzod"]
12+assignee = ["~topfet-parmed"]
13+completed = true
14+canceled = false
1515work_request_link = ""
1616+++
1717
content/grants/ra-page-tracking.md → content/grants/2021/ra-page-tracking.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "Improve Page Tracking"
1212reward = "2 stars"
13−mentor = "~silsyn-wathep"
13+mentor = ["~silsyn-wathep"]
1414assignee = ["~fanfun-mocbud"]
1515completed = true
1616work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0039&prefill_Grant+Name=Runtime%20Apprenticeship%3A%20Improve%20Page%20Tracking"
content/grants/ra-segfaults.md → content/grants/2021/ra-segfaults.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "Segfaults"
1212reward = "2 stars"
13−mentor = "~silsyn-wathep"
13+mentor = ["~silsyn-wathep"]
1414assignee = [""]
1515completed = false
1616canceled = true
content/grants/ra-stack-overflow.md → content/grants/2021/ra-stack-overflow.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "Stack Overflow"
1212reward = "2 stars"
13−mentor = "~silsyn-wathep"
13+mentor = ["~silsyn-wathep"]
1414assignee = [""]
1515completed = false
1616canceled = true
content/grants/search-in-groups.md → content/grants/2021/search-in-groups.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Implement a basic text search in groups channels"
1212reward = "2 stars"
13−assignee = ["@nrtxrmnd"]
13+assignee = ["~nortex-ramnyd"]
1414id = "835369230"
1515completed = true
1616link = ""
content/grants/send-emails-to-a-mailing-list.md → content/grants/2021/send-emails-to-a-mailing-list.mdrenamed

The content is the same.

content/grants/smol-future-sustained-knowledge-sharing-and-marketing.md → content/grants/2021/smol-future-sustained-knowledge-sharing-and-marketing.mdrenamed

The content is the same.

content/grants/speech-recognition.md → content/grants/2021/speech-recognition.mdrenamed

The content is the same.

content/grants/staff-the-urbit-helpdesk-east.md → content/grants/2021/staff-the-urbit-helpdesk-east.mdrenamed

The content is the same.

content/grants/static-site-generation.md → content/grants/2021/static-site-generation.mdrenamed

The content is the same.

content/grants/thread-documentation.md → content/grants/2021/thread-documentation.mdrenamed

The content is the same.

content/grants/translate-key-parts-of-urbitorg-into-german.md → content/grants/2021/translate-key-parts-of-urbitorg-into-german.mdrenamed

The content is the same.

content/grants/translate-key-parts-of-urbitorg-into-korean.md → content/grants/2021/translate-key-parts-of-urbitorg-into-korean.mdrenamed

The content is the same.

content/grants/translate-key-parts-of-urbitorg-into-norwegian.md → content/grants/2021/translate-key-parts-of-urbitorg-into-norwegian.mdrenamed

The content is the same.

content/grants/translate-key-parts-of-urbitorg-into-spanish.md → content/grants/2021/translate-key-parts-of-urbitorg-into-spanish.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Documentation" ]
1010image = ""
1111description = "Help the Urbit community grow internationally by translating key resources, guides, and documentation to Spanish."
1212reward = "1 star"
13−assignee = ["Tom Holford"]
13+assignee = ["~datder-sonnet"]
1414id = "446864346"
1515completed = false
1616canceled = true
content/grants/try-urbit-website.md → content/grants/2021/try-urbit-website.mdrenamed

The content is the same.

content/grants/twitter-uv-extension.md → content/grants/2021/twitter-uv-extension.mdrenamed

The content is the same.

content/grants/ua-collaborative-text-editor.md → content/grants/2021/ua-collaborative-text-editor.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "A line-based editor for looking at text and code."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = ["~hanfel-dovned"]
1515completed = true
1616work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0019&prefill_Grant+Name=Collaborative%20text%20editor%20and%20annotator"
content/grants/ua-filesharer.md → content/grants/2021/ua-filesharer.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "An application that allows peers to upload files to managed storage, either on or off Urbit, and share files with each other."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = [""]
1515completed = true
1616work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0022&prefill_Grant+Name=Filesharer"
content/grants/ua-heads-up-poker.md → content/grants/2021/ua-heads-up-poker.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "A fun client app that would be a good way to get acquainted with Urbit's networking and p2p abilities."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = ["~bacwyl-samweg", "~hodzod-walrus"]
1515completed = true
1616work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0021&prefill_Grant+Name=Heads-up%20poker"
content/grants/ua-invoice-system.md → content/grants/2021/ua-invoice-system.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "A system to request and record payments made and received."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = [""]
1515completed = true
1616work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0020&prefill_Grant+Name=Invoice%20system"
content/grants/ua-marketplace.md → content/grants/2021/ua-marketplace.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Arvo" ]
1010image = ""
1111description = "A marketplace in which users can post items for sale and browse goods for sale by other users."
1212reward = "1 star"
13−mentor = "~timluc-miptev"
13+mentor = ["~timluc-miptev"]
1414assignee = ["~dachus-tiprel"]
1515grant_id = "A0009"
1616completed = false
content/grants/ucal-google-and-outlook-integration.md → content/grants/2021/ucal-google-and-outlook-integration.mdrenamed

The content is the same.

content/grants/urbit-api-for-elixir.md → content/grants/2021/urbit-api-for-elixir.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "A proposal to build an Urbit HTTP Api for the Elixir language, bringing to Urbit its state of the art concurrency capabilities."
1212reward = "3 stars"
13−assignee = ["mirtyl-wacdec"]
13+assignee = ["~mirtyl-wacdec"]
1414id = "2126792953"
1515completed = true
1616link = ""
content/grants/urbit-community-concierge-east-coast-2q2021.md → content/grants/2021/urbit-community-concierge-east-coast-2q2021.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Provide concierge service assisting new users in the Urbit Community Group"
1212reward = "1 star"
13−assignee = ["tocrex"]
13+assignee = ["~tocrex-holpen"]
1414id = "427340266"
1515completed = true
1616canceled = false
content/grants/urbit-community-concierge-east-coast.md → content/grants/2021/urbit-community-concierge-east-coast.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "Community" ]
1010image = ""
1111description = "Provide concierge service assisting new users in the Urbit Community Group"
1212reward = "1 star"
13−assignee = ["tocrex"]
13+assignee = ["~tocrex-holpen"]
1414id = "928966814"
1515completed = true
1616canceled = false
content/grants/urbit-community-concierge-west-coast-2q2021.md → content/grants/2021/urbit-community-concierge-west-coast-2q2021.mdrenamed

The content is the same.

content/grants/urbit-community-concierge-west-coast.md → content/grants/2021/urbit-community-concierge-west-coast.mdrenamed

The content is the same.

content/grants/urbit-http-api-for-emacs-elisp.md → content/grants/2021/urbit-http-api-for-emacs-elisp.mdrenamed

The content is the same.

content/grants/urbit-http-api-for-python.md → content/grants/2021/urbit-http-api-for-python.mdrenamed+2−2
@@ -10,10 +10,10 @@ grant_category = [ "App Dev: Other" ]
1010image = ""
1111description = "Write an Urbit HTTP API (aka airlock) for Python"
1212reward = "1 star"
13−assignee = ["novbyr-miclux"]
13+assignee = ["~novbyr-miclux"]
1414id = "P0029"
1515completed = false
16−canceled = false
16+canceled = true
1717link = ""
1818+++
1919
content/grants/urbit-irc-bridge.md → content/grants/2021/urbit-irc-bridge.mdrenamed

The content is the same.

content/grants/urbit-lfs-filehosting.md → content/grants/2021/urbit-lfs-filehosting.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Share large files"
1212reward = "4 stars"
13−assignee = ["tabnus-fondeg"]
13+assignee = ["~tabnus-fondeg"]
1414id = "1736585775"
1515completed = false
1616canceled = true
content/grants/urbit-notes.md → content/grants/2021/urbit-notes.mdrenamed+2−2
@@ -7,10 +7,10 @@ grant_category = ["App Dev: Other"]
77[extra]
88image = ""
99description = "Bring your note-taking game into the 31st century!"
10−reward = "2 stars"
10+reward = "4 stars"
1111assignee = ["~ribben-donnyl"]
1212grant_id = "P0056"
13−completed = false
13+completed = true
1414link = ""
1515+++
1616
content/grants/urbit-react-cookbook.md → content/grants/2021/urbit-react-cookbook.mdrenamed

The content is the same.

content/grants/uturn.md → content/grants/2021/uturn.mdrenamed+1−1
@@ -10,7 +10,7 @@ description = "TURN server support for WebRTC"
1010reward = "1 star"
1111assignee = ["~martyr-binbex"]
1212grant_id = "P0088"
13−completed = false
13+completed = true
1414link = ""
1515+++
1616
content/grants/uv-extension-library.md → content/grants/2021/uv-extension-library.mdrenamed

The content is the same.

content/grants/video-content-manager.md → content/grants/2021/video-content-manager.mdrenamed

The content is the same.

content/grants/volt-lightning-on-urbit.md → content/grants/2021/volt-lightning-on-urbit.mdrenamed+2−1
@@ -13,7 +13,8 @@ reward = "7 stars"
1313assignee = ["~dasrun-fadben"]
1414completed = true
1515canceled = false
16−link = ""
16+link = "~pindet-timmut/urbitcoiners"
17+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1718+++
1819
1920## Introduction
content/grants/webrtc-gall-agent-and-external-app.md → content/grants/2021/webrtc-gall-agent-and-external-app.mdrenamed

The content is the same.

content/grants/~home-urbit.md → content/grants/2021/~home-urbit.mdrenamed+1
@@ -11,6 +11,7 @@ reward = "4 stars"
1111assignee = ["~sipsen-pilser"]
1212id = ""
1313completed = false
14+canceled = true
1415link = ""
1516+++
1617
content/grants/abacus.md → content/grants/2022/abacus.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "Abacus: A basic calculator app with the ability to convert units"
1212reward = "1 star ($1k bonus if done by Assembly)"
1313assignee = ["~sorpes-ranrep"]
1414grant_id = "B0160"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0160&prefill_Grant+Name=Abacus"
1818+++
1919
content/grants/app-engram.md → content/grants/2022/app-engram.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "Engram is a knowledge management application that allows individu
1212reward = "7 stars"
1313assignee = ["~nolteg-tobtyc", "~dalsyr-diglyn"]
1414grant_id = "B0128"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0155&prefill_Grant+Name=Engram"
1818+++
1919
content/grants/app-openbsd.md → content/grants/2022/app-openbsd.mdrenamed+2−2
@@ -10,10 +10,10 @@ grant_category = [ "Runtime" ]
1010image = ""
1111description = "Get the project to the point where it works on OpenBSD"
1212reward = "1 star"
13−mentor = "~silsyn-wathep"
13+mentor = ["~silsyn-wathep"]
1414assignee = ["~tidsut-radryd"]
1515grant_id = "A0103"
16−completed = false
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0124&prefill_Grant+Name=Resurrect%20OpenBSD%20Build"
1818+++
1919
content/grants/2022/app-store.mdnew file+159
@@ -0,0 +1,159 @@
1++++
2+
3+title = "App Store"
4+date = "2022-09-12"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "A tool for decentralized curation and discovery of urbit applications"
13+reward = "4 stars"
14+assignee = ["~dilryd-mopreg"]
15+champion = ["~hodzod-walrus"]
16+grant_id = "P0182"
17+completed = false
18+canceled = false
19+link = ""
20+
21++++
22+
23+# App Store - Proposal
24+
25+### Motivation
26+
27+As an urbit user I want to be able to boot my ship and search for apps to download. I think that looking for apps through Groups is not the optimal solution. I want to be able to scroll through a page, find cool apps and easily download them. Non-technical and new-to-urbit users, especially, should be able to download apps and run them as smoothly as possible.
28+
29+### Making It Decentralized
30+
31+ My thinking started by looking at Google Play Store and figuring out how to create it on Urbit. But, Google Play is centralized - there is one curator (Google) for all the apps. Google is the one who both evaluates apps’ security (I hope), and is also responsible for curating which apps the users will see. Curation involves categories, recommendations, and search.
32+
33+I envision multiple Curator Sites - essentially, anybody who is willing to put in the effort, can become a Curator. I see it somewhat analogously to Groups: when the user first boots the Groups app, he is recommended to join the Urbit Community group. App Store would have it similar - there would be one “default” Curator (possibly Urbit Foundation, or whoever the community decides it to be), and other Curators the users would have to discover themselves.
34+
35+Right now, we don’t need more than one Curator as there are not as many apps. But in the future I could see Curators specializing in different types of apps (e.g. a curator for games, for utilities, …), I could see Developers or companies becoming Curators for themselves (making a Curator Site to showcase their own apps) and lastly, it is good to have the possibility of multiple “legitimate” sources of apps.
36+
37+### Categories of Users
38+- User
39+- Developer
40+- Curator
41+
42+### Categories of Service
43+- Curator Site
44+- App Page
45+
46+### Apps to be Created
47+- App Store
48+- Curator Site Server
49+- App Page Server
50+
51+### Basic User Story - Browsing and Downloading Apps
52+
53+I see a user story going something like this: The User opens App Store. The User can add a Curator by clicking on a button “Add Curator” and inputting the Curator’s ship name. He sees multiple Curators which he added previously. He opens one Curator Site, and sees a list of apps, categorized by the Curator. If the Curator hasn’t created categories, it will display all apps.
54+
55+A listing will contain an app icon, app name, a little description (added by the Curator), a direct download link, and a link to the App Page.
56+
57+The Curator Site can also allow the User to search by app name, description, tags in the search box, sort by rating, and display apps by category.
58+
59+The User finds an app he likes, clicks on it, and goes to a page containing information about the app. I will call this page App Page. He can also click on a link to download the app directly.
60+
61+This requires:
62+- App Page hosting by Developers
63+- Curator Site containing the data of the App Pages it displays, hosted by the Curator
64+- The User’s ship containing all the data of the Curators
65+
66+### App Page
67+
68+**Necessary Requirements**: The usual Urbit software distribution requirements should be listed: Desk Hash, Installed into (desk), Developer Desk, Last Software Update, License, Website, Version. There should be a “Get App” button.
69+
70+**Default Template**: Contains all necessary requirements plus description, screenshots, instructions, possibly other.
71+
72+The App Page should be customizable as long as it contains the Necessary Requirements.
73+
74+### Developer User Story - Using App Page Server
75+
76+The Developer enters the App Page Server app. There he can see a dashboard with all of his App Pages, displaying the comments and average rating of each. Each app has a delete and edit button next to it. App Pages are all served through App Page Server app, but the apps themselves can be hosted anywhere.
77+
78+To create an App Page, he clicks an “add” button on the dashboard, and then he will have to fill the template. He should enter the desk name (which should already be published on Grid) and fill in the Default Template. When he is finished with creating/editing an App Page, he will be redirected to the main page (dashboard of his apps).
79+
80+A Developer should have a separate App Page for each of his apps. If he wants to display them all in one place, he can create a Curator Site.
81+
82+### Curator Site
83+
84+**Necessary requirements**: Probably none. But likely all Curators will at least want to have hyperlinks to App Pages.
85+
86+**Default Template**: Possibly Sphinx-like listings, containing app name, icon, host, and tag, with a hyperlink to its App Page. There can be a default set of tags, and the Curator can modify it as he sees fit.
87+
88+On the back end, the Curator Site will be subscribing to App Pages, and gathering all their data to make searching and filtering possible.
89+
90+Curator Sites should also be customizable.
91+
92+### Curator User Story - Using Curator Site Server
93+
94+The Curator enters the Curator Site Server app. On the main page he sees a list of Developers (whose apps he is displaying), an input box for a list of categories, and a list of apps which he is displaying.
95+
96+The Curator can remove or add a Developer to his list of Developers. There will be a list of apps from that Developer, and the Curator can click on checkboxes of the apps he wants to display. These apps will automatically show up in his list of apps.
97+
98+The Curator can input categories for the apps. If no category is input, then the default will be “all”. Categories will be assigned to apps.
99+
100+The Curator can scroll through his list of apps, and each will have a “delete” and “edit” button next to it. The curator clicks on “edit” and then he can add his own description of the app and choose a category (based on those he input earlier). After confirming, his list will be updated and the Curator Site updated. He will then be redirected to the main page.
101+
102+### Miscellaneous Considerations
103+
104+- We don’t know how we would connect Grid software distribution with App Pages, whether it would be integrated or only hyperlinked.
105+- We don’t know how exactly will customization work. We want to make customizable CSS files for Developers and Curators which would be delivered to the Users.
106+
107+### Milestones
108+
109+Payment per milestone: 1 star
110+
111+**Milestone 1** - Setting up the minimum back end. Only CLI for now.
112+ETA: October 7th 2022.
113+
114+- The Developer should enter data basic info about his app through the command line.
115+- The Curator should subscribe to a Developer, and store all app data locally.
116+- The User should subscribe to a Curator, and be able to access data about apps locally.
117+
118+**Milestone 2** - Building up the features in the back end. Still only CLI.
119+ETA: November 4th 2022.
120+
121+- The Developer can now enter the whole App Page model, which includes a full set of metadata. He can edit and delete App Pages.
122+- The Curator can now add and delete categories, choose which apps to showcase, add and edit their own text/comment about the app.
123+- The User can now subscribe and unsubscribe from curators effectively, leave ratings and comments, and share the app.
124+- Designing all of the front end components and layouts of App Store, Curator Site Server and App Page Server in Figma, as described in detail in the User/Developer/Curator stories.
125+
126+**Milestone 3** - Building the front end and connecting it to the back end.
127+ ETA: December 2th 2022.
128+
129+- Building the front end in ReactJS according to our design from Milestone 2.
130+- Connect the front end to the back end, so that all roles can do everything they did in Milestone 2, but through a UI
131+- Add a search bar on the front end. It will be able to search by app name, Developer ship ID, tags, and possibly also pattern match through app descriptions.
132+
133+**Milestone 4** - Groups discovery and mobile view optimization.
134+
135+- As a curator, I want to list groups in my collection for users to browse
136+- As a user, I want to browse through a list of groups that a curator recommends to me
137+- As a user, I want to see a group’s name, description, and host, and join the group easily from the app store
138+- As a user, I want a mobile-optimized experience the app store so I can easily use the app inside the EScape mobile app or in a mobile browser
139+- App Store will be published and downloadable on urbit
140+- There will be detailed documentation for App Store, describing how it works and how to use it
141+- A github pull request will be submitted to [https://urbit.org/applications/submit](https://urbit.org/applications/submit)
142+
143+### About Us
144+
145+I was looking for stuff to do which might actually do some good for the world. So here I am. My name is Jurij Jukić, ~dilryd-mopreg. I have about a year of programming experience, mostly in Python. I recently quit my job to come work on Urbit full time. I just finished App School Live and I’m looking to build and learn.
146+
147+Joining me is Adrián Muñoz, ~hacpur-parbes. He has about a year of programming experience mainly in JavaScript (full stack) and a little bit of Python, Java and C#. He will primarily contribute to the front-end. He will learn Hoon as we go.
148+
149+### Future Considerations
150+
151+The App Store which I described as a proposal for me to build is nowhere near the full potential of App Store. I see many other avenues for improvement in the future, and I don’t want to bite off more than I can chew. Anyways, here are some things which could be built in the future.
152+
153+**Payments:** Developers should be able to sell their apps. There is a possibility of integration with books.
154+
155+**Distinguishing Trusted from Unsafe/Malicious Software:** I am unfamiliar with how software security audits usually work, but still, here is one completely unbaked idea.
156+
157+There are people who evaluate software - let’s call them Evaluators. There can be a part of the App Page where Evaluators can give technical reviews of the app. So when people go to App Page they will see which Evaluators have “approved” the app. The Evaluators’ reputation should be at stake here.
158+
159+This would somehow work by Users deeming Evaluators trusted. And Users could also deem other Users as trusted, so there could be a chain of trust, trackable to the Evaluator himself. I see this working together with pals. There is a lot more to think about here.
content/grants/app-urvault.md → content/grants/2022/app-urvault.mdrenamed+1−1
@@ -12,7 +12,7 @@ image = ""
1212description = "UrVault: Urbit Password Manager"
1313reward = "$12,000 in WSTR"
1414assignee = ["~dabber-sicsup"]
15−mentor = "~mocrux-nomdep"
15+mentor = ["~mocrux-nomdep"]
1616grant_id = "A01465"
1717completed = false
1818canceled = true
content/grants/app-uv-native-notificatons.md → content/grants/2022/app-uv-native-notificatons.mdrenamed+2−2
@@ -12,10 +12,10 @@ image = ""
1212description = "Build native notifications into Urbit Visor"
1313reward = "1 star"
1414assignee = ["~toclec-baldeg"]
15−mentor = "~haddef-sigwen"
15+mentor = ["~haddef-sigwen"]
1616grant_id = "A0119"
1717completed = false
18−canceled = false
18+canceled = true
1919link = ""
2020
2121+++
content/grants/apprenticeship-extending-bitcoin.md → content/grants/2022/apprenticeship-extending-bitcoin.mdrenamed+3−1
@@ -10,10 +10,12 @@ grant_category = [ "App Dev", "Other" ]
1010image = ""
1111description = ""
1212reward = "1 star"
13−mentor = "~dasrun-fadben"
13+mentor = ["~dasrun-fadben"]
1414assignee = ["~sipned-nistug"]
1515grant_id = "A0113"
1616completed = true
17+link = "~pindet-timmut/urbitcoiners"
18+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1719work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0138&prefill_Grant+Name=Extending%20the%20Bitcoin%20Provider%20API"
1820+++
1921
content/grants/apprenticeship-studio-collections.md → content/grants/2022/apprenticeship-studio-collections.mdrenamed+2−2
@@ -10,10 +10,10 @@ grant_category = [ "App Dev", "Other" ]
1010image = ""
1111description = "Extend ~tirrel's studio app content offering to include groups collections"
1212reward = "1 star"
13−mentor = "~novlud-padtyv"
13+mentor = ["~novlud-padtyv"]
1414assignee = ["~dachus-tiprel"]
1515grant_id = "A0147"
16−completed = false
16+completed = true
1717canceled = false
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0174&prefill_Grant+Name=Studio%20Collections"
1919+++
content/grants/apprenticeship-studio-email.md → content/grants/2022/apprenticeship-studio-email.mdrenamed+1−1
@@ -10,7 +10,7 @@ grant_category = [ "App Dev", "Other" ]
1010image = ""
1111description = "Build out email capabilities of ~tirrel's Studio app"
1212reward = "1 star"
13−mentor = "~novlud-padtyv"
13+mentor = ["~novlud-padtyv"]
1414assignee = ["~rivmud-fabwen"]
1515grant_id = "A0114"
1616completed = true
content/grants/astrolabe.md → content/grants/2022/astrolabe.mdrenamed+4−3
@@ -12,11 +12,12 @@ image = ""
1212description = "Urbit address space explorer"
1313reward = "5 stars"
1414assignee = ["~midlev-mindyr"]
15−champion = "~norsyr-torryn"
15+champion = ["~norsyr-torryn"]
1616grant_id = "P0099"
17−completed = false
17+completed = true
1818canceled = false
19−link = ""
19+link = "~poster-hoster-midlev-mindyr/astrolabe"
20+deliverable = "~midlev-mindyr/astrolabe"
2021
2122+++
2223
content/grants/2022/books-development.mdnew file+44
@@ -0,0 +1,44 @@
1++++
2+title = "Books feature development"
3+date = "2022-10-04"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Books is an application for managing your crypto wallets, transactions, and counterparties. It allows you to add your wallet and others' wallets, track balances and transactions, and add private annotations to all of the above."
12+reward = "2 stars"
13+assignee = ["~nismut-tamwep"]
14+champion = ["~dinleb-rambep"]
15+grant_id = "B0189"
16+completed = false
17+link = ""
18+deliverable = "~doller-doller-dozzod-dalten/books"
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0189&prefill_Grant+Name=Books%20Feature%20Development"
20++++
21+
22+[Books](https://urbit.org/grants/books) is an application for managing your crypto wallets, transactions, and counterparties. It allows you to add your wallet and other people’s, track balances and transactions, and add private annotations to all of the above.
23+
24+
25+# Overview
26+
27+Books was developed by Quartus and has is currently distributed from [~dister-dozzod-dalten](web+urbitgraph://~dister-dozzod-dalten/books). The Foundation has found internal use for Books and has decided to fund continued development for some key features.
28+
29+## Features in scope
30+
31+- Rolodex entries should support multiple public addresses.
32+- Transactions in the ledger should automatically be associated with known counterparties from the rolodex. The associations should happen even for transactions that happened before the rolodex entry was created.
33+- Books should recognize transactions involving Urbit stars.
34+- Books should be able to display balances.
35+- Books should issue notifications on incoming transactions.
36+
37+## Implementation Notes
38+
39+Books is distributed as a desk that contains `/app/books` and a frontend written in Vue. This bounty will require modifying the Urbit backend and the Vue frontend.
40+
41+The source code for Books lives at https://github.com/dalten-collective/books.
42+
43+## Milestones and Compensation
44+The applicant will receive 2 stars on completion of all the features in scope.
content/grants/books.md → content/grants/2022/books.mdrenamed+5−2
@@ -9,10 +9,13 @@ grant_category = [ "App Dev" ]
99[extra]
1010image = ""
1111description = "Books is an application for managing your crypto wallets, transactions, and counterparties. It allows you to add your wallet and others' wallets, track balances and transactions, and add private annotations to all of the above."
12−reward = "5-7 stars"
12+reward = "6 stars"
1313assignee = ["Quartus"]
14+champion = ["~wolref-podlex"]
1415grant_id = "B0109"
15−completed = false
16+completed = true
17+link = ""
18+deliverable = "~doller-doller-dozzod-dalten/books"
1619work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0134&prefill_Grant+Name=Books%3A%20address%20and%20transaction%20manager"
1720+++
1821
content/grants/2022/calendar-holium.mdnew file+53
@@ -0,0 +1,53 @@
1++++
2+title = "Calendar Feature Completion"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Calendar is a tool for creating events, inviting participants, and sharing your schedule with others."
12+reward = "3 stars"
13+assignee = [""]
14+champion = ["Holium"]
15+grant_id = "B0190"
16+completed = false
17+canceled = true
18+work_request_link="https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0190&prefill_Grant+Name=Calendar%20Feature%20Completion"
19++++
20+
21+# Calendar
22+
23+## Rationale
24+A calendar is one of the most useful tools for organizing events and appointments. It helps you juggle your professional and personal life.
25+
26+## Overview
27+Calendar: a calendar app with the ability to create/modify events, invite participants, share your calendar with others while using cross-platform synchronization to import/export events from other service providers like: Google, Apple, Outlook, Zoho, Proton, etc. and integration with Holium's Campfire app.
28+
29+## User stories
30+- As a user, I want to be able to create/modify an event.
31+- As a user, I want to be able to send email invites to a scheduled event.
32+- As a user, I want to share my calendar with team/group members.
33+- As a user, I want to import/export scheduled events between service providers.
34+- As a user, I want to update invited participants when a change is made to the scheduled event.
35+- As a user, I want to be able to switch between a calendar view and a schedule view.
36+- As a user, I want to schedule an event with a video call with Holium's Campfire app. (Potentially Future work)
37+
38+## Architecture
39+Within the app, there should be a Calendar view as well as a schedule view. It should also utilize cross-platform synchronization to import/export events from other service providers like: Google, Apple, Outlook, Zoho, Proton, etc. for a seamless experience.
40+
41+Holium will work with the developer(s) to provide frontend support, but the individual/team working on this bounty will be responsible for frontend implementation.
42+
43+## Milestones & Compensation
44+Milestones and final compensation will be determined in conjunction with the selected applicate, but is expected to be complete before the end of 2022 and approximately 3 Stars. Completion means having a working calendar app that accounts for all of the requirements listed in User stories and the app must be approved by Holium and it must be hosted for distribution on Holium's app star (as well as your own if desired).
45+
46+## Future work
47+- Creating a team calendar with a schedule view, to compare schedules with colleagues across any provider.
48+- Mobile access.
49+
50+## Requirements
51+- At least one years of professional programming experience
52+- Experience with full-stack development, including JS and some server-side language
53+- Graduated from Hoon school
content/grants/chess-bounty.md → content/grants/2022/chess-bounty.mdrenamed+7−3
@@ -10,15 +10,17 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Improvements to the Chess app, creating an Urbit Chess experience comparable to that of any modern Chess website"
1212reward = "3 stars"
13−assignee = [""]
13+assignee = ["~bonbud-macryg", "~nordus-mocwyl", "~rovmug-ticfyn"]
1414grant_id = "B0175"
15−champion = "~finmep-lanteb"
15+champion = ["~finmep-lanteb"]
1616completed = false
17+link = ""
18+deliverable = "~finmep-lanteb/chess"
1719work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0175&prefill_Grant+Name=Chess%3A%20Improved%2C%20Timed%2C%20%26%20Rated"
1820+++
1921
2022# Rationale
21−~finmep-lanteb is sponsoring the improvement of the Chess app to create an Urbit Chess experience comparable to that of any modern Chess website. The current Chess app meets the basic requirements to play a game with a friend, but lacks various quality of life features: move notifications, undo requests, %pals integration, etc. In addition, only unrated, correspondence games are currently possible. These missing features & improvements offer a great opportunity for a team of 3 novice Urbit developers (preferably three Hoon School Live and App School Live graduates) to work together to complete this bounty, each earning a star in the process.
23+[Omitted long matching line]
2224
2325The goals of this bounty are to resolve the quality of life issues present in the Chess app, as well as enable timed and rated games.
2426
@@ -47,4 +49,6 @@ Never say never, but there is a strong preference for 3 novice developers to wor
4749# Milestones and Compensation
4850Each of the three Deliverables above is a milestone. However, since the reward is 3 stars and designed to be completed by a 3-person team, it seems likely that the compensation schedule would be "1 star per person upon full completion". Specific details will be agreed upon with the contributor team prior to starting work.
4951
52+**Bonus** 3 additional stars will be paid to the contributors (1 each) if work is completed before October 2023
53+
5054
content/grants/chronicle.md → content/grants/2022/chronicle.mdrenamed+3−3
@@ -10,10 +10,10 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Chronicle is a news app that links all articles from group channels"
1212reward = "2 stars ($4k bonus if done by Assembly)"
13−assignee = [""]
13+assignee = ["~hanfel-dovned"]
1414grant_id = "B0161"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0161&prefill_Grant+Name=Chronicle"
1818+++
1919
content/grants/communal-computing.md → content/grants/2022/communal-computing.mdrenamed+2−2
@@ -9,9 +9,9 @@ image = ""
99description = "User research, domain research/synthesis, white paper creation and publicity effort around Urbit ID as a solution to questions of IoT identity sharing and privacy"
1010reward = "4.6 stars"
1111assignee = ["~pilwyc-fastec"]
12−mentor = "~simfur-ritwed"
12+mentor = ["~simfur-ritwed"]
1313grant_id = "P0113"
14−completed = false
14+completed = true
1515link = ""
1616+++
1717
content/grants/cue.md → content/grants/2022/cue.mdrenamed+2−2
@@ -12,10 +12,10 @@ image = ""
1212description = "A bookmarking tool that reminds you of content you saved for later"
1313reward = "4 stars"
1414assignee = ["~mallus-fabres"]
15−champion = "~fabled-faster"
15+champion = ["~fabled-faster"]
1616grant_id = "P0146"
1717completed = false
18−canceled = false
18+canceled = true
1919link = ""
2020
2121+++
content/grants/2022/desk-import-export.mdnew file+102
@@ -0,0 +1,102 @@
1++++
2+title = "Importing and exporting desks as jamfiles"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Improve the application development experience through simplified importing and exporting of desks."
12+reward = "2 stars"
13+champion = ["~tinnus-napbus"]
14+assignee = ["~niblyx-malnus"]
15+grant_id = "B0187"
16+completed = true
17+work_request_link="https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0187&prefill_Grant+Name=Desk%20jamfile%20import%2Fexport"
18++++
19+
20+## Rationale
21+
22+App development is typically done on a fake ship. Fake ships are isolated from
23+the network. If you're developing an app that interfaces with other apps, it is
24+inconvenient to install those apps on a fake ship as well as get the necessary
25+file dependencies into your own desk. Usually it involves cloning git repos,
26+copying around a bunch of files, and fiddling with desk merging, mounting and
27+editing.
28+
29+To simplify this process, a way to easily import/export desks and sets of
30+files is necessary.
31+
32+
33+## Overview
34+
35+An app should be developed that allows users to export desks or sets
36+of files as jamfiles through a web UI. The jamfiles can then be imported
37+and either initialise a desk or be merged into an existing desk.
38+
39+## User stories
40+
41+As a user, I can:
42+
43+- Jam a desk and download its jamfile through a web UI.
44+- Be presented with all files in a desk in a similar format to the output of the
45+ `+tree` generator, select a subset of those files, and export them in a
46+ jamfile through the web UI. I would use this to create jamfiles containing
47+ dependencies for other devs who want to interface with my app.
48+- Import a jamfile by fetching it from a URL I specify or by uploading it
49+ through a file browser dialog.
50+- Create a new desk from an imported jamfile.
51+- Merge an imported jamfile into an existing desk.
52+
53+## Implementation notes
54+
55+- This is going to require wrangling Clay datastructures which are a little
56+ complex (but not too bad).
57+
58+- Desk creation will have to be done with a `%park` `task:clay`, this is
59+ currently undocumented in the Clay docs as it's fairly low-level and not
60+ typically used from userspace. You can look at `new-desk:cloy` in `zuse.hoon`
61+ for how `%park` works. You can also refer to the code in [this
62+ PR](https://github.com/urbit/urbit/pull/5360) for inspiration.
63+
64+- It may be possible to design the jamfile to only contain the desk/files, but
65+ it may need to include additional metadata such as desk name, whether it's a
66+ full desk or just a set of files, etc. It is desirable for this information to
67+ be displayed to the user before they commit it to Clay. It would probably be
68+ good for it to list the files before commit too.
69+
70+- When the user wants to merge an imported desk into an existing one, they may
71+ need to be presented with merge strategies to choose from. It should probably
72+ default to a sane one so they don't need to think about it in most cases.
73+
74+- When exporting, a sensible naming scheme is desirable for the jamfile so it's
75+ obvious what it is.
76+
77+- It is probably desirable for the user to be able to choose older desk aeons to
78+ export. You would have to handle the possibility of tombstoning with this
79+ though.
80+
81+- Note: Clay no longer uses the `blob:clay` datastructure but now uses a simple
82+ `$page` in its place as defined in `arvo.hoon`. The docs are a bit out of date
83+ with this, so eg a `%blob` scry now returns a `page` rather than `blob:clay` as
84+ the docs say.
85+
86+- [Clay is reasonably well documented
87+ here.](https://developers.urbit.org/reference/arvo/clay/clay)
88+
89+- The front-end for this could be written in sail or something like React. It
90+ mostly just needs static forms so either will probably work.
91+
92+- The app probably doesn't need to store imports/exports in its state apart from
93+ maybe the current import temporarily if it needs to be examined for info to
94+ display to the user.
95+
96+## Milestones & Compenstation
97+
98+1. Implement full desk export and create a new desk from an imported jamfile.
99+ (1 star)
100+
101+2. Implement exporting a subset of a desk's files and merging imported desks
102+ into an existing desk with the user's choice of merge strategy. (1 star)
content/grants/digital-editor-MROB.md → content/grants/2022/digital-editor-MROB.mdrenamed+4−4
@@ -9,11 +9,11 @@ grant_category = ["Other"]
99[extra]
1010image = ""
1111description = "Digital Editor for the Mars Review of Books"
12−reward = "$4,500 in WSTR"
12+reward = "$4,500 USD"
1313assignee = ["~randem-wishes"]
14−champion = "~librex-dozryc"
14+champion = ["~librex-dozryc"]
1515grant_id = "B0115"
16−completed = false
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0140&prefill_Grant+Name=Digital%20Editor%2C%20Mars%20Review%20of%20Books"
1818+++
1919
@@ -39,7 +39,7 @@ The Digital Editor will be responsible for:
3939
4040## Compensation
4141
42−$1500 (in WSTR) per month for three months of work, with possibility of extension and increased compensation after the initial period of three months.
42+$1500 per month for three months of work, with possibility of extension and increased compensation after the initial period of three months.
4343
4444Month 1 deliverable: Mars Review group is successfully hosted on Urbit and contributors are onboarded
4545
content/grants/digital-storefront.md → content/grants/2022/digital-storefront.mdrenamed+3−3
@@ -12,7 +12,7 @@ image = ""
1212description = "Online Store for Selling Digital Content (Text / Audio / Video)"
1313reward = "3 stars"
1414assignee = ["~tirrel"]
15−champion = "~tacryt-socryp"
15+champion = ["~tacryt-socryp"]
1616grant_id = "P0140"
1717completed = false
1818canceled = false
@@ -63,9 +63,9 @@ Shop:
6363 ==
6464```
6565## User Stories
66−- John Murphy is a social media influencer who wants to sell his jazz album on the web. He looked at selling it using Shopify, but was turned off at the idea that he'd be dependent on Shopify and wouldn't be able to export his data if he ever wanted to move to a different webstore provider. John wants an online store solution that allows him to run the webstore himself on the server at his house without having to fiddle with it. John decides to download Tirrel Studio, because he heard they just added online store functionality. He sets up his website, adds his product details, decides how much it should cost, and then requests to be a merchant through their payment processor. John feels good knowing that he owns all of his shop's data and software, and that his only external dependency is on a payment processor that he could switch out for a different one.
66+[Omitted long matching line]
6767
68−- Timothy Gunn is an online conspiracy theorist who writes articles about the new world order. He has an avid online following, but sometimes his posts get too juicy for conventional platforms. He doesn't trust Substack and wants to host his newsletter himself but still get paid. His audience is a little too normie to use Bitcoin, and Bitcoin isn't that convenient for payments these days anyway. Timothy sets up his newsletter site via Studio, imports his mailing list from his old Mailchimp newsletter, requests to be a merchant, and then adds pay-walls in front of his best posts. Now he's ready to make money on his own terms.
68+[Omitted long matching line]
6969
7070- Jimmy Takeria is a big calisthenics guy who teaches other guys how to get jacked. He makes informational videos and posts them to YouTube as well as running a Discord community about calisthenics. Jimmy doesn't like YouTube and Discord's new misinformation policies because he has unconventional ideas about nutrition. Jimmy decides to move his community off of Discord and into Groups on Urbit, and sets up a Studio webstore where he sells access to his latest workout videos and cutting edge nutritional info on a subscription basis. He's satisfied that he can manage his entire online business using Urbit.
7171
content/grants/dusko-valve.md → content/grants/2022/dusko-valve.mdrenamed+1−1
@@ -11,7 +11,7 @@ image = ""
1111description = "a tool which allows NFT artists to offer planets for redemption to their patrons alongside their NFTs"
1212reward = "1.0 WSTR"
1313assignee = ["~tasset-norlux"]
14−champion = "~tacryt-socryp"
14+champion = ["~tacryt-socryp"]
1515grant_id = "P0118"
1616completed = true
1717canceled = false
content/grants/eth-provider.md → content/grants/2022/eth-provider.mdrenamed+1−1
@@ -12,7 +12,7 @@ description = "Eth-provider is a Gall agent that allows Urbit users to configure
1212reward = "3 stars"
1313assignee = ["~pontus-fadpun"]
1414grant_id = "B0117"
15−completed = false
15+completed = true
1616work_request_link="https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0142&prefill_Grant+Name=Ethereum%20Provider"
1717+++
1818
content/grants/eth-wallet.md → content/grants/2022/eth-wallet.mdrenamed+4−3
@@ -9,10 +9,11 @@ grant_category = [ "App Dev" ]
99[extra]
1010image = ""
1111description = "Build an Ethereum wallet and UI that you can run from your urbit ship and use to interact with the web3 ecosystem"
12−reward = "3 stars"
12+reward = "3 stars + $15k USD"
1313assignee = [""]
1414grant_id = "B0158"
1515completed = false
16+canceled = true
1617work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0158&prefill_Grant+Name=Urbit%20Native%20Ethereum%20Wallet"
1718+++
1819# Overview
@@ -33,11 +34,11 @@ Your task is to build an Ethereum wallet with similar behavior.
3334
3435An important component is to build a way for a ship to associate Ethereum public keys with their ID so it can share its wallet address to peers when asked for. A different scheme than the one used by the Bitcoin wallet (a new address per transaction) is probably needed. After that, a sleek interface is needed so users can send each other ETH at a minimum. Replicating the Bitcoin app’s provider node system is outside of the scope, but a good submission will allow the user to set their own RPC URL. You could also consider using Pocket Network.
3536
36−Because Ethereum is a complete computer, it won’t be feasible to keep shipping new UIs for all the things you can do on Ethereum. A great submission will let users use other Ethereum apps on the public internet with their Urbit-native wallet. One potential approach would be to embed a mini-browser and inject web3 into it the same way many mobile wallets do (Metamask iOS, Coinbase Wallet, etc.) Another would be to support WalletConnect.
37+Because Ethereum is a complete computer, it won’t be feasible to keep shipping new UIs for all the things you can do on Ethereum. A great submission will let users use other Ethereum apps on the public internet with their Urbit-native wallet. One potential approach would be to embed a mini-browser and inject web3 into it the same way many mobile wallets do (Metamask iOS, Coinbase Wallet, etc.) Another would be to support WalletConnect. Prior to assignment of this bounty, The Urbit Foundation and the contributor will meet and further expand on the scope and specific implementation of this bounty. Star compensation listed below is negotiable and may change depending on specific timing and features in the final scope.
3738
3839# Milestones & Compensation
3940
40−3 stars upon successful completion of the bounty.
41+3 stars upon successful completion of the bounty and a 15,000 USD bonus provided by [Reserve Protocol](https://reserve.org/).
4142
4243# Future Work
4344
content/grants/eyre-scry.md → content/grants/2022/eyre-scry.mdrenamed+2−2
@@ -11,9 +11,9 @@ image = ""
1111description = "Speed up Urbit http server by implementing a cache for requests"
1212reward = "5 stars"
1313assignee = ["~watter-parter"]
14−champion = "~tirrel"
14+champion = ["~tirrel"]
1515grant_id = "B0151"
16−completed = false
16+completed = true
1717canceled = false
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefillGrant+ID=B0151&prefillGrant+Name=Eyre%20Request%20Cache"
1919+++
content/grants/faux.md → content/grants/2022/faux.mdrenamed+3−2
@@ -12,11 +12,12 @@ image = ""
1212description = "Discord Bridge"
1313reward = "2 stars"
1414assignee = ["~midsum-salrux"]
15−champion = "~littel-wolfur"
15+champion = ["~littel-wolfur"]
1616grant_id = "P0145"
1717completed = true
1818canceled = false
19−link = ""
19+link = "~tomdys/the-faux-shore"
20+deliverable = "~midsum-salrux/faux"
2021
2122+++
2223
content/grants/filesharer.md → content/grants/2022/filesharer.mdrenamed+1
@@ -13,6 +13,7 @@ reward = "2 stars"
1313assignee = ["~tinden-pontev"]
1414grant_id = "P0102"
1515completed = false
16+canceled = true
1617link = ""
1718+++
1819
content/grants/full-stop.md → content/grants/2022/full-stop.mdrenamed+1−1
@@ -12,7 +12,7 @@ image = ""
1212description = "A Menstruation Tracker for Urbit"
1313reward = "5 stars"
1414assignee = ["Quartus"]
15−champion = "~tocrex-holpen"
15+champion = ["~tocrex-holpen"]
1616grant_id = "P0172"
1717completed = false
1818canceled = false
content/grants/2022/gather.mdnew file+87
@@ -0,0 +1,87 @@
1++++
2+
3+title = "%gather"
4+date = "2022-08-22"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "An Urbit native meetup tool for subculture gatherings"
13+reward = "4 stars"
14+assignee = ["~polrel-witter", "~pontus-fadpun"]
15+champion = ["~dolweb-donfun", "~dinleb-rambep"]
16+grant_id = "P0166"
17+completed = true
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Rationale
24+Meatspace interaction and synchronous, virtual discussions are core values many people on Urbit share. Currently, this need is facilitated through Meetup.com, which is a good intermediate solution, but for those who are in the slow (but increasingly faster) transition to using Urbit full-time, it's clear a native meet up tool is needed. Meetup falls into the typical web2 trap of siloing functions that should integrate seamlessly with other applications. Gather tackles this problem by leveraging Urbit ID for invite and RSVP permissining, Groups to section-off contexts and make it easier for sub-cultures on Urbit to spin up gatherings (something we don't see much of on Meetup right now), and native messaging to reduce context-switching. Future integrations and features could include: connection to the Bitcoin wallet for event payment walling, beaming event pages to the Clearweb to market events outside of Urbit, QR code entrance gating, event-specific attendee profiles, and other, unforseen possibilities as applications continue to percolate from the underground.
25+# User Stories
26+- User is planning a get-together and would like to send an invite out to their friends and members of a group they're a part of.
27+- User is in a foreign city and is curious to know who (ships they interact with regularly or members of a Group they're a part of) is in the area and open to meeting up.
28+- User has a core group of people they meet up with reguarly.
29+- User is curious to know if they have mutual, Urbit acquaintances in their area.
30+
31+# Milestones
32+## Milestone 1
33+Expected Completion: September 16, 2022
34+Compensation: 2 stars
35+
36+**Gathering**
37+- User can create, send, and receive gathering invites
38+- User can ban ships to stop sending and receiving invites to/from selected ships
39+- User can see a list of gatherings they're hosting, been invited to, and RSVP'd to in a dashboard
40+- User can delete gatherings from their dashboard that have passed
41+- Host can search for ships to which to send an invite
42+- Host can set a maximum number of RSVPs they will accept
43+- Host can cancel, finalize (meaning no more RSVPs will be accepted), or mark a gathering as completed
44+- Host can edit an invite that has already been sent out, and unfinalize it to make changes, if needed
45+- Host can see who accepted/declined their invite
46+- Host can restrict an invite to deliver only within a specific radius; meaning an invite will only appear in a ship's dashboard if their settings location is within the host's specified radius of the venue address
47+- Host can include a venue location in the invite
48+- Host can select one or more groups the user is a part of from a dropdown menu to invite members
49+- Invitee can distinguish Pending, Accepted, and Completed gatherings
50+- Invitee can unaccept an invite if they decide they can no longer attend
51+- Invitee can see invite and RSVP list
52+- Invitee can click a button on the invite to DM the host
53+- Invitee can accept or decline invites
54+- Invitee can see distance from their address to venue included in invite
55+- Invitee can restrict receiving invites to only those with venue addresses in their radius
56+- Connect to an open source map API so the app can retreive Longitude and Latitude and calculate the distance between two addresses (the address input is left up to the user for privacy control)
57+ - The map API query would work as follows:
58+ - Ship obtains latitude and longitude coordinates from a free, open source map API such as [Nominatim address search](https://nominatim.org/release-docs/develop/api/Search/)
59+ - Since Nominatim has a strict use policy, ship obtains the Lat and Lon once, each time the address field is updated, and stores it locally
60+ - Whenever a ship receives a location-based invite, their ship will auto-calculate the distance from their location (address in their settings) to the venue (received in the invite).
61+**Settings**
62+- User can toggle whether they want to receive invites from anyone or only within a set radius from their location to the gathering venue included in the invite
63+- User can set a radius within which they'll receive invites, if they're not receiving invites from anyone
64+- User can set "My Location": street, city, state, country, and zip to determine coordinates
65+- User can ban/unban ships
66+- User can see list of banned ships
67+- User can create a collection to store a subset of ships or groups to easily send future invites to select groups of ships
68+- User can toggle notification for new invites received
69+## Milestone 2
70+Expected Completion: November 30, 2022
71+Compensation: 2 stars
72+
73+**Gathering**
74+- Implement feedback from Hackathon/Assembly
75+- Host can establish an event page with a title, link, description, photo, address, venue name, date, and time
76+- Host can toggle a gathering's settings: public or private (if so, select who's invited; no link generated to restrict access to the event page), meatspace (if so, enter address) or virtual (if so, enter an access link), allow those who RSVP'd to see other ships who are attending, restrict message thread access to anyone (with an invite, if private) or only those who RSVP'd
77+- Attendee can see who else has RSVP'd (if enabled by host)
78+- Anyone with a ship can access a event page and RSVP, if they have the link and the gathering is public
79+- Attendee can set a reminder on gathering's they've RSVP'd to
80+- Native messaging on event page for pre, during, and post-event chat/networking
81+- Beam event page to clearweb
82+
83+# About Us
84+`~polrel-witter`
85+Over the past few years, I've worked in various operation roles at a film festival in Austin. My most relevant development experience includes designing and managing (though not coding) the festival's reader software rebuild, which is used to manage a team of 400 readers. Additionally, I served as the general IT support person for festival staff and have been around Urbit, managing a star and experimenting with optimal ways to host ships, for nearly a year now. I completed Hoon School Live back in May, have reviewed the Gall Guide and Walkthrough, and am participating in App School Live July through August.
86+`~pontus-fadpun`
87+In the last three year I've worked as a software engineer, developing frontend and backend solutions for various clients. My area of expertise was Hyperledger Fabric, where I've created software that generates smart contracts from bpmn/workflow diagrams. I've learned Hoon recently and worked on the eth-provider grant to enable urbit ships to customize their ethereum connection.
content/grants/general-web-permissions.md → content/grants/2022/general-web-permissions.mdrenamed+1−1
@@ -12,7 +12,7 @@ image = ""
1212description = "Enabling the ability to log in and view private or user-specific content"
1313reward = "3 stars"
1414assignee = ["~tirrel"]
15−champion = "~tacryt-socryp"
15+champion = ["~tacryt-socryp"]
1616grant_id = "P0142"
1717completed = false
1818canceled = false
content/grants/2022/gnosis-safe.mdnew file+56
@@ -0,0 +1,56 @@
1++++
2+
3+title = "Gnosis Safe on Urbit"
4+date = "2022-09-13"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "A self-hosted Gnosis Safe UI to protect against centralized prohibition"
13+reward = "2-3 stars"
14+assignee = ["~witfyl-ravped"]
15+champion = ["~dinleb-rambep"]
16+grant_id = "P0154"
17+completed = true
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0154&prefill_Grant+Name=Gnosis%20Safe"
20+
21++++
22+
23+# Gnosis Safe on Urbit
24+
25+## Overview
26+
27+An Urbit app that serves the Gnosis Safe UI, but with Urbit used for storing safe/wallet metadata and exchanging signatures.
28+
29+## Rationale
30+
31+There are two problems with Gnosis Safe:
32+
33+Gnosis Safe stores safe metadata (e.g. the name of a safe and address book) in local storage, since this information is sensitive. This presents a problem when firing up Safe on different browsers.
34+Gnosis Safe isn’t completely decentralized. It relies on a server maintained by the Safe team to relay signatures to other addresses on the multisig.
35+
36+Urbit can fix both of these. Since Urbit is a personal, private server, it can store Safe metadata without compromising it to a third party. Because Urbit is a P2P network, it’s trivial to exchange signatures directly with other members of the multisig, thereby transforming into a true decentralized application.
37+
38+## Scope / Implementation
39+
40+The frontend of this is fairly straightforward: you’ll deploy the safe-react application as an Urbit application. This guide that walks through full-stack Urbit development might be helpful for learning how to do this.
41+
42+To use Urbit as the networking layer for signatures it isn’t sufficient to know only the public addresses of the other members of a safe — you’ll need to know their Urbit ID as well. This means that the Urbit version of Safe needs to maintain a mapping of which Ethereum addresses belong to which Urbit IDs, and if no such mapping is known, fall back to using the centralized service maintained by Gnosis. In light of this, the Urbit version of Safe will need to satisfy the following user stories:
43+
44+I can associate one of my public addresses (probably via Metamask) with my Urbit ID when using Safe
45+I can enter an Urbit ID instead of an Ethereum address when creating a safe, and my Urbit will ask that Urbit ID for an ETH address to use in the multisig
46+When someone adds me to a safe multisig via the Urbit Safe app, I can choose an ETH address to be used on the Safe
47+I can associate an Urbit ID with an Ethereum address on an existing safe
48+
49+The networking component of this is fairly challenging and requires modifications to the Gnosis Safe UI to support Urbit ID. A second, independent portion of this challenge is to simply use Urbit for storing safe metadata: your wallets, the safes that your wallets are part of, and the address book(s) for each safe. For this you’d need to wire up a custom Gall agent to the safe frontend, using the agent for storage rather than the browser’s local storage.
50+
51+
52+## Timeline & Compensation
53+
54+Completed within 2 months of bounty assignment: 3 stars
55+
56+Completed withing 3 month of bounty assignment: 2 stars
content/grants/go-urbit.md → content/grants/2022/go-urbit.mdrenamed+2−2
@@ -12,9 +12,9 @@ image = ""
1212description = "Create a go-urbit library that contains the required functions for interfacing with Ames"
1313reward = "3 stars"
1414assignee = ["~litryl-tadmev"]
15−champion = "~wicdev-wisryt"
15+champion = ["~wicdev-wisryt"]
1616grant_id = "P0111"
17−completed = false
17+completed = true
1818canceled = false
1919link = ""
2020
content/grants/2022/gora-apprentice.mdnew file+61
@@ -0,0 +1,61 @@
1++++
2+title = "Gora: QR Edition"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Apprenticeship" ]
7+grant_category = [ "App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Extend Gora with QR-code generation and scanning for sending and recieving gorae"
12+reward = "1 star"
13+mentor = ["~rabsef-bicrym"]
14+assignee = ["~soctun-ridsyr"]
15+grant_id = "A0192"
16+completed = false
17+canceled = false
18+link = ""
19+deliverable = "~dalten/gora"
20+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0192&prefill_Grant+Name=Gora%20Apprenticeship"
21++++
22+
23+# Gora QR Edition - Updating Urbit's Premier Sticker Software
24+
25+The Gora QR Edition Apprenticeship is a userspace application apprenticeship focused on experiential learning in Earth-to-Mars communication (web interfacing) using [sail](https://developers.urbit.org/guides/additional/sail) (urbit's XML markdown language) and [rudder](https://github.com/Fang-/suite/blob/master/lib/rudder.hoon) (urbit's leading library for raw http-request handling), as well as airlock through the [urbit/http-api npm library](https://www.npmjs.com/package/@urbit/http-api).
26+
27+## Apprentice Expectations
28+Apprentice is familiar with Urbit and Gora. Apprentice has some familiarity with hoon, and ideally has a functional understanding of gall applications. Apprentices with an understanding of encoding data in QR codes preferred.
29+
30+## Team
31+
32+The Gora QR Edition apprentice will work with the Quartus Team and ~rabsef-bicrym (Gora's creator) directly. The apprentice and Quartus team will participate in an initial "kick-off" call to talk through the user stories and the expected implementation, and will proceed with weekly or biweekly (at the apprentice's preference or need) meetings with ~rabsef-bicrym thereafter.
33+
34+## Deliverable
35+
36+Production-ready pull request to the [gora repo](https://github.com/dalten-collective/gora) and [vue-front-end repo](https://github.com/dalten-collective/gora-frontend) updating both Vue and Sail versions to allow for QR-code generation and scanning to give/receive a gora, as described in the user stories, below.
37+
38+## User Stories
39+
40+* As a Gora Issuer (host)
41+ * For Gorae that I host, which are either stakable or standard, which (if standard) are not at or beyond their max # of hodlers, I am able to:
42+ * Generate a one-time-use QR code in the application which, when scanned by another gora user, would request the gora for which I have generated the code;
43+ * Receive pokes from external ships who have scanned that QR code, containing the information of the QR code;
44+ * Decipher and validate the incoming, poked, QR code information;
45+ * and, where appropriate, provide the gora to the ship requesting it via the QR code.
46+ * I am able to complete these behaviors in both the Vue and Sail implementations of Gora.
47+* As a Gora Requester (hodler)
48+ * In my gora application, I can request a gora by scanning a QR code (amongst other methods).
49+ * When I scan a QR code, I automatically poke the host ship of the gora who's code I have scanned, with the information of the QR code for validation.
50+ * I am able to complete these behaviors in both the Vue and Sail implementations of Gora.
51+
52+## Implementation Notes
53+
54+We are amenable to suggestions of strategies from our apprentice as to the nature of the implementation of this feature, particularly in the Front-End presentation. We have a suggestion for the general implementation details on the backend, but are nonetheless open to input:
55+
56+- Gora will get a state upgrade to include a `(jug gora-id nonce)`
57+- Each time a QR code is generated, a nonce will be randomly generated, checked to be unique against the `(set nonce)
58+
59+## Schedule & Compensation
60+
61+The Gora QR Edition apprenticeship should take no longer than 3 months, but is likely executable within a month. The apprentice will recieve 1 star upon successful completion of the apprenticeship.
content/grants/herd.md → content/grants/2022/herd.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "Herd - Dependency management for Citadel"
1212reward = "2 stars"
1313assignee = ["~midsum-salrux"]
1414grant_id = "P0170"
15−champion = "~littel-wolfur"
16−completed = false
15+champion = ["~littel-wolfur"]
16+completed = true
1717+++
1818
1919## Dependency Management for Citadel
content/grants/hoon-eval.md → content/grants/2022/hoon-eval.mdrenamed+3−3
@@ -1,5 +1,5 @@
11+++
2−title = "UF Apprenticeship Grant: Hoon Eval and REPL"
2+title = "Hoon Eval and REPL"
33date = "2022-05-04"
44
55[taxonomies]
@@ -10,9 +10,9 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Build an eval command and a stateless REPL mode in vere"
1212reward = "1 star"
13−mentor = "~master-morzod"
13+mentor = ["~master-morzod"]
1414assignee = ["~mopfel-winrux"]
15−completed = false
15+completed = true
1616canceled = false
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0161&prefill_Grant+Name=Hoon%20Eval%20and%20REPL"
1818+++
content/grants/hoon-markdown-library.md → content/grants/2022/hoon-markdown-library.mdrenamed+1−1
@@ -12,7 +12,7 @@ image = ""
1212description = "CommonMark-based Library for Hoon Markdown"
1313reward = "3 stars"
1414assignee = ["~tirrel"]
15−champion = "~tacryt-socryp"
15+champion = ["~tacryt-socryp"]
1616grant_id = "P0141"
1717completed = false
1818canceled = false
content/grants/2022/http-server-driver.mdnew file+98
@@ -0,0 +1,98 @@
1++++
2+title = "HTTP Server IO Driver"
3+date = "2022-11-28"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "Core Dev", "Runtime" ]
8+
9+[extra]
10+image =""
11+description = "Rewrite the HTTP server driver in Rust"
12+reward = "2 stars"
13+mentor = ["~fanfun-mocbud"]
14+assignee = ["~soctun-ridsyr"]
15+grant_id = "B0208"
16+completed = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0208&prefill_Grant+Name=HTTP%20Server%20IO%20Driver"
18++++
19+
20+# HTTP Server IO Driver
21+
22+## Context
23+
24+All IO drivers in the Urbit runtime currently run in the same process, which is
25+called the "urth" or "king" process. As part of an effort to both increase
26+security and scalability in the runtime, we are splitting each IO driver into
27+its own process, which is capable of communicating over local (i.e. pipes) or
28+remote (i.e. TCP sockets) communication channels.
29+
30+## Description
31+
32+In the [IO drivers repo](https://github.com/urbit/io_drivers), we use the
33+following abstract model of a driver:
34+
35+```
36+ INPUT SOURCE
37+ |
38+ | serialized request (length-encoded, jammed noun)
39+ |
40++---------------+
41+| INPUT TASK |
42++---------------+
43+ |
44+ | deserialized request (noun)
45+ |
46++---------------+
47+| HANDLING TASK |
48++---------------+
49+ |
50+ | deserialized response (noun)
51+ |
52++---------------+
53+| OUTPUT TASK |
54++---------------+
55+ |
56+ | serialized response (length-encoded, jammed noun)
57+ |
58+ OUTPUT SINK
59+```
60+
61+For this bounty, you must rewrite the HTTP server IO driver in
62+[`pkg/urbit/vere/io/http.c`](https://github.com/urbit/urbit/blob/master/pkg/urbit/vere/io/http.c)
63+in the [Urbit repo](https://github.com/urbit/urbit) to fit the driver model
64+described above in a new module [`src/http/server.rs`] in the
65+[IO drivers repo](https://github.com/urbit/io_drivers) with `stdin` and `stdout`
66+as the input source and output sink, respectively. The [HTTP client
67+driver](https://github.com/urbit/io_drivers/blob/master/src/http/client.rs) and
68+[file system driver](https://github.com/urbit/io_drivers/blob/master/src/fs.rs)
69+will serve as useful references.
70+
71+## Requirements
72+
73+- Knowledge of C and Rust.
74+- Experience with asynchronous, task-based programming.
75+- Familiarity with HTTP.
76+
77+## Resources
78+
79+- [Scalable
80+ IO](https://gist.github.com/mcevoypeter/a682dcd2d7c037c3b96de7268a7c2617)
81+- [Scaling Urbit's
82+ Runtime](https://gist.github.com/mcevoypeter/fe0270c9a4a72a9350c0f8944612bbf6)
83+
84+
85+## Deliverables
86+
87+- A thoroughly-documented HTTP server driver implementation in
88+ `src/http/server.rs` using `stdin` and `stdout` as the input source and output
89+ sink, respectively.
90+- A complete suite of unit tests structured as a `tests` module in
91+ `src/http/server.rs` that exercises the conversions from request nouns into
92+ driver-specific data structures and from driver-specific data structures into
93+ response nouns.
94+- A complete suite of integration tests in `tests/http_server_tests.rs` that run
95+ the spawn the HTTP server driver in a separate process and feed it requests as
96+ jammed nouns.
97+
98+Upon completion of all deliverables, you will receive two (2) stars.
content/grants/2022/keep.mdnew file+119
@@ -0,0 +1,119 @@
1++++
2+title = "Keep"
3+date = "2022-11-25"
4+
5+[taxonomies]
6+grant_type = [ "Proposal" ]
7+grant_category = [ "App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Keep: Arbitrary Agent State Restoration Agent + Wrapper"
12+reward = "6 star"
13+assignee = ["~wicrum-wicrun", "~sogrum-savluc"]
14+grant_id = "P0184"
15+champion = ["~rabsef-bicrym"]
16+completed = false
17++++
18+
19+## Purpose
20+Keep is Urbit’s first agent-state backup utility. Outside of the Flag Day script and other areologic phenomena, the breach has been an impenetrable barrier for Urbit pilots and their data. Agent state has been, as a result, considered ephemeral trans-breach.
21+
22+## Rationale - Keep
23+
24+Urbit will eventually be a perfect diamond protocol at the center of a computing dynasty. Until that time, however, people will experience issues with their urbits. Sometimes, people will breach.
25+
26+Unfortunately, to date, data continuity across breach has remained technically possible but practically impossible for users.
27+
28+![a recent question in urbit community about restoring groups across breaches](https://i.imgur.com/i1xMhH1.png)
29+
30+Enter Keep!
31+
32+### Keep
33+
34+As new and interesting software appears on network, users create an ever-expanding series of data-persistence expectations that Urbit must uphold, in order to gain their trust. Backing up agent state, therefore, needs to be a protocol that a user can **_arbitrarily apply to any agent they use, regardless of whether the original code afforded for such backups_**. Keep is that protocol. Utilizing a wrapper library, a user can add backup functionality to any agent. With the Keep agent, that library-wrapped agent's state can be held and hot-reloaded into an agent, should it be `nuke`d or otherwise lose its state.
35+
36+## User Stories
37+
38+* Import
39+ * [ ] Recover an Agent's `state` from a saved file - potentially transferrable between ships, or at least over rifts
40+* Export
41+ * [ ] Export an Agent's `state` to a file on underlying file system (e.g. Unix) - in the `/path/to/pier/.urb/put` directory
42+* Backup/Restore
43+ * [ ] Backup an Agent's `state` to a central agent, on the same ship or a moon of that ship, or many ships (distributed backup)
44+ * [ ] Once and/or on a recurring basis
45+ * [ ] Restore an Agent's `state` from a central agent, on the same ship or a moon of that ship
46+ * [ ] Request from a backup provider that, should I ever breach in the future, they will automatically send me a DM with instructions on how to restore the agents whose states they store for me
47+
48+### Export to Disk - Details
49+* [ ] User can see and select from available Agents that have been wrapped in Keep's library
50+* [ ] User can select an Agent to back up to disk
51+* [ ] User can click a button to begin the export
52+* [ ] User is told that the export will/has begun and is given an indicator as to where the file will go (this will always be the `/path/to/pier/.urb/put` directory, but we can also specify, a priori, the file name)
53+ * [ ] User's data is exported to an intelligibly named folder - if backups are recurring, some indication as to recency of the last backup is provided to the user.
54+
55+### Import from File - Details
56+* [ ] User can import a `jam` file of agent-state, if that jam file is saved on a mounted disk available to the ship in question.
57+* [ ] User can import a `jam` file of agent-state through a web-portal to avoid impacting clay and loom size more than necessary.
58+* [ ] User's `jam` file is applied as restoration-of-state to the agent to which it belongs.
59+* [ ] User is informed that the restoration is underway/has completed
60+
61+#### Network Restoration
62+* [ ] User is given instructions to wrap an agent
63+ * Currently, this requires a code modification, see implementation notes.
64+* [ ] User can see all "wrapped" agents
65+
66+##### Backup (User)
67+* [ ] User can choose to backup an Agent's `state`:
68+ * `once` - an instant time
69+ * `many` - on a recurring basis, every `x-time`
70+* [ ] User is informted that a backup is underway/has completed successfully
71+* [ ] Users can see any backups they have currently stored, per Agent
72+
73+##### Restore (User)
74+* [ ] Users can choose to restore an Agent's `state`
75+* [ ] User is informed that a restoration is underway/has completed successfully
76+
77+##### Backup (Server)
78+* [ ] Admin can manually (de/)whitelist ships that can send them backups
79+* [ ] Admin can automatically (de/)whitelist ships using `gora` or the bitcoin wallet
80+* [ ] Visualize which pairs of ships and their agents are stored in backup, accompanied by their size
81+
82+##### Restore (Server)
83+* [ ] Admin can toggle between automatically sending (or not sending) instructions via DM to any breached ships (by reading azimuth state) for which Admin holds backups
84+
85+## Milestones
86+
87+* **Milestone 1:**
88+ Delivery: November 20, 2022
89+
90+ Reward: 5 stars
91+
92+ Tasks:
93+
94+ * [ ] Keep is available for installation from a distribution moon.
95+ * [ ] Keep distributes with its wrapper library and full documentation on `%docs` that walks a user through adding the wrapper library to a software of the user's choice
96+ * [ ] Keep's "server" system is implemented to install locally, however instructions for prospective providers are included in the `%docs`.
97+
98+* **Milestone 2:**
99+ Delivery: Pending on Solid State Subscription
100+
101+ Reward: 1 Star
102+
103+ Tasks:
104+
105+ * [ ] Keep is implemented with Glue + Bank - Glue is an upcoming middleware aggregator system that will make appending and prepending agent transformers to an agent easier. Bank is a system whereby use of an agent can be payrolled. With these two component parts, Keep will be a viable service model for providers - they could charge to back up and maintain state for their clients and gate restoration functions behind the same paywall.
106+
107+* **Milestone 3**
108+
109+ Delivery: After Milestone 2, Community Outreach Required
110+
111+ No Additional Compensation
112+
113+ Tasks:
114+
115+ * [ ] Keep is in use by some hosting provider to provide backup and restoration utilities to their Urbit clients.
116+ * [ ] Provider speaks to this fact.
117+ * [ ] Agents are being shipped pre-wrapped in Keep for convenience.
118+ * [ ] Developers speak to this fact.
119+ **No Additonal Compensation**
content/grants/2022/knox.mdnew file+81
@@ -0,0 +1,81 @@
1++++
2+
3+title = "Knox"
4+date = "2022-11-01"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "A vault for web2 passwords with a browser extension and easy to use client interface, bringing the features you would expect from a first class password manager to Urbit"
13+reward = "4 stars"
14+assignee = ["~wordel-sitnec", "~radbus-tactyl"]
15+champion = ["~haddef-sigwen"]
16+grant_id = "P0185"
17+completed = false
18+canceled = false
19+link = "~wordel-sitnec/knox"
20+
21++++
22+
23+# The Problem
24+
25+Everyone here basically agrees - the internet is broken, the megacorps are predators, Urbit solves this, etc. etc. What Urbit doesn't solve in the immediate term is the entrenchment of web2 services from which many of us are not yet able (whether ready or not) to eject. Some solutions tangential to this space have already been developed, most notably dcSpark's Urbit Visor. Waiting for the services we still rely on to adopt log in with Urbit may be a pipe dream, and their eventual extinction is not imminent enough. Many of us still need an email address and a password to log in to pay our utilities, and we'll speak for many more in saying we wish Urbit could handle this for us.
26+
27+Enter Knox.
28+
29+# The Purpose
30+
31+Knox is a vault for your web2 passwords. With it running on one's ship, a user can generate strong passwords, easily cycle passwords, autofill login forms with the correct credentials, trivially grab an arbitrary password with a command, and manage all of this with an easy-to-use client interface. It does everything you expect a first class password manager (BitWarden, LastPass) to do, but it lives on your urbit.
32+
33+As of this writing, the basic architecture for such an app is assumed to be 1) a Gall agent, 2) a browser interface, and 3) a chromium extension. We intend to leverage the urbit visor/command launcher for some maximally convenient features, such as quick-grabbing an arbitrary password with a well-formed scry or quickly generating a password. Much of this functionality will be extended into the Knox extension as well.
34+
35+Technical details/best practices for many aspects of this project will require some research. Most notable examples include best practice for storing passwords and for transferring passwords over http/https.
36+
37+# Components
38+
39+The entirety of the app includes at least the three discreet components named above, namely 1) the Gall agent, 2) the web client, and 3) the chromium extension.
40+
41+1. Gall Agent
42+The Gall agent's primary role is storing passwords and assisting with password generation. Due to the current state of app permissions and security concerns, the passwords will be stored encrypted at rest, requiring a secret supplied client side to be legible. This client-side password could be whatever kind of password the user would like, but the user would be prompted somewhere in the UI that says something to the effect of "strong passwords are highly recommended". The set of passwords will be stored in Clay so the info isn't lost forever if the agent crashes. As far as password generation, the Gall agent will provide entropy for the client to use for randomness.
43+
44+2. Web Client
45+The web client will probably end up being the least important, or at least the least used, part of the app, but given the current skills of the team, it will be tackled simultaneously with the Gall agent and before the extension. The web client will serve a sort of dual purpose, both helping with beginning development of the Gall agent and as proof of concept for accessing/using the data stored. As mentioned above, the secret supplied client-side is how the data stored in Gall becomes legible. In addition to the features already described, there will of course be use cases where a web client may be preferable to a slimmer extension UX, like finding a particular password, checking for duplicates, easier account management, etc. As of this writing, the web client stack is React and Tailwind.
46+
47+3. Chromium Extension
48+The extension is what ties everything together, elevating the UX to being on par with other password managers and making password management on Urbit a seamless and secure experience. Research into this part of the project is underway, but leveraging dcSpark's visor and using their developer guides for building extensions that interact with visor would afford many shortcuts.
49+
50+# Milestones and Compensation
51+## Milestone 1 - MVP and %docs - January 2023
52+**Payment: 2 stars**
53+- Through the web client, user can -
54+ - view all saved entries (website, username, password)
55+ - generate a new password
56+ - save a new entry
57+ - edit an entry (change username/password)
58+ - delete an entry
59+- Full documentation for features so far in %docs
60+- MVP implementation requires a relatively slim agent set up, and more sophisticated password generation/functionality could come in future releases
61+
62+## Milestone 2 - Chromium Extension and Backups - March 2023
63+**Payment: 2 stars**
64+- Stand alone extension - brings all the functionality of client to extension
65+ - Primary extension feature is auto-populating username/password fields if on known website
66+- Backup management via %peat (or other compatible app) integration. This could include storing/backing up other sensitive/valuable agent state, such as a user's gorae.
67+- Export - easily get some report of all existing/selected accounts/passwords. Good for having a physical backup (think crypto wallet seed phrases), preparation for risky software/hardware tinkering, etc
68+
69+## Future Considerations*
70+- After delivering on the first two milestones, future work could be done on expanding the scope of Knox into more sophisticated use cases, such as crypto wallet seed phrase storage, storage of offline passwords/pins, etc. Some of this work could be implemented during milestone 2 if time allows.
71+- Expansion of app scope could also warrant a more sophisticated UI, with folder-like sorting options
72+- Due to less certain status about dcSpark's continued development in Urbit space, featires that requires the visor extension/command launcher have been moved from specific milestone objectives into this separate future considerations category. The visor extension affords many useful features, but development based explicitly on visor integration is at the mercy of its long term stability. Knox features based on visor integration include:
73+- Through the command launcher, user can -
74+ - generate a new password
75+ - get the password for an arbitraty website with a poke
76+
77+## About Us
78+
79+- ~radbus-tactyl - Currently I am a student studying Maths and Economics, I discovered Urbit early last year and have been learning more about the network and it's components. I was one of the HSL finishers with Hoon being my first programming language and am currently working through ASL. I am eager to contribute to the Urbit ecosystem in any way that I can and think developing an app that provides a useful and convenient function for Urbit users is the best way to get started while creating something valuable.
80+
81+- ~wordel-sitnec - My day job is a software engineer for a big company you’ve heard of. I am relatively new to development in general, with most of my experience being in the frontend React app realm. I discovered Urbit coming up on two years ago, and have since been working on developing the skills to exit to Mars completely, building the software necessary if someone else hasn’t already. This would be my first serious foray into hoon development, having gone though Hoon School and App School asynchronously and diving into many other dev tools as they have become available, including dcSpark’s authenticate with urbit ID and their urbit visor/command launcher. I am eager to contribute to the Urbit ecosystem, and think development of an app I myself want to use (that others will hopefully also find useful) is the perfect way to up my chops while providing value for the community.
content/grants/lexicon.md → content/grants/2022/lexicon.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "A simple dictionary app with ability to add custom definitions fo
1212reward = "1 star ($3k bonus if done by Assembly)"
1313assignee = ["~bitful-pannul"]
1414grant_id = "B0162"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0162&prefill_Grant+Name=Lexicon"
1818+++
1919
content/grants/2022/lightning-development.mdnew file+201
@@ -0,0 +1,201 @@
1++++
2+title = "Lightning Development"
3+date = "2022-10-20"
4+
5+[taxonomies]
6+grant_type = [ "Proposal" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Extending Bitcoin on Urbit via lightning submarine swaps and onion routing"
12+reward = "6 stars"
13+assignee = ["~tondes-sitrym"]
14+grant_id = "P0183"
15+champion = ["~hastuc-dibtux"]
16+completed = false
17+link = "~pindet-timmut/urbitcoiners"
18+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
19++++
20+
21+# Introduction
22+
23+The upcoming release of Volt, the Urbit/Lightning Network integration initiated by a 2021 UF grant, will furnish Urbit users and potential Urbit-native merchants with a high-speed, low-fee Bitcoin payment rail that facilitates transactions both between ships and with parties outside the Urbit network. Many integrations of this functionality into the existing Urbit app ecosystem are relatively simple and can be accomplished in the short term, including Substack-style paid subscription channels and groups, friend-to-friend payments via Pals, and tipjars for app developers and users. Simultaneously, additional work is needed to make Volt fully practical for merchant use and the bootstrapping of a circular Bitcoin economy within Urbit, starting at the feature level with two issues brought up in the original Volt grant as areas for future work: submarine swaps and onion routing.
24+
25+# Background
26+
27+*Inbound liquidity*
28+
29+In a Lightning payment channel, transfers are facilitated by updating a balance of account between the two participants, and the amount that can be transferred across it in a given direction is limited by the portion of the channel’s funds currently owned by the originating party. In general, an end user needs to fund the creation of their own channel, which therefore starts out with a balance entirely owned by them. This balance is “outbound liquidity” that can be used to make payments - shifting part of it to the counterparty’s side of the channel - but not to get paid, which requires some amount of “inbound” liquidity on the counterparty side. Without any additional tools, a new Lightning user whose primary use-case is to accept payments - a merchant - can only do so either by first making payments to others that build up inbound liquidity, or with a custodial and manual setup where they send their on-chain funds to the counterparty and trust them to open the channel. Neither of these is a viable onboarding process for businesses, who just want to start cheaply accepting Bitcoin for goods and services on demand; fortunately there is an existing solution.
30+
31+*Submarine swaps*
32+
33+Submarine swaps combine on-chain and Lightning transactions such that neither can be completed without enabling the completion of the other - an “atomic” swap - allowing balances in Lightning channels to be trustlessly exchanged for an on-chain payment. With a submarine swap, 80-90% of the funds in a new channel (depending on its configuration) can be paid to the other side and converted into inbound liquidity, in exchange for an on-chain repayment that can only be redeemed using the cryptographic proof-of-payment (hash preimage) that the swap counterparty reveals in order to complete the associated Lightning transfer.
34+
35+Subsequently, this will also allow merchants to move accumulated income out of their Lightning channels and into long-term on-chain storage, replenishing their inbound liquidity in the process. The pattern of business operation is equivalent to emptying a stuffed cash drawer (Lightning channel) and depositing the cash at the bank (on chain) at the end of the day. This is desirable independent of inbound liquidity needs because a wallet participating in a Lightning channel must be “hot”, ie. remain online, in order to sign balance updates without manual intervention - an intrinsically less secure disposition of funds than eg. a hardware wallet.
36+
37+Swap providers are paid a fee, and there are existing marketplaces for the service, such as Loop operated by Lightning Labs, that Urbit merchants can use as a fallback. However, since the Loop marketplace is centralized (though noncustodial), and in order to keep fee income and market development inside Urbit, it will be important to enable ships to directly negotiate channel rebalancing peer-to-peer. This can be accomplished by implementing the PeerSwap messaging protocol currently in beta on Lightning mainnet.
38+
39+*Onion routing*
40+
41+While a single channel is useful for parties who make frequent transactions with each other, the true utility of Lightning lies in multi-hop transactions, which update multiple channels in a route to send a payment between any two nodes in the network. For privacy, the Bitcoin contracts that comprise this route are sent in the form of an onion, which encrypts each contract with the public key of the node meant to initiate it, who then passes the remainder of the onion to the specified counterparty. This prevents any individual node in the path from knowing the hops preceding and following them, ie. being able to identify the sender and destination.
42+
43+The current Volt architecture does not implement the construction of payment routes with multiple intra-Urbit hops, and instead has ‘interior’ ships without a colocal Lightning node forward all multi-hop transactions through channels with a 'provider' running lnd, who is thus easily able to inspect the user’s transaction history. This simplification made sense for a number of reasons, not least that to make outbound payments along a multi-Urbit path will require lnd, the most popular Lightning node implementation, to add two new RPC methods to facilitate passing onions and proof-of-payment secrets in and out of its context. However as Urbit adoption continues to accelerate, it is unrealistic - and undesirable for Urbit’s robustness in an increasingly adversarial environment - to expect that Bitcoin users will be widely willing to accept this sacrifice of privacy to a node provider as the condition of operating on Urbit.
44+
45+# User Stories 1: Submarine Swaps
46+
47+As a merchant/payee, I can…
48+- Ready my channel to receive payments immediately after opening it
49+- Optionally use the funds I get back on-chain to open a second, outgoing channel
50+- Move funds I’ve received on Lightning to an on-chain address of my choice for long-term storage
51+- Replenish my channel’s capacity to receive payments when previous transaction flow has depleted it
52+
53+As a swap purchaser, I can…
54+- Receive information about available swap providers on the Urbit network
55+- Poll the Loop marketplace for swap providers if none are available inside Urbit
56+- Communicate with a swap provider to accept their offer and receive an invoice
57+- Monitor the Bitcoin chain for a correct conditional payment
58+- Pay the provider’s invoice once the on-chain payment is confirmed
59+- Redeem the on-chain payment once I receive proof-of-payment over Lightning
60+
61+As a swap provider, I can…
62+- Signal the amount I’m able to swap and the fees I charge
63+- Send a Lightning invoice to an interested party
64+- Broadcast an on-chain conditional payment
65+
66+# User Stories 2: App Integrations
67+
68+As a group host and volt user, I can…
69+- Create channels in my groups that restrict access to subscribers that make one-time or recurring Bitcoin payments
70+- Create groups that restrict access to ships that make one-time or recurring Bitcoin payments
71+- Add a tipjar channel to my group that allows subscribers to send a Bitcoin payment to my volt wallet
72+
73+As a group subscriber and volt user, I can…
74+- Make a one-time payment or authorize a recurring payment to subscribe to a group or channel
75+- See and subscribe or navigate to paid-only channels in groups I’m subscribed to, from my volt wallet
76+- Manage my subscriptions, seeing how much I’ve paid to a service and removing authorization for future payments if I wish to cancel
77+
78+As a pals and volt user, I can…
79+- See and make payments to pals that also use volt
80+- Receive gossip via my pals about volt-provider ships that operate a Lightning node, and attempt to open channels and perform submarine swaps with them
81+
82+As an app developer and volt user, I can…
83+- Add a tipjar to my app that allows users to send a Bitcoin payment to my volt wallet
84+
85+# User Stories 3: Onion Routing
86+
87+As a volt user, I can…
88+- Receive and decrypt an onion sent by another ship
89+- Forward the encrypted remainder of the onion to the counterparty of the included contract
90+- Receive a proof-of-payment from another ship and use it to settle an outstanding contract on a different channel
91+
92+As an interior volt user (who does not operate lnd), I can…
93+- Open/close channels with multiple ships
94+- Receive information from channel counterparties and pals about intra-Urbit channels available to forward payments through
95+- Send outgoing payments on a route that transits channels between multiple ships before entering the exterior Lightning network
96+- Create an invoice for a payer that includes route hints specifying a payment route to me that involves multiple hops between ships
97+
98+As a volt provider (who does operate lnd), I can…
99+- Receive an onion from another ship and inject it into lnd for propagation to the exterior Lightning network
100+- Intercept an onion received by lnd and forward it to the counterparty ship of the associated contract
101+- Receive a payment secret from lnd and use it to resolve an outstanding contract with another ship
102+
103+# Milestones & Compensation
104+
105+**Milestone 0: Volt Cleanup, Urbitcoin Landing Page**
106+
107+Expected time to completion: 2-4 weeks
108+Payment: 1 star
109+
110+- Modify %volt to use the %volt-wallet external signing agent in place of current internal signing behavior
111+- Design and manage urbit.org/bitcoin landing page
112+
113+**Milestone 1: Submarine Swaps**
114+
115+Expected time to completion: 1 month
116+Payment: 2 stars
117+
118+- Offer/accept a swap with another ship at a set feerate
119+- Send/receive a Lightning invoice for an accepted swap, broadcast/monitor the chain for the associated conditional payment
120+- Pay an invoice and use the proof-of-payment to redeem on-chain funds
121+- Use the Loop API to source and fulfill swaps with non-Urbit swap providers
122+
123+**Milestone 2: PeerSwap and UI Release**
124+
125+Expected time to completion: 6 weeks
126+Payment: 3 stars
127+
128+- Use the %rumours gossip protocol to send updates about ship availability for swaps between %volt peers
129+- Implement a version of the PeerSwap messaging protocol to automatically coordinate on-chain and off-chain payments
130+- Publish full-featured app with UI that allows users to initiate swaps, configure accepted swap parameters, and review/accept manual swap offers
131+
132+
133+---
134+
135+In response to feedback from the Foundation, I'm restricting the scope of the current proposal to the first phase of work, on submarine swaps, and an added 'phase 0' milestone finishing leftover work integrating the %volt agents and setting up bitcoin.urbit.org. This is noted in **Milestones** below.
136+
137+---
138+*Subsequent Proposals / Future Work*
139+
140+**Groups**
141+
142+Expected time to completion: 1 month
143+Payment: 2 stars
144+
145+Integration with Groups 2 including:
146+- Admins of groups can gate membership of their group by a one-time or recurring payment
147+- Admins of groups can gate access to channels by a one-time or recurring payment
148+- Subscription management
149+- Automatic payment flows for joining groups
150+
151+**Pals and Tipjars**
152+
153+Expected time to completion: 1 month
154+Payment: 2 stars
155+
156+- Use %rumours gossip protocol to advertise ships running %volt-provider and lnd to %pals and %volt peers
157+- Send invoices and payments to pals
158+- Library for app developers to plug Lightning tipping into their apps, handling invoice generation and allowing them to set default amounts
159+- Modular tipjar channel type for Groups 2
160+
161+**Lnd PR and Incoming Routing**
162+
163+Expected time to completion: 2 months
164+Payment: 4 stars
165+
166+Deliverables
167+- Submit a PR to lnd for RPC methods enabling onion injection and hash preimage interception, for outbound payment routes
168+- Release a draft UI using %volt to invoice and confirm receipt of multi-Urbit-hop incoming payments
169+
170+Requirements
171+- Library for serializing and deserializing Lightning onions
172+- Gossip protocol for route information
173+- Add support to %volt for opening channels with multiple counterparty ships
174+- Use logged routing gossip to select intra-Urbit final hops and add them to an invoice as route hints
175+- Parse onion data injected into %volt-provider from lnd
176+- Add %pokes for forwarding onion data
177+- Use de/serialization library to extract the local HTLC from a decrypted onion, initiate %volt’s BOLT 3 workflow
178+
179+**Outgoing Routing**
180+
181+Expected time to completion: 1 month
182+Payment: 2 stars
183+
184+- Use logged routing gossip to construct outgoing routes and encrypt the resulting HTLC chain in an onion
185+- Inject onions from %volt-provider into lnd
186+- Receive hash preimages from lnd and use them to settle HTLCs in interior channels
187+- Add %pokes for forwarding preimages after settlement
188+- Final deliverable: Release a full-featured (inbound and outbound) multi-hop %volt extension and UI updates
189+
190+# Additional Future Work
191+
192+This grant is intended to be the beginning of a long-term project realizing the potential of Urbit/Lightning integration. Whether or how much of this will involve seeking further grant funding is hard to say in advance, but I think it’s worth giving a brief overview of what I have in mind.
193+
194+- The single biggest win in this space will be implementation of the recently announced Taro protocol, which allows arbitrary assets like NFTs and stablecoins to be represented on the Bitcoin chain in a private and lightweight fashion and transferred via Lightning. Moving quickly on this (immediately after completion of the current proposal) would make Urbit the first fullstack environment for using the biggest expansion of Bitcoin’s capabilities since Lightning. My focus will be on using Bitcoin NFTs as granular, transferable rights and roles for ships participating in different communities and app ecosystems, but as the DeFi community’s interest in Urbit grows I expect supporting alt- and stablecoin use-cases to be highly significant as well.
195+- The app integrations covered in this proposal are only the basics even of what’s currently possible. Creating a library that can be used by any app, eg. Pokur to support betting with Lightning, is a priority since by 6 months from now I expect the Urbit app ecosystem to have multiplied several times in size. The reason for doing bespoke integrations with Groups and Pals first is simply to start generating common use and awareness on the network rather than allow Bitcoin integration to continue lying largely fallow while waiting for development.
196+- My favorite species of these use-cases is atomic streaming payments: continuous resources like audio/video or services that are incrementally accessed using cryptographic credentials received via proof of ongoing payments. The first application of this will be pay-to-play WebRTC streams, eg. through integration with Assembly Capital's %radio, but data, compute, and storage, eg. for hosting or AI applications, are all next steps.
197+- Improvements to the bitcoin wallet to make it more resemble a traditional light client in security model and UX are a necessity. I expect a large degree of overlap and concentration for the first year or more between providers of Bitcoin full nodes and Lightning nodes on the network, which would put the funds of many non-node-operating Lightning users of the current wallet in a highly precarious situation.
198+
199+# About Me
200+
201+My previous background is in Solidity and Javascript development for DeFi protocols on Ethereum, always with the ambition of eventually leaving the Ethereum space and working on Bitcoin, which I became enthusiastic about through a philosophy seminar in 2015. I’ve learned Hoon and Gall app development off and on over the past two years, and recently completed a demo app implementing a basic gossip protocol. I've also operated my own cloud-hosted Lightning and Bitcoin nodes and intend to serve as a provider for these services on Urbit.
content/grants/loom-pointer-compression.md → content/grants/2022/loom-pointer-compression.mdrenamed+2−2
@@ -10,10 +10,10 @@ grant_category = [ "Core Dev", "Runtime" ]
1010image = ""
1111description = "Expand the maximum addressable loom size"
1212reward = "1 star"
13−mentor = "~fanfun-mocbud"
13+mentor = ["~fanfun-mocbud"]
1414assignee = ["~barter-simsum"]
1515grant_id = "A0173"
16−completed = false
16+completed = true
1717canceled = false
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0173&prefill_Grant+Name=Loom%20Pointer%20Compression"
1919+++
content/grants/meld-memory.md → content/grants/2022/meld-memory.mdrenamed+2−2
@@ -1,5 +1,5 @@
11+++
2−title = "UF Apprenticeship Grant: Reduce memory usage of |meld"
2+title = "Reduce memory usage of |meld"
33date = "2022-05-04"
44
55[taxonomies]
@@ -10,7 +10,7 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Reduce memory usage of |meld"
1212reward = "1 star"
13−mentor = "~master-morzod"
13+mentor = ["~master-morzod"]
1414assignee = ["~winter-paches"]
1515completed = false
1616canceled = false
content/grants/membrane.md → content/grants/2022/membrane.mdrenamed+4−3
@@ -9,11 +9,12 @@ image = ""
99description = "Martian native spreadsheets"
1010reward = "5 stars"
1111assignee = ["~tiller-tolbus"]
12−champion = "~sarlev-sarsen"
12+champion = ["~sarlev-sarsen"]
1313grant_id = "P0138"
1414completed = false
1515canceled = false
16−link = ""
16+link = "~tiller-tolbus/membrane"
17+deliverable = "~tiller-tolbus/membrane"
1718+++
1819
1920# Intro
@@ -53,7 +54,7 @@ Payment: 2 stars
5354
5455## Milestone 2
5556
56−Expected Completion: November 2022
57+Expected Completion: May 2023
5758
5859Payment: 3 stars
5960
content/grants/2022/middleware-apprentice.mdnew file+55
@@ -0,0 +1,55 @@
1++++
2+title = "Middleware Tools"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Apprenticeship" ]
7+grant_category = [ "Other"]
8+
9+[extra]
10+image = ""
11+description = "Build middleware tooling for interfacing between arbitrary agents"
12+reward = "1 star"
13+mentor = ["~wicrum-wicrun"]
14+assignee = ["~litlep-nibbyt"]
15+grant_id = "A0193"
16+completed = true
17+canceled = false
18+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0193&prefill_Grant+Name=Middleware%20Apprenticeship"
19++++
20+
21+## Bolt Middleware Apprenticeship
22+At Assembly 2022, Quartus CTO ~wicrum-wicrun gave a presentation on agent transformers, and how this is currently the necessary pattern to implement middleware in Gall. Now, we are pleased to announce an opportunity to work with ~wicrum-wicrun as an apprentice in developing a whitelisting middleware. While it is possible, today, on the network to `%ruin` ships you don't want to talk to, or to hard-code exceptions to pokes based on ship IDs, there is no good no-code, non-permanent way whereby one ship can authorize or disallow pokes from any arbitrary group of other ships.
23+
24+Enter the Whitelist Middleware (Bolt). The Whitelist Middleware Apprenticeship will provide Agent Transformer (an `$-(agent:gall agent:gall)` library) experience in a real world usecase. The whitelist middleware will add to the growing list of Agent Transforms in use on the network (following on Keep and Bank which Quartus described and released in connection to Assembly 2022). Experience with Middleware like Bank or Bolt informs apprentices about the nature of Gall agents and the limitations of middleware software in its current configuration. The Apprentice will be asked to consider many elements of the current Gall configuration. Additionally, the apprentice will be required to investigate points where an agent transformer like Bolt might interfere with the underlying agent (subscriptions, pokes, arvo gifts) and make affordances to ensure that service is only interrupted based on the blacklist/whitelist.
25+
26+## Expectations of the Mentor
27+
28+### Work Style
29+Quartus is committed to providing the apprentice with weekly 1 hour meetings to review code and discuss next steps. Depending on the apprentice's timezone, Quartus can provide additional support during apprentice's working hours via DM on Urbit (or videoconference if appropriate).
30+
31+Prior to submission of the work for payment, Quartus will do a full code review for style and completeness, with the apprentice. Submitted code must adhere to the [style guide](https://developers.urbit.org/reference/hoon/style) ***except*** where code-elegance demonstrably surpasses form.
32+
33+### Learning Outcomes
34+Experience with Middleware like Keep or Bolt informs apprentices about the nature of Gall agents and the limitations of middleware software in its current configuration. The Apprentice will be asked to consider many elements of the current Gall configuration, to understand points where an agent transformer like Bolt might interfere with the underlying agent (subscriptions, pokes, arvo gifts) and make affordances to ensure that service is only interrupted based on the blacklist/whitelist.
35+
36+After completion the apprentice will be well-equipped to create their own middleware according to patterns established by Quartus.
37+
38+## Expectations of the Grantee
39+It is recommended that any candidates have either created at least one previous Gall agent or significant previous experience with programming.
40+
41+### Time Commitment
42+Quartus expects Bolt to take roughly 20 hours. At a minimum of 10 hours per week, Quartus expects the engagement to take roughly 2 full weeks of work.
43+
44+## User Stories:
45+1. As a user, I can transform my agent with a whitelisting library (Bolt)
46+2. When my agent is bolted, I can turn on and off Bolt's functionality
47+3. When my agent is bolted, I can poke it to instruct it as to whether I want to establish a blacklist or a whitelist (only stop, only allow, respectively)
48+4. When my agent is bolted, and Bolt is turned on, I can poke it with a set of ships which I wish to ban or admit.
49+5. When my agent has been instructed, it will either ban (blacklist) or allow-only (whitelist) the set of ships which I have suggested.
50+6. When my agent is bolted and instructed, I can change its instruction by removing or adding ships to the set currently being blocked/admitted.
51+7. When I turn off Bolt, I am still able to use the underlying agent.
52+8. If I receive an update to my underlying agent, likely resulting in the removal of my transformer (unless distributed by the manufacturer complete with the transformer), I am notified to retransform my agent.
53+
54+## Milestones & Compensation
55+The expected duration of the apprenticeship is one month. Upon successful completion of the apprenticeship, grantee will be awarded 1 Star.
content/grants/minesweeper.md → content/grants/2022/minesweeper.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "A redesigned version of minesweeper where all of the game logic i
1212reward = "1 star ($2k if done by Assembly)"
1313assignee = ["~hanfel-dovned"]
1414grant_id = "B0163"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0163&prefill_Grant+Name=Minesweeper"
1818+++
1919
content/grants/native-planet-2.md → content/grants/2022/native-planet-2.mdrenamed+2−2
@@ -11,9 +11,9 @@ image = ""
1111description = "Native Planet - A domestic hosting solution for Urbit"
1212reward = "6 stars"
1313assignee = ["~dalhec-banler"]
14−champion = "~poldec-tonteg"
14+champion = ["~poldec-tonteg"]
1515grant_id = "P0126"
16−completed = false
16+completed = true
1717canceled = false
1818+++
1919
content/grants/nested-goals.md → content/grants/2022/nested-goals.mdrenamed+45−11
@@ -7,13 +7,14 @@ grant_category = ["App Dev"]
77[extra]
88image = ""
99description = "Urbit application for invidividual and social management of high-level goals and their tasks"
10−reward = "3 stars"
11−champion = "~tacryt-socryp"
10+reward = "6 stars"
11+champion = ["~tacryt-socryp"]
1212assignee = ["~niblyx-malnus"]
1313grant_id = "P0143"
14−completed = false
14+completed = true
1515canceled = false
16−link = ""
16+link = "~dister-dozzod-niblyx-malnus/proposal-nested-goals"
17+deliverable = "~niblyx-malnus/gol-cli"
1718+++
1819
1920# Project Description
@@ -116,13 +117,46 @@ A fully functional social task manager CLI.
116117- Can delegate goals (and their subgoals) to other ships. Delegates will have permissions to add subgoals, edit deadlines, edit goal descriptions, create precedence relationships, and to further delegate subgoals with respect to the goal they have been delegated.
117118- Can transfer ownership of goals (and all their subgoals) between ships.
118119
119−### Milestone 3
120+## Milestone 3
121+Expected Completion: September 21st
122+Payment: 2 stars (1 for back-end API (~niblyx-malnus), 1 for front-end (~randes-losrep))
120123
121−Expected Completion: September 16th
124+A basic but compelling front-end prototype to showcase at Assembly 2022. A working interactive browser analog of the current CLI. Focused on getting the backend hooked up to the frontend and providing a minimum viable product. The main view will be the "hierarchical/nested" view in which projects and goals can be viewed and explored.
122125
123−Payment: 1 star
126+### User Stories
127+I can create projects and update/delete them
128+I can create goals and update/delete them
129+I can nest goals beneath one another
130+I can mark goals as complete or incomplete
131+I can collapse/uncollapse any hierarchy of goals or projects
132+I can filter out completed/uncompleted goals
133+
134+## Milestone 4
135+Expected Completion: October 28th, 2022
136+Payment: 2 stars (1 for back-end (~niblyx-malnus), 1 for front-end (~randes-losrep))
137+
138+Based on the relative success of the Goals prototype, we believe a self-sustaining version of the app is possible by leaning into what we already have that works and focusing on making it rock solid. To this end we want to focus on the following:
139+
140+Implement all existing CLI functionality in the front-end:
141+ (1) moving subgoals under different goals, (2) virtual children, (3) precedence, (4) priority, (5) marking actionable, (6) specifying kickoff/deadline times, (7) delegating goals and subgoals to other ships, and (8) harvesting
142+Integration with Groups so that pools can be created which are associated with existing groups
143+
144+In addition we need to make the backend robust with the following:
145+- Marks/Subscription versioning to gracefully manage API upgrades
146+- Subscription channel update log in case front-end is kicked and must resubscribe
147+- Poke relays and undecided/approved/rejected status for pokes to other ships for front-end display
148+- Documentation
124149
125−- A basic Sail frontend.
126−- Ability to reference an arbitrary graph-store node or set of nodes to capture context which triggered the creation of the goal.
127−- Ability to have threaded comments on goals.
128−- Other such integrations with Groups which will probably become more obvious to me as I become more familiar with this part of user space.
150+### User Stories
151+- I can set a deadline or a kickoff date for a goal and edit or remove it
152+- I can mark/unmark goals as actionable
153+- I can filter to see only actionable goals
154+- I can precede a goal before another, having the option to remove the relation
155+- I can prioritize a goal ahead of another, having the option to remove the relation
156+I can "harvest" from a goal, listing the preceding goals which can be tackled immediately
157+I can archive goals and have an option to view them later
158+I can restore or permanently delete archived goals (as an admin)
159+I can read about nested-goals in a documentation page
160+I can select a group from the Groups app and invite everyone from that group to a pool
161+I can move a goal to be nested elsewhere in the tree
162+I can make a copy of any pool
content/grants/notifications-protocol.md → content/grants/2022/notifications-protocol.mdrenamed+3−3
@@ -1,5 +1,5 @@
11+++
2−title = "UF Apprenticeship Grant: Notifications Protocol"
2+title = "Notifications Protocol"
33date = "2022-05-04"
44
55[taxonomies]
@@ -10,11 +10,11 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Build a new network protocol to Urbit to handle notifying subscribers when a new datum is published"
1212reward = "1 star"
13−mentor = "~rovnys-ricfer"
13+mentor = ["~rovnys-ricfer"]
1414assignee = ["~novned-tidsyl", "~boldur-dashes"]
1515grant_id = "A0136"
1616completed = false
17−canceled = false
17+canceled = true
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0163&prefill_Grant+Name=Notifications%20Protocol"
1919
2020+++
content/grants/olif.md → content/grants/2022/olif.mdrenamed+1−1
@@ -12,7 +12,7 @@ description = "Olif: olfactive rendering of Urbit address space"
1212reward = "2 stars"
1313assignee = ["~litneb-maltyp"]
1414grant_id = "P0159"
15−champion = "~tocrex-holpen"
15+champion = ["~tocrex-holpen"]
1616completed = false
1717+++
1818
content/grants/peat.md → content/grants/2022/peat.mdrenamed+3−2
@@ -12,11 +12,12 @@ image = ""
1212description = "Social Areoloy, or, Urbit's first Backup Utility"
1313reward = "4 stars"
1414assignee = ["Quartus"]
15−champion = "~sarlev-sarsen"
15+champion = ["~sarlev-sarsen"]
1616grant_id = "P0174"
1717completed = false
1818canceled = false
19−link = ""
19+link = "~magped-magped-rabsef-bicrym/peat"
20+deliverable = "~magped-magped-rabsef-bicrym/peat"
2021
2122+++
2223
content/grants/2022/persistent-memory.mdnew file+157
@@ -0,0 +1,157 @@
1++++
2+title = "New Mars Persistent Memory"
3+date = "2022-08-24"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "Runtime" ]
8+
9+[extra]
10+image = ""
11+description = "Development of persistent memory arena for the New Mars runtime"
12+reward = "4 stars"
13+champion = ["~ritpub-sipsyl"]
14+assignee = ["~finmep-lanteb"]
15+grant_id = "B0178"
16+completed = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0178&prefill_Grant+Name=New%20Mars%20Persistent%20Memory%20Arena"
18++++
19+
20+# Rationale
21+
22+New Mars requires a persistence layer. Nouns which are allocated in the top frame of a 2stackz memory manager can only be freed by resetting the stack. This loses all nouns. Therefore, for nouns which persist between computations, another arena is needed.
23+
24+These are also the nouns which should be included in a snapshot. Therefore, this arena ought to exist in memory mapped to persistent storage. This also represents a solution to the loom size limit: since memory is block-storage-backed, we can grow the Arvo state much larger than physical RAM or system swap space permit, and rely on virtual memory to make pages resident when we read them.
25+
26+Since this memory will never be used to directly allocate a noun, we do not need the speed of bump-allocating. We do require stable addressing along with fragmentation resistance. Therefore, we will take design cues from `malloc` implementations, and maintain information about free spaces in our memory arena. For nouns, freeing will be triggered by tracing or reference counting from a set of roots.
27+
28+This implies that any noun used as an input to a computation run in a stack arena must be maintained as a root until that computation completes. For instance: an Arvo core stored in persistent memory is used as input to an event computation. This core is maintained as a root in the persistent arena until the computation has completed.
29+
30+This bounty details the parameters expected to support the broader New Mars runtime.
31+
32+## Copy-on-Write File-Backed Memory Arena
33+
34+As the [Varnish](https://varnish-cache.org/docs/trunk/phk/notes.html) notes point out: a userspace program ought not to go to great lengths to juggle disk vs memory residency for persistent data. This is something the (terran) operating system already puts large amounts of work into. It is not necessary to work very hard to manage eviction and restoration of immutable data. At the greatest extent of effort, judicious use of `madvise` calls can reduce block storage wait times.
35+
36+Every page in our memory-backed arena is mapped to a region of a file. This ensures that the operating system can evict the page at will, without need for swap space. The file contains an index which is read when the process starts, describing which regions should be mapped to which virtual memory addresses. This permits us to persist data without serialization or deserialization. The file stores a memory image of the persistent arena.
37+
38+What is more difficult is to ensure that data *written* to the arena is fully synchronized and that the persistent index between file and memory locations do not point to corrupted data. This is addressed with a "copy-on-write" strategy, similar but not identical to that of [LMDB](http://www.lmdb.tech/media/20120829-LinuxCon-MDB-txt.pdf).
39+
40+The copy-on-write strategy ensures that commmitted data is not corrupted. Since it is not possible to "atomically" write data to disk, committed data is not overwritten, but rather copied and modified. Committing then progressively ensures that this new data is durably written to disk, and that the index of disk regions to memory regions is durably updated, before it will permit the previous copy to be overwritten.
41+
42+### Handling writes to the arena
43+
44+There are several ways in which we can handle writes without overwriting, and possibly corrupting, data already committed to our store.
45+
46+By default, pages in the persistent memory arena are protected read-only (`PROT_READ` flag to `mmap()` or `mprotect()`). This means that an attempt to write through a pointer into such a page will trigger a protection fault, raising a SIGSEGV to our process.
47+
48+#### Immediate copying
49+
50+The most likely successful approach involves immediately copying the page to a new page, mapped to a new region of the file, and then mapping this page back over the same virtual memory space.
51+
52+To handle the SIGSEGV signal and resolve the fault, our handler will:
53+
54+- move the page to the copy-on-write set, so other threads faulting will not also attempt to copy the page.
55+- `write()` the contents of the page to an unused region of the backing block storage. Note that this will not block on writing through to the disk, though it may write through if the OS decides.
56+- `mmap()` the new region to the address of the original page, being sure to set `MAP_SHARED`, `PROT_READ`, and `PROT_WRITE`
57+- Move the page from the copy-on-write set to the dirty set.
58+
59+The net effect of this is that the file region to which the read-protected page was mapped will remain unmodified, but our process continues with identical contents in a virtual memory page mapped to a new region of the file. The process continues from the faulting instruction and writes to memory. Index metadata which maps regions of the file to regions of memory remains untouched at this juncture.
60+
61+To facilitate restoring the persistent memory arena from durable block storage, we reserve two pages at the beginning of the file for metadata storage. This does not limit us to a page for metadata, we may commit metadata objects alongside our stored data, and reference it from a page. A metadata page contains a counter and a checksum of the page's contents. The page with a valid checksum and the more recent counter is used to load the data.
62+
63+To atomically commit writes since the last commit to durable storage, we simply `msync()` each dirty page. If all syncs succeed, we know that data in these pages is durably persisted to disk. We may now safely write a new metadata page to whichever metadata page is not in use. Once this too successfully `msync`s, our writes are durably committed.
64+
65+#### Lazy copying
66+
67+Another possible approach which leverages kernel support for in-memory copy-on-write, at the expense of using a boundable amount of swap, is to make writable mappings `MAP_PRIVATE`. This instructs the kernel to copy the page in the page cache on the first write. Unfortunately, this is now an anonymous mapping, meaning it is not backed by file storage.
68+Thus, if the kernel elects to evict it, it will be written to swap space on disk. It is still necessary to map pages as `PROT_READ` and use a signal handler, because we must track which pages are dirtied. It is almost certainly necessary to set a configurable limit on the number of dirty pages before a snapshot will be committed, since the number of dirty pages is limited by the available RAM and swap.
69+
70+To commit, we select regions in the file from the free list, and `write()` each dirty page to a free region.
71+We must then achieve a successful `fsync()` to know that the file has been committed.
72+
73+### When to commit
74+
75+Committing is required to know that an event is durably persisted in the log. It is also required to save a snapshot to disk.
76+
77+### Memory allocation
78+
79+Allocation of memory space for persisted nouns, and for helper structures for the runtime, follows largely the algorithm from [phkmalloc](https://papers.freebsd.org/1998/phk-malloc.files/phk-malloc-paper.pdf).
80+Briefly:
81+
82+- Pages are tracked as free, start, continue, or partitioned
83+- Small allocations seek space in a partitioned page, and only partition a page if no suitable space is found
84+- Large allocations (> 1/2 a page) are allocated sufficient contiguous free pages
85+
86+One difference is that since all of our persistent memory is file-backed, the acquisition of new memory consists in mapping new, initially-dirty pages, backed by unused regions of block storage, instead of using the `brk` syscall.
87+
88+### Block region allocation
89+
90+As well as allocating memory to noun (fragments) which need to be copied into the persistent set, we must also allocate regions of block storage to memory pages. Fortunately this is much easier. All pages are the same size. When committing writes, we can take note of file regions which are not mapped by the new metadata, and prepopulate a free list of file regions with these regions. The list becomes usable once the commit succeeds. We simply pop regions off of the list, starting with those nearest the beginning of the file. until it is exhausted, at which point we must extend the file.
91+
92+It's not clear whether it would be necessary to shrink the backing file, but if so, this could initially be done manually with a separate program, or a heuristic could be applied. Perhaps when a certain ratio of free-to-used pages are run, a defragmentation step is run, followed by shrinking the file.
93+
94+## Snapshots
95+
96+After each event is processed, the working state is copied to the snapshot persistent arena to be used as input for the next event. Creating a durable snapshot consists of committing, and recording a pair of event number and noun pointer in a durable metadata record. Metadata is referenced from the root page of a commit, and includes the event number of the snapshot and a pointer to the snapshotted noun.
97+
98+## Event log
99+
100+The event log should live in a separate arena from Arvo snapshot nouns. These arenas should be of incomparable seniority: that is, references are not permitted between either of them. This precludes synchronization issues between snapshot and event log commits, and ensures that old epochs of the event log can be freed without corrupting a snapshot.
101+
102+This requires logic in the copier to ensure that a reference is only preserved as a reference if the seniority of the source is ≤ the seniority of the destination.
103+
104+Epochs in the event log can be stored as linked lists in the event log persistent arena. In order to safely release effects computed from incoming events, the events must be durably written to disk.
105+
106+Allocations in this arena may be made by bumping a pointer within pages. Dirtying a page does not necessitate copying as long as the pointer to the most recent event can be stored consistently, and is updated *after* an event is made durable on disk. This eliminates repeated copies of a page to re-dirty it after a commit. The only time when a free block of storage must be allocated to a page is when a new page is mapped. If each epoch has its own page set, then when an epoch is discarded, pages may simply be unmapped together and their blocks re-added to the free list.
107+
108+The separate arena need not be maintained in an entirely separate memory region. Rather, on disk, two indexes each with two root pages (which are alternated for commits) can be maintained, and the allocator can track which pages belong to which arena, and inform the persistence subsystem of this when requesting free pages, so that the persistence subsystem knows which index should track a newly dirtied page.
109+
110+## Concurrency
111+
112+Because nouns are immutable, and because the copy-on-write approach ensures that a new, dirty page is a copy of an existing clean page prior to mapping it, readers should never see an inconsistent state of an object so long as that object is traceable from a root.
113+
114+It is not necessary to support multiple writers to the arena. Event (`+poke`) computation is linearized: we cannot start computing the next event until the result of the previous event is copied to the arena. Computation of scries (`+peek`) may run concurrently, but will only read from the arena unless new code generation is necessary.
115+
116+Thus, it should suffice to maintain a single, global writer lock for an arena.
117+Contention for this lock is not likely to be high, and this will eliminate a great deal of complexity which would obtain if page dirtying and commits required more granular synchronization.
118+
119+## Tuning
120+
121+Commit frequency of the Arvo snapshot arena is a potentially tunable value, with performance implications.
122+Committing more often incurs more disk IO, saving nouns that will potentially soon be discarded (Ames queues, for instance). However, under memory pressure, it makes paging more performant, as the proportion of dirty pages which must be *written* to disk to evict is smaller. Already-committed pages can simply be evicted from memory and re-read from disk when a read fault occurs. Committing less often requires writes as part of eviction, but reduces disk IO. It is desirable as long as memory pressure as low, and highly desirable for block storage where write-wearing is a concern.
123+
124+
125+# Evaluation
126+An important part of this work is to objectively evaluate the proposed approach. This will require the implementation of at least one alternate approach. The primary alternative is to map pages `MAP_PRIVATE` and simply track dirty pages and set `PROT_WRITE` in the fault handler. Then dirty pages could be more lazily written to disk, using `write()`, and committing using `fsync()`. The main reason this tradeoff is not expected to perform well is that it requires the underlying OS to have swap space configured and available if a dirty page must be evicted from the page cache. Another way of stating this is that the size of our dirty page set is limited by available RAM and swap space.
127+
128+However, this approach is used both by the current Vere as well as by LMDB for writing dirtied pages. It should therefore be implemented for New Mars at least by way of comparison.
129+
130+# Milestones & Compensation
131+
132+## Milestone 1: Basic copy-on-write arena
133+
134+Implement a copy-on-write arena by using `write()` to copy pages to new regions of the backing file.
135+This should include at least single-arena snapshot support.
136+
137+Compensation: 1 star
138+
139+## Milestone 2: Kernel copy-on-write (`MAP_PRIVATE`) + lazy write arena
140+
141+Implement a copy-on-write arena by mapping pages `MAP_PRIVATE` and lazily writing dirty pages to the backing file.
142+
143+Compensation: 1 star
144+
145+## Milestone 3: Memory allocation and separate event arena
146+
147+Implement a memory allocator on top of this arena. This includes the ability to store metadata such as roots which will be committed with the snapshot, and reference counting or tracing to free nouns which are not referenced from the root.
148+
149+Implement a separate (may be interleaved at the page level in memory/on disk) arena for event logs, which is bump-allocated and not copy-on-write but rather does not reallocate in committed pages.
150+
151+Compensation: 2 stars
152+
153+## Stretch/beyond scope
154+- Migration to/from vere
155+ - Portable snapshots?
156+ - LMDB event log import/export
157+- Raw block devices?
content/grants/2022/plug.mdnew file+165
@@ -0,0 +1,165 @@
1++++
2+
3+title = "Plug"
4+date = "2022-09-01"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Sell a catalog of physical goods from your Urbit"
13+reward = "5 stars"
14+assignee = ["~hastyp-patmud"]
15+champion = ["~novlud-padtyv"]
16+grant_id = "P0156"
17+completed = false
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Elevator Pitch
24+Plug is a lightweight way to list and sell a small catalog of physical goods on Urbit — Plug your merch!
25+
26+# Purpose
27+
28+Commerce is one of the most important needs fulfilled by the internet today. While there is a long way to go in terms of a complete solution for businesses at scale. There is no reason why Urbiters shouldn’t be able to move Etsy stores or Ebay listings onto Urbit, and sell to their friends on network.
29+
30+Plug is that solution: A lightweight way to list products and take payments, storing your data on your Urbit where it can’t be taken away or sold back to you as a “Premium Tier”.
31+
32+The goal of plug is to immediately enable users that want to sell one or a handful of things online today, while keeping in mind how it might accommodate adjacent systems built around it later — when it comes time to build tooling for more robust operations.
33+
34+# Scope
35+
36+There are many systems used by ECommerce stores today:
37+* **Storefront** — A interface for listing products, and checking out; often includes other media and content (I.e. pages), and things like discounts and coupons
38+* **Product Information Management (PIM)** — An interface for managing things like product listings, variants, product metadata, product dimensions etc
39+* **Inventory** — An interface and associated reports for managing quantity and supply of various products, variants and SKUs contained in a PIM
40+* **Warehouse Management System (WMS)** — A set of interfaces for tracking the handling of inventory items and related metadata (location, expiration, damage etc)
41+* **Fulfillment Management System (FMS)** — An set of interfaces for packing and shipping pieces of inventory, as well as tracking and notifications
42+* **Procurement / ERP** — A system for generating POs and ordering products from your suppliers; often includes forecasting
43+* **Marketplace** — A system which accommodates the abstraction of having multiple sellers (and their associated stores and catalogs) rather than just one; applicable at all layers of the data model
44+
45+As you can see the scope is rather large. Plug is only intended to solve for a subset of this upon delivery, however its data models should be aware of these adjacent needs and take pains to future proof themselves for easy extension. A brief description of what Plug will cover is as follows:
46+* A **PIM Interface** to create, edit, delete basic product listings — title, images, description, id — no variants, metadata, complex specs etc
47+* A **storefront** to display product listings and a **checkout** (Bitcoin, Fiat); additional site content will be minimal
48+ * *Note: implementation will use JAMStack to insert web2 fiat payment rails for now, with the intent to upgrade once a native solution is available*
49+
50+While by no means comprehensive, this targeted selection of tooling should be complete for the set of use cases we are targeting: *seller’s who want to list individual items, or a small catalog*
51+
52+# Design and Implementation
53+
54+## User Segments
55+* Sellers
56+* Buyers
57+
58+## User Stories
59+1. As a **seller**, I need to be able to store product information on my Urbit, so that I own and control the content for my site
60+2. As a **seller**, I need to be able to create, update, and delete product information on my Urbit, so that I can poke and scry to manage my content
61+3. As a **seller**, I need to be able to add a product listing in a GUI, so that my product can be made available to buyers
62+4. As a **seller**, I need to be able to remove a product listing in a GUI, so that it does not keep getting bought after it is sold
63+5. As a **seller**, I need to be able to update product listings title, description and images in a GUI, so that I can make listings more enticing / error free
64+6. As a **seller**, I need to be able to update the price of a listing in a GUI, so that my price remains competitive
65+7. As a **seller**, I need to be able to serve a store, so that I can share product listings with buyers
66+8. As a **buyer**, I need to see product listings so that I can shop for what I want
67+9. As a **buyer**, I need to be able to add items to cart, for later purchasing
68+10. As a **seller**, I need customers to be redirected to an external checkout page, so that one of my various payment processors can validate the cart and collect payment
69+11. As a **buyer**, I need to be able to check out, so that I get my Items
70+12. As a **buyer**, I need to be able to pay with fiat, so that my bank can show my NSA Agent my conspicuous spending 🕵🏻‍♂️ 😉
71+13. As a **seller**, I need to be able to store bitcoin carts in my urbit, so that they can be made available in a GUI
72+14. As a **seller**, I need bitcoin carts to contain order info, that I know what to ship
73+15. As a **buyer**, I need bitcoin carts to contain payment/price info, that I know what to pay and which address to send to
74+16. As a **buyer**, I need to be able to pay with bitcoin wallet, so that my indiscretions remain private and decentralized 👌
75+17. As a **seller**, I need to be able to see bitcoin carts in a GUI, so that I know when orders come in
76+18. As a **seller**, I need to be able to see when a buyer has paid a bitcoin cart, so that I know to ship the items
77+
78+## Technical Reqs
79+
80+System will be desgned to send users to an external checkout; for the purposes of this grant, this will be a 3rd party web2/JS payment processor, in future work this boundary will be replaced with an Urbit native checkout application (either by gall or a web2/glob). In both cases the boundary/API contract should be similar. Will work with Tirrel on the design to minimize friction down the line for this future work.
81+
82+## Engineering Design
83+
84+### Containter Descriptions
85+The implementation will have 3-4 distinct parts
86+* **PIM Backend** — a gall agent, essentially a product listing DB and associated pokes/scries for CRUD
87+* **PIM Frontend** — A globbed React (or Vue?) app; list of existing listings, form for adding listings, form for editing listings etc; image storage in S3 (or other URL)
88+* **A web storefront** — A (web2?) storefront built and served from your urbit via a gall agent and sail; displays product, and lets a user check out; payment processing via JamCart or SnipCart
89+* **Bitcoin Cart backend?** — a gall agent, handles interaction with bitcoin wallet to validate a cart has been paid (need some direction here)
90+
91+### System Context (C1)
92+
93+![IMAGE](http://thisistheaj.com/wp-content/uploads/2022/06/Screen-Shot-2022-06-17-at-12.39.40-PM.png)
94+
95+### Container Interactions (C2)
96+
97+![IMAGE](http://thisistheaj.com/wp-content/uploads/2022/06/Screen-Shot-2022-06-17-at-12.39.51-PM.png)
98+
99+# Milestones
100+
101+## 1. Data Design + PIM Backend
102+**Expected Completion**: Early Sept 2022
103+**Deliverables**:
104+* Engineering Designs for the system, i.e. C4 and preliminary Data Models
105+* A Gall Agent, User Stories 1-2
106+**Payment**: 1 Star
107+
108+## 2. UI Design + PIM Frontend
109+**Expected Completion**: Late Sept 2022 (~aiming at assembly demo)
110+**Deliverables**:
111+* Greybox Skteches of the PIM UI Designs
112+* Globbed JS App, User Stories 3-6
113+**Payment**: 1 Star
114+
115+
116+## 3. Sail Storefront w/ fiat payment
117+**Expected Completion**: Oct 2022
118+**Deliverables**:
119+* Greybox Skteches of the Store UI Designs
120+* A Gall Agent + a sail frontend,
121+* JAM Stack cart integration
122+* User Stories 7,8
123+**Payment**: 1 Star
124+
125+## 4. Fiat Checkout Integration
126+**Expected Completion**: Nov 2022
127+**Deliverables**:
128+* 2 sets ofIntegration design docs and API contract: one for this grant and 1 for the later urbit native integration
129+* User Stories 9-11
130+**Payment**: 1 Star
131+
132+## 5. Bitcoin Cart Integration
133+**Expected Completion**: Dec 2022
134+**Deliverables**: A Globbed JS App + additional work on sail store, User Stories 12-17
135+**Payment**: 1 Star
136+
137+# About Me
138+
139+I am a seasoned full stack application developer. Although my initial training was in design and business, I keep getting more technical out of necessity. I’ve been an IC, an Engineering Manager, and a PM in the past.
140+
141+Most notably I spent 2.5 years leading a team in charge of Warehousing and Supply chain Engineering at a Unicorn Delivery App startup, where I led a team that designed and built their WMS, and ERP systems from pre-valuation to 11B+.
142+
143+I also have my own ecommerce store nowadays so I am very familiar with the space. Ideally I would like to get paid to port all of the SaaS products I use onto Urbit, so that myself and others can start serving our stores from there and take our data away from shopify and amazon.
144+
145+I believe I am uniquely positioned to execute on this.
146+
147+I am already somewhat familiar with hoon, gall, ames and http-api. I built a habit tracker app that can be found at `web+urbitgraph://group/~hastyp-patmud/ulyssess`
148+
149+# Future Work
150+
151+Although this project is scoped to be SLC (simple, loveable, complete) for the purposes of this grant, here is a preview of what a tentative roadmap of follow on projects could look like:
152+**Plug** — Sell a Thing
153+* Product Listing
154+* Payment
155+**Hawk** — Display Your Wares
156+* Full Cart
157+* PIM including Variants, meta, specs etc
158+**Vend** — Track your merchandise
159+* Desktop Inventory system
160+**Ware** — Manage your physical business
161+* WMS, including PO receipt, Counting, moving, damaging, expiring inventory pieces
162+**Flea** — Invite sellers to your marketplace
163+* MarketPlace/Multiple Sellers
164+**Grab** — Manage your supply chain
165+* Procurement/ERP, PO generation, forecasting, accounting estimates etc
content/grants/2022/pony-bounty.mdnew file+72
@@ -0,0 +1,72 @@
1++++
2+title = "%pony"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Urbit-native long-form mail for threaded communications."
12+reward = "4 stars"
13+assignee = ["~hanfel-dovned"]
14+champion = ["~sarlev-sarsen"]
15+grant_id = "B0191"
16+completed = true
17+work_request_link="https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0191&prefill_Grant+Name=Pony"
18++++
19+
20+# %pony: Urbit-native long-form mail
21+
22+## Purpose
23+The objective of this work is to create an Urbit-native client to facilitate long-form, threaded communication (hereafter "verbose communication") between groups of users. Communication over the Urbit network is already ubiquitous and straightforward. However, it is restricted to a particular set of formats: namely the chatroom, notebook, and collection functionality provided by the Groups app. It is entirely possible to conduct verbose communication over Groups, but Groups is not designed to facilitate such activity. A built-to-purpose Gall app and interface have the potential to dramatically improve the experience and provide a familiar communication tool for new and old users alike.
24+
25+## Background
26+Anything you can do with email, you can certainly do with Groups. But some functions of email are difficult to replicate with Groups alone:
27+- Threading and subjects, i.e.: carrying on multiple conversations with the same set of ships, but with specific topics and context for each conversation, as opposed to lumping all of those conversations together in one chat.
28+- Per-message addressing, or carrying on a conversation with a different set of ships at different stages of the conversation. With Terran email, it's straightforward for me to start a conversation with Bob, and later add Alice, without losing context at any point. In the existing Groups app, doing this would require starting a new chat and restating all of the preceding context.
29+- Blind carbon copy (Bcc) functionality. It is often useful to send a message to a set of ships, without disclosing the full list of recipients to everyone receiving the message. This is strictly not possible with the current iteration of Groups.
30+- Archiving and sorting conversations with folders and labels. EScape, the alternative Groups client, has made some progress on this front, but first-rate functionality for organizing and sorting messages in the Groups app is still being developed. Additional affordances—for example, sending incoming messages to one or another folder based on the origin ship's status in my own %pals state—could make community management significantly easier.
31+- Drafts. Groups currently preserves any text written in the composition box of a channel, but a full-featured drafts system with the same organization affordances mentioned above would be a considerable improvement.
32+- Scheduling, and otherwise automating, the dispatch of messages.
33+
34+## Implementation
35+This project is probably best undertaken by a two-person team, one with experience is in frontend web development and the other with enough Hoon experience to build the Gall app. Working in parallel and collaborating on the architecture of the overall application will be key to success.
36+On the frontend, editing text is the most complex part of the app. This is particularly true if the scope of the project includes full-featured HTML editing, as with traditional email; conversely, the scope and effort involved would be much more attainable if the content of %pony messages were initially restricted to Groups-flavored Markdown. In building up to a minimum viable app, the most expedient approach may be to make use of an open-source JavaScript text editor, such as Quill.js, ByteMD, or similar.
37+It seems likely that the Gall app and associated core functionality of %pony could be achieved with a new interface to the existing %graph-store, or it may be an opportunity to make use of the new 'Groups 2' framework from TLON.
38+Again, in my understanding, the %graph-query agent is still forthcoming, which would make searching for messages by their content or author straightforward.
39+The minimum viable functionality consists in sending messages to some set of ships, saving and editing drafts, and being able to reply to a given message. Rich editing, automation and organization are likely further afield, but well within scope.
40+
41+## User Stories
42+- I can edit a message on my ship, and send it to some set of ships.
43+- I can, at my discretion, choose not to include the full list of recipients along with the message (Bcc).
44+- I can reply to received messages, with all previous messages in the conversation easily accessible to myself and the recipient.
45+- I can forward a message or conversation to some set of ships.
46+- I can compose a message and save it as a draft without sending it.
47+- I can sort conversations into folders, including an archive or garbage folder for messages I'm no longer concerned with.
48+- I can categorize messages and conversations with custom tags.
49+- I can set rules controlling how %pony will handle incoming messages, based on their author, content, %pals tags, etc.
50+- Pending the release of %graph-query, I can search for messages according to their content, author, date of receipt, etc.
51+## Milestones & Compensation
52+Final milestones and compensation are pending selection of the bounty applicant and refinement of the exact execution plan, but are expected to look something like the following:
53+### Milestone 1 - MVP
54+Expected completion: November 30th 2022
55+
56+Payment: 2 stars
57+
58+The Gall agent and frontend have all core functionality in place. Sending and receiving messages, replying to threads, editing and saving drafts, and forwarding messages are all possible.
59+
60+### Milestone 2 - Advanced Functionality and Polish
61+
62+Expected completion: January 31st 2022
63+
64+Payment: 2 stars
65+
66+Received messages and conversations can be sorted into folders, archived, and categorized with custom tags. Incoming messages can be categorized and sorted according to the author's %pals status (mutual status, tags) on the recipient ship. Messages can be scheduled to be sent at a particular time, and other agents on the ship can request to write a message into %pony's Drafts folder, pending final approval by the pilot before sending.
67+
68+### Strech Goals
69+- Referencing arbitrary agent state within a message or thread
70+- Integration with Contacts (%whom) application, or other agents.
71+- S3 Integration for 'Attachments
72+These and other potential features will be assessed upon the completion of the MVP application and formally agreed to between grantee and Champion prior to further work being undertaking.
content/grants/port-maintenance.md → content/grants/2022/port-maintenance.mdrenamed+2−2
@@ -8,10 +8,10 @@ grant_category = ["App Dev"]
88image = ""
99description = "Maintain the Port application"
1010reward = "2 stars"
11−champion = "~nocsyx-lassul"
11+champion = ["~nocsyx-lassul"]
1212assignee = ["~latter-bolden"]
1313grant_id = "B0112"
14−completed = false
14+completed = true
1515work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0137&prefill_Grant+Name=Port%20Maintenance"
1616+++
1717
content/grants/2022/port-to-hosting.mdnew file+56
@@ -0,0 +1,56 @@
1++++
2+title = "Port to Hosting Protocol"
3+date = "2022-09-25"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "Other" ]
8+
9+[extra]
10+image = ""
11+description = "Create an easy way to onboard Port users to hosting providers"
12+reward = "3 stars"
13+champion = ["~latter-bolden"]
14+assignee = [""]
15+grant_id = "B0194"
16+completed = false
17+canceled = true
18+work_request_link="https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0194&prefill_Grant+Name=Port%20to%20Hosting%20Onboarding%20Protocol"
19++++
20+
21+## Summary
22+Over the past year, Port has established itself as a critical onramp among Urbit newcomers. For non-technical users, it remains the only free option suitable for getting onto the network in just a few clicks and serves as a first impression to the computing platform as a whole. That said, home hosting of your ship can come with a few hurdles that are most easily solved by using a hosting provider. As such, Port is well positioned to streamline network onboarding while providing a simple user experience that integrates well with the rest of the ecosystem.
23+
24+## Streamlined Onboarding
25+Running an Urbit node locally provides a low touch way for beginners to dip their toes. But after continued use and investment in the system, the limitations of hosting from your personal computer become more pronounced. For the foreseeable future, cloud hosting providers will be the go-to option for ensuring uptime and stability once the value proposition for a recurring subscription is realized.
26+Currently, this transition requires the user to navigate the decentralized ecosystem of providers and after selecting one, figure out how to archive and upload their (usually quite large) pier. For non-technical users, this presents unnecessary friction that limits adoption.
27+The proposed solution is an open protocol for transitioning to hosting providers that would be fully integrated into Port. The app would present a variety of providers to choose from, direct the user to the relevant signup flow after selecting one, and handle all of the legwork required to transfer the pier.
28+This same tradeoff of simplified initial use vs sustainable participation applies to ephemeral identities (comets). Gatekeeping these identities at the group level is already common practice making planets necessary for full network participation. As a stretch goal, an analogous protocol would be specified and integrated to handle planet purchase and key transfer from within Port.
29+
30+## User Stories
31+
32+- As a Port user (PU), I can browse potential hosting providers from within the app, so I know which one would best serve my needs.
33+- As a PU, when I’ve decided I don’t want to host my ship locally, I can seamlessly transition to a hosting provider from within the app.
34+- As a PU, I’m encouraged to purchase a planet if I don’t already have one instead of booting a comet, so I can fully participate in the network. (stretch goal)
35+
36+- As a hosting provider (HP), I can apply to have my service listed within Port and set/update my logo, description, and pricing for display.
37+- As a HP, I can sign up new customers and pull in their existing pier through the new protocol.
38+
39+- As an identity provider (IP), I can apply to have my service listed within Port and set/update my logo, description, and pricing for display.
40+- As an IP, I can sell identities and forward the keys to Port for ease of use.
41+
42+## Milestones & Compensation
43+
44+### Milestone 1: Protocol Fully Specified — 1 Month, 1 star
45+Research and design of the hosting and identity protocol complete. Concrete specification published. Ready to be developed against by providers.
46+
47+### Milestone 2: Backend Supported, Interface Designed — 1 Month, 1 star
48+Functioning protocol client integrated into the Port backend. Development server built out. Mockups or other intermediate design assets available for coming frontend build out (both hosting and identity).
49+
50+### Frontend Integrated — 1 Month, 1 star
51+User interface developed and hooked up to backend functionality. End to end support for transitioning a pier to hosting provider. Stretch goal of completing purchase flow for planets if time permits.
52+
53+### Further Research
54+Gather feedback from other stakeholders (UF, hosting and identity providers)
55+Prior to applicants begining work, final conversations and edits to this scope will be covered and agreed to with the Champion.
56+
content/grants/2022/profiling.mdnew file+74
@@ -0,0 +1,74 @@
1++++
2+title = "Vere Profiling"
3+date = "2022-08-26"
4+
5+[taxonomies]
6+grant_type = [ "Apprenticeship" ]
7+grant_category = [ "Core Dev", "Runtime" ]
8+
9+[extra]
10+image = ""
11+description = "Uncover and visualize performance bottlenecks in the runtime"
12+reward = "1 star"
13+mentor = ["~fanfun-mocbud"]
14+assignee = ["~pontus-fadpun"]
15+grant_id = "A0180"
16+completed = true
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0180&prefill_Grant+Name=Vere%20Profiling"
18++++
19+
20+# Vere Profiling Apprenticeship
21+
22+Urbit currently has two profilers: a tracing profiler and a sampling profiler.
23+The tracing profiler writes a stack trace to `<pier>/.urb/put/trace`. To enable:
24+```console
25+$ urbit -j <pier>
26+```
27+
28+The sampling profiler uses `SIGPROF` to build up a set of data points detailing
29+the code paths that the runtime spends the most time executing. To enable:
30+```console
31+$ cd <urbit_repo>/pkg/urbit
32+$ CPU_DEBUG=1 ./configure
33+$ make
34+$ build/urbit -P <pier>
35+```
36+
37+This project will add additional profiling capabilites to Vere by using
38+well-known profiling tools like `dtrace`, `bpftrace`, and similar to develop
39+more nuanced insights into the performance bottlenecks in Vere. Upon
40+identification, the bottlenecks will be addressed where possible, leading to a
41+more performant runtime. Exploration of alternative profiling techniques like
42+causal profiling is encouraged.
43+
44+## Deliverables
45+
46+- Integration of additional profiling tooling into Vere;
47+- list of performance bottlenecks;
48+- and patches addressing as many of the performance bottlenecks as possible.
49+
50+## Prerequisites
51+
52+- Proficiency in C
53+- Experience with profiling tools like `dtrace` (macOS, FreeBSD), `bpftrace`
54+ (Linux)
55+
56+## Educational Outcomes for the Apprentice
57+
58+The apprentice will:
59+
60+- learn about the current state of profiling in Vere;
61+- integrate new tooling into Vere;
62+- and address any performance bottlenecks discovered.
63+
64+## Responsibilities of the Mentor
65+
66+The mentor will:
67+
68+- provide technical direction via recurring meetings and DM;
69+- review code;
70+- and help the apprentice prepare the changes for release.
71+
72+## Duration and Compensation
73+
74+The expected duration is two months. Compensation is 1 star upon sucessful completion of the apprenticeship.
content/grants/2022/qr-login.mdnew file+48
@@ -0,0 +1,48 @@
1++++
2+
3+title = "Seamless QR Login"
4+date = "2022-09-13"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Implementation of the state-of-the-art, battle-tested user experience for logging into your urbit"
13+reward = "2 stars"
14+assignee = ["~mirtyl-wacdec"]
15+champion = ["~fabnev-hinmur"]
16+grant_id = "P0186"
17+completed = true
18+canceled = false
19+link = "~hoster-dozzod-sortug/qr-login"
20+deliverable = "~sortug/gate"
21+
22++++
23+
24+# %qr-login: Secure, seamless login for Urbit
25+
26+### Let's make joining Urbit easier
27+The first boot story of Urbit has improved much recent years, but it still requires technical skill. An Urbit user has to acquire an Urbit ID, which requires knowledge of the Ethereum ecosystem, and then has to find a good hosting setup to run the Urbit runtime, which also generally requires technical skill with Unix computers.
28+
29+But even if ID acquisition and hosting aren't an issue, say you are using a paid hosting service, or a friend took care of booting your ship for you. When you first visit your Urbit frontend, either the Grid web interface, or the EScape mobile app, you are greeted with a login screen asking for the `+code` login password, or even the ship's URL (in the case of EScape). You have to repeat that for every new device or browser that you use.
30+
31+This is not an ideal UX for the vast majority of users. Mainstream mobile apps such as Signal handle first login much more seamlessly; after registration is done, further logins are done via QR code. The app produces a QR code, you scan it, and that's it. That's the state-of-the-art, battle-tested user experience for modern applications. And we are bringing this to Urbit.
32+
33+%qr-login will make it easier for newcomers to use Urbit, and will greatly enhance the user experience of the future native applications, desktop and mobile, that Urbit deserves.
34+
35+### User stories
36+- A user will be able to login to Urbit just by scanning a QR code, no user input required, not even copy-pasting.
37+- A user will be able, if using a device without a camera, to receive a URL link and login to an Urbit ship instantly by clicking on it, again without any user action required.
38+- A hosting provider would be able to send a QR code or a URL link to a user, and have the user access his Urbit apps with a simple camera scan or click of a link.
39+
40+### Grantee
41+~sortug, represented by ~mirtyl-wacdec
42+
43+### Milestones
44+
45+#### Milestone 1
46+%qr-login implemented and fully functional. Merge ready PR for the [Uqbar official mobile template](https://github.com/uqbar-dao/urbit-mobile-app-template)
47+ETA: Before Assembly 2022
48+Payment: 2 stars.
content/grants/quorum.md → content/grants/2022/quorum.mdrenamed+2−2
@@ -12,8 +12,8 @@ description = "Quorum: Clone of Stack Exchange on Urbit"
1212reward = "3 stars"
1313assignee = ["~tamlut-modnys", "~litlep-nibbyt", "~sidnym-ladrut"]
1414grant_id = "B0167"
15−champion = "~lagrev-nocfep"
16−completed = false
15+champion = ["~lagrev-nocfep"]
16+completed = true
1717+++
1818
1919## Purpose
content/grants/regex-library.md → content/grants/2022/regex-library.mdrenamed+2−2
@@ -10,10 +10,10 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Implement a regular expressions library in Hoon"
1212reward = "3 stars"
13−mentor = "~lagrev-nocfep"
13+mentor = ["~lagrev-nocfep"]
1414assignee = ["~macrep-racdec"]
1515grant_id = "B0149"
16−completed = false
16+completed = true
1717canceled = false
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0177&prefill_Grant+Name=Regular%20Expressions%20Library"
1919+++
content/grants/seguro-phase-2.md → content/grants/2022/seguro-phase-2.mdrenamed+3−3
@@ -1,6 +1,6 @@
11+++
22
3−title = "Seguro Prototype"
3+title = "Seguro MVP"
44date = "2022-07-27"
55
66[taxonomies]
@@ -12,9 +12,9 @@ image = ""
1212description = "Implement a working FoundationDB event read/write layer that is as ready as possible for interfacing with the Urbit runtime."
1313reward = "5 stars"
1414assignee = ["~mastyr-bottec"]
15−champion = "~master-morzod"
15+champion = ["~master-morzod"]
1616grant_id = "P0168"
17−completed = false
17+completed = true
1818canceled = false
1919link = ""
2020
content/grants/seguro-prototype.md → content/grants/2022/seguro-prototype.mdrenamed+2−2
@@ -12,9 +12,9 @@ image = ""
1212description = ""
1313reward = "2 stars"
1414assignee = ["~mastyr-bottec"]
15−champion = "~master-morzod"
15+champion = ["~master-morzod"]
1616grant_id = "P0130"
17−completed = false
17+completed = true
1818canceled = false
1919link = ""
2020
content/grants/2022/serving-the-people.mdnew file+101
@@ -0,0 +1,101 @@
1++++
2+title = "Hari + Rama (The Urbit Cyclopaedia)"
3+date = "2022-03-25"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "Facilitating 'A literal but delinquent reprint of the Encyclopedia Schizophrenica on Urbit'."
12+reward = "6 stars"
13+assignee = ["~rabsef-bicrym", "~sogrum-savluc"]
14+grant_id = "B0211"
15+champion = ["~sarlev-sarsen"]
16+completed = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0211&prefill_Grant+Name=STP%20Cyclopaedia"
18++++
19+
20+# Hari + Rama (The Urbit Cyclopaedia)
21+
22+## Rationale
23+
24+Serving the People DAO would like to move some of their content onto the Urbit network. In order to do that, they need additional controls and facilities on top of the New Groups (and Diary) product Tlon will soon be releasing. Hari and Rama are a server and client agent for generating, maintaining, and connecting to "Foundations", groups that create Encyclopedias. Hari and Rama maintain additional metadata regarding the Encyclopedia, including folders, tags, permissioned authors and editors, opt-in view-count-per-post and unique-view tracking for the server.
25+
26+## Overview
27+* `hari:` An Encyclopedia Schizophrenica Server, on Urbit. Generates "Foundations" and allows `rama` clients to connect to them to receive metadata.
28+* `rama:` A client for injesting additional metadata about groups, from `hari`. Note that it is not necessary for a user to use `rama` to read the contents of a Foundation's Encyclopedia (though they won't have the full experience).
29+
30+## User Stories
31+
32+### Hari
33+1. I can create a Foundation (meaning a Public Group, with a section called "<my input>-paedia", that contains a Diary that only I can write to, but who's posts anyone can comment on.
34+
35+2. On creating such a Foundation, I associate with it some versionable set of metadata, which I can modify using a series of commands (initially, as below):
36+> Note: Hari contains both the state that rama normally carries plus some additional information that is not shared to clients.
37+
38+> Note: Hari's command set relating to metadata allows the host to set the folders and tags that are allowed on their Foundation. If authors (almoners) or janitors tag/retag some document with a tag not in the allowed list (`tags.public`), those tags will be stripped but stored in `proposed-tags.secret` whereupon the admin can approve those tags for later use.
39+```
40+++ states
41+ |%
42+ +$ rama
43+ $: folders=(jug term @ud)
44+ authors=(jug @p @ud)
45+ views=(map @ud @ud)
46+ tags=(jug term @ud)
47+ ==
48+ +$ hari
49+ $: public=rama
50+ $= secret
51+ $: proposed-tags=(set term)
52+ unique-views=(jug @ud @p)
53+ ==
54+ ==
55+ --
56+```
57+
58+3. For each Foundation that I create, I can permission a set of Almoners (writers) and Janitors (editors) for my Foundation.
59+ * Almoners can submit new articles and edit their own articles.
60+ * Janitors can retag/folder articles, edit articles, delete comments.
61+
62+4. I can also close my Foundations at will, and cause the relevant Groups cleanup activities.
63+
64+5. All metadata that I collect will be parsed into Hari. The public facing portions of this (de-identified) will be shared back to Rama users.
65+
66+6. Though I am technically the only writer to the Foundation, I will preserve metadata about authors when they send me articles they write.
67+
68+### Rama
69+
70+1. I can watch any number of providers, whereupon I will learn of the Foundations they host.
71+
72+2. I can join any Foundation or leave any Foundation from any host I watch, and Rama will track for me which I am in (despite being able to see this in Groups).
73+
74+3. I can allow or disallow the capture of my viewing information for metrics to my Foundation provider.
75+
76+4. I can save/delete articles into a list of my own (later editions might allow you to set up a Foundation from these materials).
77+
78+5. I can receive metadata updates from the host including new articles being added to folders, tags, new view counts, etc.
79+
80+6. I can view Foundations through standard Groups or through an interface that enriches that experience with the metadata captured by Hari and Rama.
81+
82+## Architecture
83+
84+The Foundation system will piggyback off of the New Groups system for content delivery. All Foundations will be legible and interactable through Groups, though they will lack some of the convenience of the metadata system that Hari and Rama afford.
85+
86+## Milestones
87+
88+### Milestone 1 - 3 stars
89+
90+* Initial product provided to STP for Front End Development
91+* Product includes all features described in user stories above
92+* Product documentation includes step-by-step instructions for interacting through a JavaScript Front End.
93+
94+### Milestone 2 - 2 stars
95+
96+* Front End Development is in progress and STP identifies that all required components are in place for the completion of Front End Development, inclusive of any additions, changes, deletions, modifications to the interaction pattern required to complete the desired activities (see user stories).
97+
98+### Milestone 3 - 1 star
99+
100+* Product is deployed and available for installation on Urbit.
101+* All user stories are satisfied, an application listing is available at urbit.org/ecosystem and documentation is available via `%docs`.
content/grants/slam.md → content/grants/2022/slam.mdrenamed+4−3
@@ -9,10 +9,11 @@ image = ""
99description = "Slam Action Game"
1010reward = "3 stars"
1111assignee = ["~hanfel-dovned"]
12−champion = "~rabsef-bicrym"
12+champion = ["~rabsef-bicrym"]
1313grant_id = "P0101"
14−completed = false
15−link = ""
14+completed = true
15+link = "~hanfel-dovned/arcadia"
16+deliverable = "~hanfel-dovned/slam"
1617+++
1718
1819## Overview
content/grants/slaw-scot-jets.md → content/grants/2022/slaw-scot-jets.mdrenamed+2−2
@@ -10,8 +10,8 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Tune slaw/scot jets for better perfomance."
1212reward = "1 star"
13−mentor = "~master-morzod"
14−assignee = [""]
13+mentor = ["~lagrev-nocfep"]
14+assignee = ["~ponmep-litsem"]
1515grant_id = "B0137"
1616completed = false
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0164&prefill_Grant+Name=Tune%20slaw%2Fscot%20Jets"
content/grants/2022/smart-lightbulb-controller.mdnew file+104
@@ -0,0 +1,104 @@
1++++
2+
3+title = "Smart light bulb app"
4+date = "2022-10-27"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "A smart light bulb app for controlling the ambiance in your home"
13+reward = "4 stars"
14+assignee = ["~pilwyc-fastec", "~larryx-woldyr"]
15+champion = ["~simfur-ritwed"]
16+grant_id = "P0199"
17+completed = true
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Smart light bulb app for Urbit
24+
25+## Summary
26+Urbit’s strong identity system with a focus on privacy and local control points to potential use in the smart home. To show a proof-of-concept for smart home control by Urbit we should build out a basic integration for a smart light bulb. In this prototype a bulb can show current state and be controlled from a standard [Gall app](https://urbit.org/docs/arvo/gall/gall) accessible as a tile from the user’s [Landscape](https://urbit.org/blog/landscape-a-portrait) home screen. The full history and logging of the bulb will be collected to provoke consideration of what should be controlled and tracked by the people living in the smart home. This will inspire people to think of the potential utility of Urbit in the smart home, inspire non-Urbit users to think of Urbit in non-community driven scenarios, and be a small step forward in understanding the affordances for Urbit in the home.
27+
28+## Scope
29+After completing the initial [Communal Computing for Urbit grant](https://urbit.org/grants/communal-computing) (and [release of the whitepaper](https://pilwyc-fastec-public.s3.us-west-2.amazonaws.com/Communal-Computing-for-Urbit-whitepaper.pdf)) we learned a lot about the expectations and problems Urbit users have with current smart home technologies. This includes the use of their identity, 3rd party data sharing, and maintenance.
30+
31+Smart light bulb integrations will be considered for those that have publicly available, HTTP-based APIs. The first integration will be with the [Philips Hue](https://developers.meethue.com/develop/hue-api-v2/getting-started/). There is a [developer program with documentation](https://developers.meethue.com/develop/get-started-2/).
32+
33+It should ideally be architected in such a way to allow for additional smart light bulb manufacturers that support HTTP-based integration to be added by other developers outside of the grant. Also, it should allow for integration of other device types with additional work to adopt their state and control capabilities longer term but not required in the delivery of this grant.
34+
35+This would require an app tile that would display basic device state and a more expansive app to control the state of the devices. If this is not possible technically or proves to be too much work we could consider only including current state and interactivity in future work.
36+
37+When opened the app would show the following:
38+
39+1. Current, single smart light bulb that is configured - if nothing is configured a link to do so
40+2. Ability to control the current on/off state and brightness - hue adjustment will be a stretch goal
41+3. Link to history and logging - this will include changes in configuration, on/off, etc.
42+4. Ability to manage devices: replacing current device, removing current devices, change configuration of current device
43+
44+Anything that is found to be not possible during spiking and development will require a conversation of an appropriate tradeoff, functionality being [stubbed](https://en.wikipedia.org/wiki/Method_stub) or removed depending on the impact of testing the concept.
45+
46+All smart light bulb providers require some type of specialized identity to be integrated (e.g. Philips Hue requires a Philips login) and will be linked with the Urbit ship’s planet. For this prototype we will use a moon since this seems like the most likely way a n Urbit device would be controlled and managed by a planet. All connected moons and comets will have the ability to control the connected light bulbs. However, they will not be able to configure new devices or remove them.
47+
48+During the implementation a decision should be made about how much we can obfuscate the specifics of each lightbulb manufacturer's identity system and developer keys. In the worst case, we will require the Urbit user to register as a developer to get their own keys. In the best case, we hope that they can log in via some bridge to a SSO for the lightbulb’s service. There will need to be some investigation into whether this should be inside the Gall app or part of a module outside of Urbit to handle the special cases of login for each provider.
49+
50+The reference design that will be created will then be shared via open source for other developers to consider how to integrate other smart light bulbs and smart home devices. What we learn from the development of this reference app and use will provide the foundation for another grant to evolve the smart home offering for Urbit.
51+
52+# Stages
53+The proposal will be broken into the following key stages:
54+
55+## Technology spiking - in progress
56+Investigation into Philip Hue’s developer program, APIs, and capabilities. This is already in progress.
57+
58+Some key questions that need to be answered:
59+
60+* Are there any complications of using a moon as the identity to control the smart light bulb?
61+* Will we be able to do all of this in a React front end and Hoon or do we need to create something outside of Urbit to handle state?
62+* What will the setup experience be like for people? Do they need to get their own developer key?
63+* How will this work for Tlon (or other provider) hosted planets? Or does this require a local Urbit instance on the same home network?
64+
65+## Design of home app
66+UI/UX for the display of state and control of the smart light bulbs. This would be part of the “[self-sovereign WeChat](https://messari.io/article/look-to-the-stars-navigating-the-urbit?referrer=author:mihai-grigore#:~:text=Imagine%20an%20extensible,existing%20computing%20platforms.)” where lightbulb control is integrated with Urbit’s Landscape application UX schema. Some prototyping and limited user testing should be performed based on an initial design.
67+
68+For the first version we will only display an app icon (such as the Urbit smart home logo) rather than provide interactive functionality. If possible the Landscape icon will be replaced with functionality but will be a stretch goal for the grant proposal.
69+
70+And the following interactions from the full app:
71+
72+1. See a more spacious (full screen) display of the current lightbulb state.
73+2. Ability to toggle light bulbs, control brightness and hue (stretch goal) if it is available for that lightbulb.
74+3. Access to history of change in state, configuration, etc.
75+4. Configure light bulbs by removing, replacing, and removing them from the app.
76+5. Control identities (moons for this prototype) which have permissions over given access accounts on the device/manufacturer side.
77+
78+The ship (and its planet’s identity) will be linked with the identities required by the HTTP API for each lightbulb manufacturer. Moons will also gain access to the lightbulbs control but would ideally limit the configuration of new/current light bulbs.
79+
80+## Implementation
81+Building the reference implementation based on the design and any updates from the initial user testing. The ability to add new lightbulb “providers” and potential extensibility to different smart home devices should be considered when implementing the app.
82+
83+## Testing
84+Beta program for Urbit users with smart light bulbs to try out and report issues which includes some qualitative interviews on their use. A user research interview guide will be created for this phase. All interviews will include problem questions (e.g. is this the right problem to solve in the smart home), usability (e.g. how does this app work for them), and future interest (e.g. how would this work in your home).
85+
86+## Publishing
87+Open source publishing of the reference design and implementation via Github. This will include blogging from the Urbit blog, podcast discussions, and any other appropriate announcements.
88+
89+# Why are we the right people for the job
90+~pilwyc-fastec completed the first Communal Computing for Urbit grant and has continued to grow the community focused on Urbit smart homes.
91+
92+~larryx-woldyr is a software engineer in the aerospace industry interested in sovereign computing and composable software. He wants to explore opportunities in IoT and learn more about what Urbit has to offer.
93+
94+# Milestones and Compensation
95+## Milestone 1 - 2 stars
96+* Technology spiking - October 31st, 2022
97+* Design of home app - November 15th, 2022
98+* Implementation - December 15th, 2022
99+## Milestone 2 - 2 stars
100+* Testing - January 6th, 2023
101+* Publishing - January 15th, 2023
102+
103+# Funding
104+4 stars to be split evenly between ~larryx-woldyr and ~pilwyc-fastec upon distribution of the app.
content/grants/symmetric-routing.md → content/grants/2022/symmetric-routing.mdrenamed+3−3
@@ -1,5 +1,5 @@
11+++
2−title = "UF Apprenticeship Grant: Symmetric Routing"
2+title = "Symmetric Routing"
33date = "2022-05-04"
44
55[taxonomies]
@@ -10,11 +10,11 @@ grant_category = [ "Core Dev" ]
1010image = ""
1111description = "Change Urbit's peer discovery, routing, and packet forwarding to use symmetric routing"
1212reward = "1 star"
13−mentor = "~rovnys-ricfer"
13+mentor = ["~rovnys-ricfer"]
1414assignee = ["~novned-tidsyl", "~boldur-dashes"]
1515grant_id = "A0135"
1616completed = false
17−canceled = false
17+canceled = true
1818work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0162&prefill_Grant+Name=Symmetric%20Routing"
1919+++
2020
content/grants/2022/trail.mdnew file+168
@@ -0,0 +1,168 @@
1++++
2+
3+title = "Trail"
4+date = "2022-10-27"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "An application for tracking and reviewing your outdoor workouts via a native mobile OS application, a webapp, and an Urbit backend for your sensitive location data"
13+reward = "4 stars"
14+assignee = ["~hanryc-tirpur"]
15+champion = ["~famhut-wolpyx"]
16+grant_id = "P0197"
17+completed = false
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Trail - An Outdoor Activity Tracker for Urbit
24+Outdoor workout trackers, especially when including social features, generally require users to submit sensitive location data to their servers. With %trail, an Urbit user can keep control over their sensitive location data with their own secure, private server. In addition, social features, such as workout challenges, will not require revealing a user’s social graph to a third party.
25+## App UI
26+Due to the nature of location tracking and map displays in mobile, it would seem best to have two different UIs depending on the context.
27+When out in the world and recording a run/bike ride/hike, the user should be using a native mobile experience.
28+When on a laptop reviewing previous exercises, a user would be using grid (browser), and therefore, will not have the capability to record exercise.
29+## Gall app API
30+The Gall App API will be documented clearly using the `%docs` app, and will address the following considerations:
31+- The %trail gall agent should be kept as small as possible.
32+- There are many possible data sources, implying that the %trail gall agent should not include data source parsing knowledge
33+- Not all users will care about all data sources. This implies:
34+ - Data sources should be separate from the %trail gall agent
35+ - There should be a mechanism to register their existence with the main gall agent
36+ - There could be 3rd party data source parsers that can be install separately from the %trail desk
37+- Indoor and outdoor activities will need to be treated differently.
38+
39+### Milestones & Compensation
40+
41+**Milestone 1: Gall app backend**
42+
43+*1 Star, Estimated delivery date: November 30, 2022*
44+
45+Pokes
46+- `%start-activity`: Starts an activity, making it available to receive location information.
47+- `%save-path`: Saves a list of locations to the currently active activity.
48+- `%stop-activity`: Stops an activity, but will allow activity to be continued at a later time.
49+- `%end-activity`: Ends an activity and will not allow further updates.
50+- `%delete-activity`: Deletes an activity.
51+- `%save-settings`: Saves settings, including whether distance should be measured in miles or km
52+Peeks
53+- View details of a previously completed activity
54+/sur
55+```
56+|%
57++$ id @
58++$ timestamp @
59++$ activity-type ?(%bike %walk %run)
60++$ distance-unit ?(%mile %km)
61++$ settings [unit=distance-unit]
62++$ location
63+ $: =timestamp
64+ lattitude=@rs
65+ longitude=@rs
66+ altitude=@rs
67+ heading=@rs
68+ ==
69++$ activity
70+ $: =id
71+ =activity-type
72+ segments=(list segment)
73+ total-distance=@rs
74+ total-elapsed-time=@rs
75+ ==
76++$ activity-summary [=id total-distance=@rs total-elapsed-time=@rs]
77++$ segment
78+ $: start-time=timestamp
79+ end-time=(unit timestamp)
80+ path=(list location)
81+ distance=@rs
82+ elapsed-time=@rs
83+ ==
84++$ activities ((mop id activity) gth)
85++$ action
86+ $% [%start-activity =id =activity-type]
87+ :: [%stop-activity =id path=(list location)]
88+ :: [%end-activity =id path=(list location)]
89+ :: [%delete-activity =id]
90+ [%save-settings unit=distance-unit]
91+ :: [%save-locations =id path=(list location)]
92+ ==
93++$ update
94+ $% [%activities list=(list activity-summary)]
95+ [%activity =activity]
96+ ==
97+--
98+```
99+
100+**Milestone 2: Basic outdoor workout tracking on iPhone**
101+
102+*1 Star, Estimated delivery date: December 31, 2022*
103+
104+- Choose between metric and imperial unit systems
105+- Live tracking of an outdoor workout
106+- Path on map updates as user moves
107+- Displays current pace, total distance, average speed
108+- View summary of previously completed workouts
109+- View details of a previously completed workout
110+
111+**Milestone 3: Grid application developed in React**
112+
113+*1 Star, Estimated delivery date: January 15, 2023*
114+
115+- View summary of previously completed workouts
116+- View details of a previously completed workout
117+- Edit workout
118+- Can modify the time of the workout to remove a time period at the end of a workout
119+
120+**Milestone 4: Ingest data from various sources**
121+
122+*1 Star, Estimated delivery date: January 31, 2023*
123+
124+- Ingest data from common activity file types
125+ - Create gall agent
126+ - Parse Strava data and save to %trail agent
127+ - Parse .gpx files
128+ - Parse .tcx files
129+ - Grid UI
130+ - Ability to enter Strava API access token
131+ - Ability to upload files to be parsed
132+- documentation of agents delivered via `%docs`
133+- App Ecosystem listing submitted via https://urbit.org/applications/submit
134+
135+## Future Integrations
136+When more of the base layer of health applications get built out, there are some exciting features that can be created by combining data from other apps.
137+- A workout routine / training program. This app could also include weightlifting programs as well as cardio.
138+ - Integrates with
139+ - Calendar
140+ - Groups
141+ - Can be used by:
142+ - Users can develop their own routines
143+ - Personal trainers can provide users with custom routines
144+- Exercise challenges. Challenge your friends to see who can accumulate the most miles in a month
145+ - Integrates with
146+ - Calendar
147+ - Groups
148+ - Chat
149+ - %pals / %whom
150+ - Can be used by
151+ - Groups
152+- Spin class. Join a decentralized spin class
153+ - Integrates with
154+ - Web RTC
155+ - Exercise bike
156+ - Groups
157+ - Can be used by
158+ - Spin class instructors
159+- Calorie estimation
160+ - Integrates with
161+ - Heartrate
162+ - Weight
163+
164+## About Me
165+I am a recent Hoon School Live and App School Live graduate. I also have 18 years of experience developing web apps and APIs using various back-end technologies including .NET and node.js, as well as modern JavaScript front-end frameworks including React/Redux, Vue, and Svelte over the past 6 years.
166+As importantly, I am extremely passionate about having fitness tracking and biometric data integrated with Urbit. It was the first use case that came to mind while reading the initial blog post describing Urbit.
167+
168+
content/grants/trill-ufa.md → content/grants/2022/trill-ufa.mdrenamed+3−2
@@ -12,11 +12,12 @@ image = ""
1212description = "Urbit microblogging platform and social feed aggregator"
1313reward = "5 stars"
1414assignee = ["~mirtyl-wacdec"]
15−champion = "~poldec-tonteg"
15+champion = ["~poldec-tonteg"]
1616grant_id = "P0127"
17−completed = false
17+completed = true
1818canceled = false
1919link = ""
20+deliverable = "~sortug/trill"
2021
2122+++
2223# Purpose
content/grants/trove.md → content/grants/2022/trove.mdrenamed+11−7
@@ -1,6 +1,6 @@
11+++
22title = "Trove: group file drive"
3−date = "2022-07-18"
3+date = "2022-11-08"
44
55[taxonomies]
66grant_type = [ "Bounty" ]
@@ -9,11 +9,11 @@ grant_category = [ "App Dev" ]
99[extra]
1010image = ""
1111description = "A shared file drive allowing the upload of files to an S3 bucket or IPFS and the ability to organize the file links in folders."
12−reward = "2 stars ($4k bonus if done by Assembly)"
13−assignee = [""]
12+reward = "4 stars ($8k bonus if done by December 12, 2022)"
13+assignee = ["Quartus"]
1414grant_id = "B0164"
15−champion = "Holium"
16−completed = false
15+champion = ["Holium"]
16+completed = true
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0164&prefill_Grant+Name=Trove"
1818+++
1919
@@ -69,9 +69,13 @@ A set of roles will be mapped to each action as below:
6969
7070Holium will work with the developer(s) to provide frontend support, but the team working on this bounty will be responsible for frontend implementation.
7171
72−## Milestone 1: 2 stars ($4k bonus if done by Assembly)
72+## Milestone 1: 4 stars ($4k bonus if done by December 12, 2022)
7373
74−Have a working file eHave a working file explorer app that can find files, transfer files, and drag and drop.
74+- Have a working file explorer app that can find files, transfer files, and drag and drop.
75+
76+- Have recursive, per-folder, forced-nesting, permission sets for the operations described in **Permissions** above.
77+
78+- Produce material contributions towards a frontend library to assist developers in integrating with Holium Spaces. **(Additional $4k bonus)**
7579
7680For the milestone to be completed, the app must be approved by Holium and it must be hosted for distribution on Holium's app star (as well as your own if desired).
7781
content/grants/urbit-forms.md → content/grants/2022/urbit-forms.mdrenamed+5−4
@@ -10,13 +10,14 @@ grant_category = ["App Dev"]
1010[extra]
1111image = ""
1212description = "Create forms and surveys with multiple question types"
13−reward = "2 stars"
13+reward = "1 star"
1414assignee = ["~nallux-dozryl"]
15−champion = "~lagrev-nocfep"
15+champion = ["~lagrev-nocfep"]
1616grant_id = "P0110"
17−completed = false
17+completed = true
1818canceled = false
1919link = ""
20+deliverable = "~donpub-datdux/forms"
2021
2122+++
2223
@@ -235,7 +236,7 @@ Below all that are the questions itself. At the bottom of the survey, there is a
235236 - multiple choice grid (select many)
236237 - datetime
237238
238−### Milestone 2 - 1 Star
239+### Milestone 2 - 1 Star - *Cancelled as grantee got a full time job working on Urbit*
239240- Completion: 11 July 2022 (1 month)
240241- Improved front-end
241242- CSV export
content/grants/2022/urbit-interface-framework.mdnew file+88
@@ -0,0 +1,88 @@
1++++
2+title = "Urbit Interface Framework"
3+date = "2022-08-24"
4+
5+[taxonomies]
6+grant_type = [ "Proposal" ]
7+grant_category = [ "Other" ]
8+
9+[extra]
10+image = ""
11+description = "Develop framework for alternative urbit web browser interface"
12+reward = "5 stars"
13+champion = ["~nocsyx-lassul"]
14+assignee = ["~nortex-ramnyd"]
15+grant_id = "P0100"
16+completed = false
17+canceled = false
18++++
19+
20+Proposal to develop web application creation tooling and framework in hoon following [thick stateful server single-page application architecture](https://en.wikipedia.org/wiki/Single-page_application#Thick_stateful_server_architecture).
21+
22+The framework is abstracted into a library that is used by a gall agent. The gall agent defines the application's data model and state controller. View model is defined separately from the agent. This ensures that agent api remains as is and, if needed, agent could implement multiple different view/UI models, e.g some other UI framework that is targeting different kind of device instead of web browser. It also means existing agents can plug in the view model defined with this framework without making changes to agent data and controller model.
23+
24+Being a SPA, in-app links and navigation is intercepted: DOM patching and history api is used instead. In-app navigation is handled by a router in which URL paths are mapped to UI states, either strucutred as separate pages but could also be more granular (i.e. some UI state might only change part of current document not the whole document).
25+
26+The view model should be defined using sail components. Sail components abstract view model into splitted subviews, which store their own internal state and controller. Component's controller is conceptually similar to agent's controller (on-poke arm), it receives [mark vase] and produces list of card:agent:gall and the component with possible internal state modification. `+on-init` in called when component is going to be mounted to DOM. At this arm, a card needs to be sent that declares which browser events this component expects to receive.
27+
28+```
29+++ sail-component
30+ $_ ^|
31+ |_ [props children bowl:sail]
32+ ++ on-poke |~([mark vase] *(quip card:agent:gall _^|(..on-poke)))
33+ ++ on-init *(quip card:agent:gall _^|(..on-poke))
34+ ++ manx *^manx
35+ --
36+```
37+
38+Component's on-poke arm receives from browser user interaction events (DOM events) and handles these accordingly, by emitting cards and/or modifying state.
39+
40+In case agent's state or component's internal state gets modified at on-poke call, a view patch is sent to browser. The view patch is an html string representing the component(s) whose state (and thus their sail template at `+manx` which interpolates state) got modified.
41+
42+The patch is then applied in the application's javascript context with diffHTML.
43+
44+The view model declares component tree in sail syntax:
45+
46+```
47+:: component1, component2 are imported from some path ::
48+:: foo, boo are passed in from agent
49+;div#root
50+ ;component1(prop1 (p foo));
51+ ;component2
52+ =prop1 (p foo)
53+ =prop2 (p boo)
54+ ==
55+==
56+```
57+
58+gate `+p` produces jammed atom that is encoded to tape since manx properites must be tapes. decoding is handled by the library and components receive nouns that they have to normalize to their own needed structures (using `;;(mold noun)`)
59+
60+---
61+
62+**milestones**
63+
64+_sail component abstraction layer and framework base logic_
65+
66+2 stars
67+
68+the base of the framework is written in scope of this milestone. this is the base functionality of writing sail components and attaching the resulting UI logic to agent.
69+
70+_routing and navigation layer_
71+
72+1 star
73+
74+- implementing url mapping to view states.
75+
76+- implementing history api.
77+
78+_hot reloading_
79+
80+1 star
81+
82+implementing transition logic when components source code changes
83+
84+_documentation and example agent_
85+
86+1 star
87+
88+documentation about using this framework and example usage in form of a todo app
content/grants/urbitswap.md → content/grants/2022/urbitswap.mdrenamed+4−2
@@ -10,10 +10,12 @@ grant_category = [ "App Dev" ]
1010image = ""
1111description = "Host a Uniswap frontend trading UI on your urbit"
1212reward = "1 star"
13−assignee = [""]
13+assignee = ["~togtyr-roplux"]
14+champion = ["~dinleb-rambep"]
1415grant_id = "B0155"
15−completed = false
16+completed = true
1617work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0186&prefill_Grant+Name=Uniswap"
18+deliverable = "~maptyl-lapsyl/uniswap"
1719+++
1820
1921# Overview
content/grants/value-articles.md → content/grants/2022/value-articles.mdrenamed+2−2
@@ -8,8 +8,8 @@ grant_category = ["Other"]
88image = ""
99description = "Create in-depth valuation models for Urbit address space, network effects, and commercial utilization"
1010reward = "$5000"
11−assignee = [""]
12−champion = "~simfur-ritwed"
11+assignee = ["~ripnyt-ripnyt", "~nilrun-mardux", "~bacfur-bitfed", "~hodreb-racdem"]
12+champion = ["~simfur-ritwed"]
1313id = "B0156"
1414completed = false
1515work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0156&prefill_Grant+Name=Urbit%20Value%20Longform%20Writing%2FAnalysis"
content/grants/volt-ui.md → content/grants/2022/volt-ui.mdrenamed+3−1
@@ -10,11 +10,13 @@ grant_category = [ "App Dev", "Other" ]
1010image = ""
1111description = "An app to serve the UI to urbit's lightning wallet"
1212reward = "1 star"
13−mentor = "~dasrun-fadben"
13+mentor = ["~dasrun-fadben"]
1414assignee = ["~mipsun-diflex"]
1515grant_id = "A0152"
1616completed = false
1717cancelled = false
18+link = "~pindet-timmut/urbitcoiners"
19+deliverable = "~mister-dister-dozzod-dozzod/bitcoin"
1820work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0152&prefill_Grant+Name=Lightning%20Wallet%20User%20Interface"
1921+++
2022
content/grants/2022/whom.mdnew file+70
@@ -0,0 +1,70 @@
1++++
2+
3+title = "Whom: profile and contacts manager"
4+date = "2022-08-25"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "A dedicated contacts app to store contact info that other apps can programmatically access"
13+reward = "3 stars"
14+assignee = ["~rivmud-fabwen"]
15+champion = ["~palfun-foslup"]
16+grant_id = "P0171"
17+completed = true
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Rationale
24+When I've been to in-person social events like Assembly or other meetups, I was excited to meet new people, but frustrated that I couldn't easily keep track of everyone I met. While I could add other users by `@p` in `%pals`, the tagging system doesn't lend itself to storing contact info in a structured way, like names, emails, Twitter handles, etc. Also, even at Urbit events, many people I met didn't have planets yet! I could add them into my phone's contacts or as a Web 2 social contact, but now my contacts are split between multiple disconnected sources.
25+
26+Urbit needs more robust way of connecting people and representing who they are. In short, I should be able to broadcast who I am with a profile, and I should be able to keep an organized list of contacts with my friends' profiles.
27+
28+While `%pals` is a great tool for defining a list of friends, its tagging feature was not meant to represent structured contact data. The `%pals` frontend states
29+> Applications could make use of tags for grouping content, but should not change their core behavior based on the presence or absence of specific tags.
30+
31+A dedicated contacts app needs to be able to store contact info in a way that other apps can programmatically access specific info about a contact. For example, if I knew somebody in real life, I could enter their real name into my contacts app, and Groups could display their real name instead of their @p in chats.
32+# Overview
33+`%whom` would be an app that lets me manage a list of contacts.
34+Each contact has a variety of fields that are common in desktop/phone/Web2 contact apps (name, notes, email, phone, Twitter, GitHub, etc).
35+If a contact is another Urbit user with `%whom` installed, the contact will also contain info they shared about themselves (their profile).
36+## User stories
37+1. As a user, I want to add people I know to a list of contacts, whether my contact uses Urbit or not.
38+2. As a user, I want to view and edit info about my contacts through a frontend.
39+3. As a user, I want to have a shareable profile with a variety of fields, like name, email, phone, Github, Twitter, etc.
40+4. As a user, I want to see other users' profiles in my contacts list, in addition to the info I entered about them.
41+5. As a user, I want my contacts to be updated when another user updates their profile.
42+6. As a user, when one of my non-Urbit contacts gets a planet, I want to be able to convert them to an Urbit contact.
43+7. As a user with `%pals`, I want my pals to be added to my contacts list automatically.
44+8. As a user with `%pals`, I want to be able to add my contact as a %pal with a button click.
45+9. As a user with `%pals`, I want some info on my profile to be public, but I only want to share more personal info with users I trust (pals).
46+10. As a developer of another app, I want to be able to programmatically access specific fields from contacts.
47+# My background
48+I'm a professional fullstack software engineer and I've been active on Urbit since 2019. I operate the star ~holnes and have onboarded a few of my friends. I graduated Hoon School in 2020, attended Assembly and a few local meetups, and completed the Studio email apprenticeship with Tirrel earlier this year. I've had a great experience working with Hoon and Gall so far, and am eager to build more apps.
49+# Milestones / Estimates / Compensation
50+## Milestone 1 - Contacts
51+Completed by: Sep. 1
52+- Compensation: 1 star
53+- Goals:
54+ - Users can create and manage contacts
55+ - Users can view and edit contacts in a working frontend
56+## Milestone 2 - Profiles
57+- Completed by: Sep. 22 (Assembly '22)
58+- Compensation: 1 star
59+- Goals:
60+ - Users can create public profiles
61+ - Users can view public profiles in the frontend
62+ - Contacts contain public info from profiles
63+## Milestone 3 - Pals and Privacy
64+- Completed by: December
65+- Compensation: 1 star
66+- Goals:
67+ - Pals are automatically added as contacts
68+ - The frontend shows which contacts are pals
69+ - Users can click a button to send a contact a pal request
70+ - Users can restrict visibility on their profile, so only pals can see certain fields
content/grants/2023/aera.mdnew file+50
@@ -0,0 +1,50 @@
1++++
2+
3+title = "Aera"
4+date = "2023-06-08"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "A decentralized, subjective reputation graph protocol."
13+reward = "8 Stars + Bonus"
14+assignee = ["~talwet"]
15+champion = ["~dalten"]
16+grant_id = "P0276"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# A new Aera of reputation
23+
24+Aera is an essential missing piece of Urbit infrastructure which will bring self-sovereign trust to the platform. This will enable application developers to manage, filter, curate, and otherwise manage context dependent trust parameters within their products. Additionally, the fully formed version of Aera will include an interface for users to view and understand the shape of their trust graph. Aera makes it possible to build applications that can’t be built using the current web stack. For a more detailed view of the Aera value prop and future product updates, please visit https://quartus.co/aera
25+
26+# Team
27+Aera is a project consisting of many Urbit community members. It is the brainchild of ~rabsef-bicrym, but will also include the following key contributors:
28+- ~litlep-nibbyt, working on hoon agents
29+- ~normul-postem, writing frontend interfaces
30+- ~litneb-maltyp, designing graphical user interface & visual content
31+
32+Additionally, the project has a variety of other advisors and participants, including ~sarlev-sarsen, ~sicdev-pilnup, ~sogrum-savluc, and ~datnut-pollen. For anyone interested in participating, download the %aera desk to learn more: /1/desk/~dister-dozzod-dalten/aera
33+
34+# Milestones & Compensation
35+This proposal is going to be partially funded by the Urbit Foundation, both by a $10,000 direct commitment, as well as a grant of 8 stars to be released along the below milestones. Additionally, Aera will also grow to include a crowdfunding campaign using %fund to support ongoing development efforts from the Urbit community. Contributors will recieve early reputation scores within the resulting reputatation graph, as well as early access to developer resources and integration support. Funds will be held in escrow by the ~dalten collective, to be paid out to contributors upon milestone completion as determined by the members of the collective.
36+
37+## Milestone 1: Initial Research and Mathematical Modelling - $10,000
38+Quartus will conduct initial research efforts to understand implementation hurdles and ideal mathematical models for the shape of the aera agents and ‘trust-reduction algorithm’. This work will be released on an ongoing basis to the Aera group, hosted by ~dalten. Bi-weekly meetings will also be held and made accessible to campaign funders.
39+
40+## Milestone 2: Agent and Library Concept Creation - 2 stars
41+Quartus will begin development of the %aera agents and library and will release them to donors for feedback. Participants will receive a chance to provide feedback on agent architecture and use case requirements.
42+
43+## Milestone 3: Release Candidate Available to Developers for Feedback - 2 stars
44+Whitelisting of select developers, including all donors, for downloading of the %aera desk, including fully functioning agents and a working library. Participants will receive a chance to provide feedback on specific implementation details.
45+
46+## Milestone 4: Final Library and General Availability to Urbit Network - 2 stars
47+Developer feedback integrated into Milestone 3 release candidate and final library released to developers along with documentation. Quartus will work with donors through onboarding sessions that will guide developers through the integration of Aera with an urbit application. Additionally, the application will be made available to the network such that end users will be able to experience the product functionality via an example integration in %fund.
48+
49+## Milestone 5: Full Release to the network with End User GUI - 2 stars
50+Quartus will develop a frontend experience for users to explore their own view of the Aera graph. This GUI will include views of the users own ship, as well as their understanding of the nodes to which they are connected.
content/grants/2023/app-metrics.mdnew file+74
@@ -0,0 +1,74 @@
1++++
2+
3+title = "Success Metrics for Urbit Apps"
4+date = "2023-02-09"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Success Metrics for Urbit Apps"
13+reward = "5 Stars"
14+assignee = ["~bacwyl-samweg"]
15+champion = [""]
16+grant_id = "P0235"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Description
23+
24+The current absence of success metrics for Urbit apps makes it challenging for developers to determine the reach and impact of their software. Without a central app store, it is difficult to obtain information on the number of downloads or daily active users for a given application. This proposal aims to address this problem by providing developers with low-level access to the number of downloads and higher-level tools to facilitate the privacy-compliant collection of daily active user metrics. This will provide valuable insights for developers and support informed decision making for urbit app development.
25+
26+# Milestones and Compensation
27+
28+## Milestone 1 - Surface App Downloads Data
29+
30+Create access to the total set of users who are synced to a local desk. This currently represents the total userbase of an app, since almost all apps on urbit are distributed from a single source. It could also be useful for other purposes, such as the ability to anticipate congestion when shipping an OTA.
31+
32+There is already [an open PR](https://github.com/urbit/urbit/pull/6136) for this milestone.
33+
34+Reward: 1 Star
35+
36+## Milestone 2 - Collect App Downloads/Time
37+
38+Create an agent that periodically records the data from milestone 1 for locally published apps. This represents growth data, or how many ships-per-day are downloading an app. It’s helpful to visualize this as a multiple line graph. For example, a developer can see the point in time when App A surpasses App B in downloads.
39+
40+The state of the agent would be something like `(map app-desk=term [users=(set ship) growth-data=(map time number-of-users=@ud)])`
41+
42+The agent should expose a local scry endpoint for this data that is available as CSV so that developers can easily export and analyze.
43+
44+Reward: 1 Star
45+
46+## Milestone 3
47+
48+### Package and Distribute
49+
50+When milestone 2 is completed, it can immediately be published as an urbit app that developers can |install to their distributor ships. Further milestones can be incremental improvements to this app. The app must be stable for initial release and available for at least the following few months. The codebase will be open sourced with sufficient documentation for developers to install manually. The app will be fully workable from the dojo, and will not depend on a javascript frontend.
51+
52+### Collect Daily Active Users
53+
54+This milestone can be considered complete when app developers can optionally collect ‘daily active users’ without having to intrude on privacy, and without having to reimplement code specifically for this purpose. For this milestone to be complete, some solution to this problem has to be made available to app developers. This code will also need to be open sourced and sufficiently documented. The exact nature of this solution has not yet been determined, but it will most likely conform to the following architecture.
55+
56+### Architecture
57+
58+A central, developer-hosted poke endpoint where logs can be sent from user agents.
59+
60+1. Bob installs :app-metrics on ~dister
61+
62+2. He can use this agent to access milestone 1, 2 data for his apps
63+
64+3. He can optionally add a wrapper agent to his apps to send some logs to ~dister:app-metrics
65+
66+ a. This requires some self-poke to be added to the inner-agent which will be ignored by the inner-agent but caught by the wrapper agent. The wrapper will then send a poke to the central :app-metrics agent, indicating user activity. This poke should be added in a place that indicates real user interaction, such as opening a frontend subscription or sending a DM.
67+
68+ b. To avoid creating too much network activity, the wrapper agent will send a maximum of one poke per day, just to indicate that the user used the agent that day.
69+
70+4. Users can opt-out by setting a boolean in the wrapper agent.
71+
72+5. Daily-active-users data can now be scry’d as a csv file from the central agent.
73+
74+Reward: 3 Stars
content/grants/2023/blog-updates.mdnew file+64
@@ -0,0 +1,64 @@
1++++
2+title = "%blog Quality of Life Improvements"
3+date = "2023-03-17"
4+
5+[taxonomies]
6+grant_type = [ "Apprenticeship" ]
7+grant_category = [ "App Dev" ]
8+
9+[extra]
10+image = ""
11+description = "%blog Quality of Life Improvements"
12+reward = "1 star"
13+mentor = ["~dachus-tiprel"]
14+assignee = ["~foddur-hodler"]
15+completed = false
16+canceled = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0250&prefill_Grant+Name=%25blog%20Quality%20of%20Life%20Improvements"
18++++
19+
20+## Blog QOL Upgrades
21+
22+%blog Apprenticeship is a userspace application apprenticeship focused on experiential learning in publishing on Urbit. The three main quality of life upgrades `~dachus-tiprel` would like are:
23+- Subscribe to someone’s ship to see when they have published a new post
24+- Password protected posts
25+- Export-Files / Import-from-Backup pokes
26+
27+
28+## Apprentice Expectations
29+
30+Apprentice is familiar with %blog, has gone through hoon school, has a worked with a gall app before (both frontend and backend).
31+
32+
33+## Team
34+
35+The apprentice will work with `~dachus-tiprel` directly. They will participate in an initial "kick-off" call to talk through the user stories and the expected implementation, and will proceed with weekly or biweekly (at the apprentice's preference or need) meetings with `~dachus-tiprel` thereafter.
36+
37+
38+## Deliverable
39+
40+3 separate production-ready pull requests to the %blog hoon repo and %blog-ui repo each of the requested features.
41+
42+
43+## User Stories
44+
45+As someone integrating with %blog I want to
46+- Subscribe to a %blogger and be notified whenever they publish a new post
47+As a %blogger I want to
48+- Password protect my posts to limit access
49+As a %blogger about to breach I want to
50+- Export all my my blogs into a file
51+- Breach my ship
52+- Reload all of my blogs/themes/drafts exactly as they were
53+
54+
55+## Implementation Notes
56+
57+`~dachus-tiprel` is amenable to suggestions of strategies from his apprentice as to the nature of the implementation of this feature, particularly in the Front-End presentation. We have a suggestion for the general implementation details on the backend, but are nonetheless open to input:
58+- Subscriptions should be done using the new sss.hoon library
59+- Password protection will likely be done using some sort of sail page that redirects to the post upon a correct POST to %blog
60+
61+
62+## Schedule and Compensation
63+
64+The %blog apprenticeship should take no longer than 3 months, but is likely executable within a month. The apprentice will recieve 1 star upon successful completion of the apprenticeship.
content/grants/2023/bridge-grab-bag.mdnew file+35
@@ -0,0 +1,35 @@
1++++
2+
3+title = "Bridge Issue Grab Bag"
4+date = "2023-04-17"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "Close three issues from the Bridge github repo."
13+reward = "2 stars"
14+assignee = ["~sicrep-docrem"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "B0260"
17+completed = false
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0260&prefill_Grant+Name=Bridge%20Issue%20Grab%20Bag"
20+
21++++
22+
23+## Overview
24+
25+The Urbit Foundation monitors existing and new issues in the Bridge codebase to identify issues that can be addressed by community contributors. Issues are selected to require minimal organizational context so that contributors can jump right in.
26+
27+This bounty will be awarded to someone who closes any three of the issues labeled community contribution in the [Bridge](https://github.com/urbit/bridge/issues?q=is%3Aissue+is%3Aopen+label%3A%22community+contribution%22) github repo.
28+
29+The ideal contributor will have a command of JavaScript (specifically React) as well as experience with Web3/ETH front end development. The latter includes setting up a local ETH testnet and deploying test contracts. Familiarity with the Urbit stack, specfically the [Azimuth PKI](https://github.com/urbit/azimuth) and the [L2 roller system](https://developers.urbit.org/reference/azimuth/l2/layer2) will also come in handy.
30+
31+For clarification on any of the issues, please mention [@vvisigoth](https://github.com/vvisigoth) or the issue filer in the issue comments.
32+
33+## Compensation
34+
35+2 Stars
content/grants/2023/community-meetups.mdnew file+37
@@ -0,0 +1,37 @@
1++++
2+title = "Community Meetup"
3+date = "2023-04-06"
4+
5+[taxonomies]
6+grant_type = [ "Bounty" ]
7+grant_category = [ "Community" ]
8+
9+[extra]
10+image = ""
11+description = "Earn stars by building a local urbit community"
12+reward = "1 star"
13+assignee = [""]
14+grant_id = "B0165"
15+champion = ["~dalweb-donfun"]
16+completed = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0165&prefill_Grant+Name=Meetup%20Bounty"
18++++
19+
20+# Requirements
21+- Meetups should be geographically based.
22+- You must host a total of six meetups, with a targeted cadence of once a month.
23+- Meetups must be publicized and include a web presence like meetup.com, and should be actively promoted via social media, in-person recruitment, flyers, a website, etc. If you need a signal boost, email thomas@urbit.org.
24+- Create and admin an Urbit group for your community to which all meetup attendees will be invited. This group should be actively maintained with info about upcoming events, copies of past presentation materials, and any other related meetup content.
25+- Share all the materials you generate in service of your meetups like, presentations, flyers, FAQs or anything else in ~siddef/uf-meetups.
26+- Every meetup must be publicized on the [Events](https://urbit.org/events) section on urbit.org via a commit to the urbit.org [github repo](https://github.com/urbit/urbit.org).
27+- Your community should have a home on the [community section](https://urbit.org/ecosystem?type=communities) of our ecosystem page. You can add this to the website with a commit to the urbit.org [github repo](https://github.com/urbit/urbit.org). If you have never submitted a pull request on github before, let us know and we will teach you how.
28+- Write a short paragraph about every meetup including: pictures of the meetup, 50-200 words description of every meetup and the attendee statistics of the meetup. At the end of your grant you can send this as one report to thomas@urbit.org for completion of your grant.
29+# Encouraged Features
30+- Semi-regular presentations that introduce Urbit to newcomers, help members boot a planet, or introduce the more technical side of urbit are strongly suggested.
31+- Having a collection of recommended groups & apps to which you can direct meetup attendees, such that they can begin to explore the Urbit network.
32+- As one of the main goals of meetups is to get people building on Urbit, once your meetup gains some traction, consider looking into writing a proposal for a grant on which members of your meetup can collaborate.
33+- While the specific requirements of the meetup bounty can be summarized as "run a regular meetup", the overarching goal is to build a local community and onboard people to Urbit. You should become a true champion of your local urbit community who helps people find their own path on urbit, whether it is signing up for a course, a grant or even working for a company in the ecosystem. It's up to you to find the potential of the attendees.
34+# Application process
35+After applying to this bounty, set-up a call with ~dalweb-donfun who will assess the soundness of your strategy and run you through the requirements of this bounty. If everything checks-out you are good to go.
36+# Compensation
37+- Upon the completion of six meetup events and the associated meetup report, one star will be paid out to the organizer.
content/grants/2023/did-rfp.mdnew file+26
@@ -0,0 +1,26 @@
1++++
2+
3+title = "Build a DID Resolver for Urbit"
4+date = "2023-04-12"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Design and implement a DID resolver to let Urbit interoperate with protocols like AT/BlueSky"
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1001"
17+completed = false
18+canceled = false
19+
20++++
21+
22+The launch of [BlueSky](https://blueskyweb.xyz/) and the [AT protocol](https://atproto.com/guides/identity) has brought renewed attention to a W3C standard called [DIDs](https://www.w3.org/TR/did-core/#introduction) or Decentralized Identifiers
23+
24+Decentralized identifiers (DIDs) are a type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject as determined by the controller of the DID. In contrast to typical, federated identifiers, DIDs have been designed so that they may be decoupled from centralized registries, identity providers, and certificate authorities. Urbit ID is a good fit with this standard, since the Urbit namespace already conforms with many aspects of the specification.
25+
26+Included in the standard is a specification for a [resolver](https://www.w3.org/TR/did-core/#dfn-did-resolvers), a function that maps a READ from an identifier to its accompanying document. Build an application layer in Urbit that uses a ship to resolve a DID to a document either on the Urbit network or outside it.
content/grants/2023/elm.mdnew file+68
@@ -0,0 +1,68 @@
1++++
2+
3+title = "Elm"
4+date = "2023-06-08"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "Making Elm the frontend technology for Urbit"
13+reward = "5 Stars + Bonus"
14+assignee = ["~racfer-hattes"]
15+champion = ["~rovnys-ricfer"]
16+grant_id = "P0275"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Description
23+
24+I think Elm is a great language for developing frontends. The Elm architecture is conceptually very similar to how %gall agents are structured.
25+
26+Goals:
27+
28+1. Remove the need to convert to and from JSON to interact with Urbit from Elm
29+2. Make interacting with Urbit from Elm as painless as possible
30+
31+To eliminate the need to convert through JSON Elm needs to support serializing and deserializing jammed nouns.
32+
33+For potential portability reasons Elm libraries are not allowed to have JS FFI. This means that we need to implement as much as possible in pure Elm.
34+
35+# Milestones and Compensation
36+
37+## Milestone 1: Jam and Nouns
38+
39+Reward: 2 Stars
40+
41+Deliverables:
42+ - An Elm library that implements `++jam` and `++cue` in Elm.
43+ - An Elm library for manipulating Nock Nouns and converting Elm data structures and type to and from Nock Nouns.
44+
45+## Milestone 2: Noun Channels
46+
47+Reward: 1 Star
48+
49+Deliverables: An Elm airlock library that supports subscriptions and pokes encoded as jammed Nouns. The library should be designed to be as ergonomic as possible.
50+
51+## Milestone 3: Documentation and Project Template
52+
53+Reward: 1 Star
54+
55+Deliverables:
56+ - Good documentation for resulting the package + a set of tutorials that cover some tricky bits.
57+ - A git repo with all of the boilerplate required to communicate with Urbit. This repo is intended to be used by ASL students to bootstrap their project frontend.
58+
59+## Milestone 4: SSS
60+
61+Reward: 1 star
62+
63+Deliverables: An Elm airlock library that supports Solid-state subscriptions.
64+
65+## Bonus
66+
67+Upon successful completion of project, the contributor will also receive a 6K USDC bonus funded by Vaporware
68+
content/grants/2023/email-stella-fixa-rfp.mdnew file+29
@@ -0,0 +1,29 @@
1++++
2+title = "Build an Email Toolchain for Urbit"
3+date = "2023-05-11"
4+
5+[taxonomies]
6+grant_type = ["RFP"]
7+grant_category = ["App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Produce an Urbit-side client for sending E2EE email"
12+reward = "TBD"
13+assignee = [""]
14+champion = [""]
15+grant_id = "P1001"
16+completed = false
17+canceled = false
18++++
19+
20+Email is the glue for much of the legacy web. While many of us share an aversion to the proliferation of email, the ability to tie email to Urbit identity will enable users to unify their control over their digital life more than is currently possible.
21+
22+There are a lot of ways such a project could shake out.
23+
24+- The gold standard would basically be run-your-own-ProtonMail from Urbit.
25+- One could also build a CLI email agent, like [Mutt](http://www.mutt.org/). This would be a good start.
26+- Implementing [JMAP](https://en.wikipedia.org/wiki/JSON_Meta_Application_Protocol) should be feasible as well, and simpler than IMAP/SMTP.
27+- The minimum viable product would be a front-end on Mars for a connected email server process on Earth, including a full user story on how to operate this without too much tetchy sysadmin work required.
28+
29+Anything in between would also be acceptable. There are some interesting crossovers possible as well, such as sending email to `@p` or via the `user@sampel-palnet.arvo.network`.
content/grants/2023/eyre-noun-channels.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+title = "Finishing Touches to Eyre Noun-Based Channels"
3+date = "2023-01-26"
4+
5+[taxonomies]
6+grant_type = ["Proposal"]
7+grant_category = ["Core Dev"]
8+
9+[extra]
10+image = ""
11+description = "Finishing Touches to Eyre Noun-Based Channels"
12+reward = "2 stars"
13+assignee = ["~polwex"]
14+grant_id = "P0229"
15+champion = ["~palfun-folsup"]
16+completed = true
17+canceled = false
18++++
19+
20+## Description
21+
22+Any Urbit developer who has coded a complex frontend will tell you that, by far, the most tedious part of making Urbit apps is JSON.
23+
24+Communication between Hoon backends and JavaScript frontends on Urbit is done currently only using JSON data, which has to be manually encoded and decoded at the backend using Hoon's JSON codec functions. Eyre communicating solely through JSON also causes performance costs which can be serious when the JSON data gets large.
25+
26+Thankfully there's a solution to this problem, and it's already more than half done. ~palfun-folsup pushed this draft PR a few months ago https://github.com/urbit/urbit/pull/5877.
27+
28+It just needs some polish. This grant proposal offers to procure it.
29+
30+As set up in the Github PR, in this grant we will:
31+
32+1. Remove the `jsbn` library dependency, and move all related logic in the `nockjs` files to JavaScript's new native BigInt type, or the `big-integer` library (which is mostly the same in practice).
33+
34+2. Add TypeScript typing to all the nockjs logic, wherever possible.
35+
36+3. Other fixes we find along the way to make sure the PR is mergeable and ready for use in Urbit apps.
37+
38+## Milestones & Compensation
39+
40+Expected completion: March 2023
41+
42+Reward: 2 stars
content/grants/2023/generator-doccords.mdnew file+46
@@ -0,0 +1,46 @@
1++++
2+title = "Doccord Compliant Comments in all Generators"
3+date = "2023-01-31"
4+
5+[taxonomies]
6+grant_type = ["Bounty"]
7+grant_category = ["Core Dev"]
8+
9+[extra]
10+image = ""
11+assignee = ["~napnyl-nortuc"]
12+description = "Adapt the comments in the default generators to take advantage of the new doccord features."
13+reward = "1 star"
14+grant_id = "B0231"
15+completed = false
16+canceled = false
17+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0231&prefill_Grant+Name=Doccord%20Compliant%20Comments%20for%20All%20Generators"
18++++
19+
20+## Overview
21+
22+The base desk comes with a variety of generators and threads that are useful for debugging and development. Documentation and usage guidance for these is scattered between inline comments (accessible via the `+help` generator) and [operators.urbit.org](https://operators.urbit.org/manual/os/dojo-tools) We propose to take advantage of the [newly released doccords](https://groups.google.com/a/urbit.org/g/dev/c/iqT0wgbFkPA) feature to consolidate the documentation and provide an introduction to the doccords utility for users.
23+
24+## Implementation
25+
26+For every "dojo tool" covered in [the docs](https://github.com/urbit/operators.urbit.org/blob/master/content/manual/os/dojo-tools.md), move the documentation into the source code in accordance with the doccord [style guide](https://github.com/urbit/urbit/blob/develop/pkg/arvo/lib/deco.hoon).
27+
28+Rewrite the `+help` generator to display the relevant doccords.
29+
30+Currently you need to do the following to see inline doccords.
31+
32+```
33+=file -build-file %/path/to/file/hoon
34+# file
35+```
36+
37+This should be improved to be:
38+
39+```
40++help %example-generator
41+> formatted comments
42+```
43+
44+## Payment
45+
46+1 Star
content/grants/2023/gh-concierge.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+
3+title = "Github Support Concierge"
4+date = "2023-02-03"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "The Github concierge will triage Urbit support issues that come in through Github."
13+reward = "2 Stars"
14+assignee = ["~larryx-woldyr"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "B0233"
17+completed = false
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0233&prefill_Grant+Name=Github%20Support%20Concierge"
20+
21++++
22+
23+## Overview
24+
25+The Github concierge will triage Urbit support issues that come in through github. Some of these issues are routine and can be handled in the thread, whereas occasionally complex issues arise that need to be escalated to the right people. Ideal candidates will also help synthesize support data to inform product feature work and documentation.
26+
27+## Responsibilities
28+
29+- Triage support issues in github
30+- Write a weekly digest of issues addressed
31+- Attend a recurring meeting with Foundation staff
32+
33+## Qualifications
34+
35+- Helpfulness
36+- Familiarity with running urbit in a variety of environments (cloud server, laptop)
37+- Ability/interest in synthesizing support data and recommending new features or documentation
38+- Dilligence
39+
40+## Compensation
41+
42+2 Stars for 3 months of work, at which time the agreement can be renewed.
content/grants/2023/git-on-clay.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+
3+title = "Implement a Git server on Urbit"
4+date = "2023-06-01"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Implement a Git server capable of hosting desks as repos"
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1001"
17+completed = false
18+canceled = false
19+
20++++
21+
22+A Git server backend would open up the use of Urbit ships to interface with remote developers and resources.
23+An Urbit implementation of Git would not have to implement all of the features that a Git server typically
24+expects, merely the ability to interface through clone, fetch, and merge operations and through the https and git
25+protocols. (Obviously sufficient internal representations of Git objects, diffs, and so forth are necessary as well.)
26+
27+Having an Urbit-native Git server-side representation has the potential to revolutionize the Urbit developer
28+experience. Not only would it become possible to synchronize Clay and host OS files through `git`, but Urbit would
29+also have direct access to the wealth of Git-based resources on the broader web. More than this, **Urbit would
30+immediately become capable of being a fully decentralized Git repository system.**
31+
32+A solution could be built directly in userspace or on top of Clay. If Clay is used, then there would need to be a
33+way for an unvalidated desk (no mark validation) to store data prior to use in Urbit, e.g. fed up to a functioning
34+regular desk or read out (via remote scry or otherwise) to the Git-based world. In this case, Git operations would
35+be done at a Unix command line regularly and Urbit would serve as a central repo or distribution point. (This could
36+ease development through the appropriate use of scripts, CI and testing, and hooks.)
37+
38+A fully userspace solution would be viable, as long as it was able to export a Git-compatible representation via the
39+API, and as long as it spoke `https` and `git` at a minimum.
40+
41+(Note particularly that this is not an implementation of `git` on Urbit, but an implementation of a Git repository
42+server. The `git` CLI would encompass a complementary set of concerns and operations.)
content/grants/2023/goals-2.mdnew file+64
@@ -0,0 +1,64 @@
1++++
2+title = "Goals 2"
3+date = "2023-03-20"
4+
5+[taxonomies]
6+grant_type = ["Proposal"]
7+grant_category = ["App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Goals 2"
12+reward = "5 stars"
13+assignee = ["~niblyx-malnus", "~sidlup-havwen"]
14+grant_id = "P0227"
15+champion = ["~datder-sonnet"]
16+completed = false
17+canceled = false
18++++
19+
20+# Main Objectives
21+
22+## Groups Integration (Reward: 2 Stars)
23+- Full association of a pool with a group.
24+ - The pool is public or private in correspondence with the group.
25+ - The pool has the same set of banned/allowed ships as the group.
26+ - All group admins are automatically admins on the pool.
27+ - Members who leave or are kicked from the group are automatically removed from the pool.
28+ - Members who join the group are automatically added to the pool.
29+- Each pool and goal will have an associated note. A note is a piece of markdown used to flesh out the pool or goal in greater detail.
30+- Each pool and goal will have an associated comment section where pool members can comment on the specific details of the goal.
31+- Both notes and comments will be able to link to existing nodes in Groups which will render appropriately. This includes chats, notes, channels, comments, entire groups, and applications.
32+- Both notes and comments will be able to link to existing pools and goals which will render similarly to Groups nodes.
33+- Significant events trigger notifications to be sent via %hark. These include:
34+ - Being assigned to be chief of a goal.
35+ - Being assigned to be in the spawn set of a goal.
36+ - New goals spawned under goals you own.
37+ - Non-actionable goals with no subgoals being left childless for an extended period of time.
38+ - Other events as they emerge and are deemed appropriate.
39+
40+
41+## Sorting/Filtering and Tags/Fields (Reward: 2 Stars)
42+
43+- Tags
44+ - Each goal within a pool can be tagged.
45+ - Everyone can maintain private tags associated with a goal which only they can view.
46+ - Harvested goals can be sorted by tags.
47+ - Tags can be viewed so that all goals associated with them can be seen and explored.
48+- Sorting/Context-based Ordering
49+ - Goals can be sorted by the date of their deadline or kickoff.
50+ - Goals can be re-ordered in the context of their subgoals with a simple dragging mechanism.
51+
52+
53+## Improved UX (Reward: 1 Star)
54+
55+- Shortcuts and quick actions using ctrl
56+- Improved mobile experience
57+- Working poke relays on the frontend
58+- Ability to re-order subgoals with a drag and drop action
59+- Dark mode
60+
61+
62+# Compensation
63+
64+Reward: 5 stars
content/grants/2023/hoon-linter.mdnew file+30
@@ -0,0 +1,30 @@
1++++
2+
3+title = "Hoon Linter"
4+date = "2023-03-21"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = ""
13+reward = "2 Stars"
14+assignee = ["~watter-parter"]
15+champion = ["~rovnys-ricfer"]
16+grant_id = "P0224"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Description #
23+
24+Most languages have some form of "linter" available that reports potentially-problematic code. Typically, such code will successfully compile, but will fail at runtime or produce otherwise undesirable results. Because the code is technically valid, it cannot be rejected by the compiler (at least, not without changing the language spec, which risks breaking existing programs), but we can still warn the programmer that what they are doing is likely to cause problems.
25+
26+I have started work on a "Hoon linter" that serves this purpose. The linter is integrated with %language-server, and can thus report warnings directly in any editor that supports the Language Server Protocol. The linter can also be invoked as a standalone generator. Currently, the linter only checks for duplicate union tags. I would like to add more checks to the linter, such as detecting when a noun is pinned to the subject but never used. There are also a few warts that I would like to eliminate, with guidance from someone more experienced.
27+
28+# Compensation #
29+
30+Reward: 2 Stars
content/grants/2023/hoon-replit.mdnew file+45
@@ -0,0 +1,45 @@
1++++
2+
3+title = "Hoon Grammar and Language Mode for Replit"
4+date = "2023-02-15"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Hoon CodeMirror grammar and language mode for Replit"
13+reward = "1 stars"
14+assignee = ["~ransud-wannus-malbex-lacnyr"]
15+champion = ["Replit"]
16+grant_id = "B0238"
17+completed = true
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0238&prefill_Grant+Name=Hoon%20CodeMirror%20grammar%20and%20language%20mode%20for%20Replit"
20+
21++++
22+
23+# Hoon CodeMirror grammar and language mode for Replit
24+
25+_Note: This is a mirror of [a bounty](https://replit.com/bounties/@masfrost/hoon-codemirror-gram) on the Replit site. Acceptance by the Replit team qualifies you for a bonus Star, to be claimed from the Urbit Foundation._
26+
27+## Project Description
28+
29+Hoon is a programming language used in the Urbit operating system. You can find the grammar specification for Hoon in the official Hoon documentation. You can use the Hoon mode for Emacs and the Vim package for reference: hoon-mode.el and hoon.vim.
30+
31+Replit uses CodeMirror as the editor and we want to add first-class support for Hoon, including syntax highlighting. We have a language mode template available on Replit (please read the README for guidance).
32+
33+We'll publish it as an open source package and credit you.
34+
35+## Acceptance Criteria
36+
37+- Syntax highlighting should match the modes for Hoon in the Emacs and Vim packages
38+- Folding ranges should be added to improve code folding
39+- Should use lezer instead of custom tokenization
40+
41+## Compensation
42+
43+- $162.00 from Replit
44+- 1 Star
45+
content/grants/2023/issue-grab-bag.mdnew file+36
@@ -0,0 +1,36 @@
1++++
2+
3+title = "Urbit Issue Grab Bag"
4+date = "2023-02-15"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Close three issues from the Urbit github repo."
13+reward = "2 stars"
14+assignee = [""]
15+champion = [""]
16+grant_id = "B0239"
17+completed = false
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0239&prefill_Grant+Name=Urbit%20Issue%20Grab%20Bag"
20+
21++++
22+
23+## Overview
24+
25+
26+The Urbit Foundation monitors existing and new issues in the codebase to identify issues that can be addressed by community contributors.
27+
28+This bounty will be awarded to someone who closes any three of the issues labeled community contribution in the [urbit](https://github.com/urbit/urbit/labels/community%20contribution) or [vere](https://github.com/urbit/vere/labels/community%20contribution) github repo.
29+
30+The ideal contributor will have a decent command of hoon and an understanding of the Urbit stack. Some, but not all, issues will require experience with the [Vere runtime](https://github.com/urbit/vere). Issues are selected to require minimal organizational context, making them amenable to open source contributors.
31+
32+For clarification on any of the issues, please mention [@vvisigoth](https://github.com/vvisigoth) or the issue filer in the issue comments.
33+
34+## Compensation
35+
36+2 Stars
content/grants/2023/json-parser-suite.mdnew file+170
@@ -0,0 +1,170 @@
1++++
2+
3+title = "JSON re/parser building suite"
4+date = "2023-02-23"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "JSON re/parser building suite"
13+reward = "2 Stars"
14+assignee = ["~litlep-nibbyt"]
15+champion = ["~lagrev-nocfep"]
16+grant_id = "P0245"
17+completed = true
18+canceled = false
19+
20++++
21+
22+# Overview
23+
24+A set of three generators which will automate a majority of the work involved in writing parsers to and from JSON. One generator will convert a noun directly to its JSON representation, one generator will produce an example hoon parser given an example input JSON, and one generator that will produce an example hoon parser given a JSON schema.
25+
26+
27+
28+# Motivation
29+
30+JSON is the most widely used format for HTTP payloads. Urbit apps which talk to existing web services must send and receive requests formatted in JSON. Additionally, apps with Javascript frontends use the Urbit HTTP API to facilitate communication between the frontend and Urbit.
31+
32+
33+
34+A set of generators which can automate a majority of the work involved in writing parsers to and from JSON would accelerate the pace of app development.
35+
36+
37+
38+# Implementation
39+
40+For the noun to JSON direction, the conversion would be direct: given any input noun, the generator would produce the corresponding JSON. `~rovnys-ricfer` has completed most of a noun to json encoder. The code can be found [here](https://gist.github.com/belisarius222/d22b39ac0fece6e0680db5d60c6595c6). When complete, it will be able to take a noun and its AST and convert it to a json representation. We have identified missing encodings inside of en-dime for the following auras: `%s, %rq, %rh, %rd, %rs, %ub, %uc, %ux, %uv, %uw`. Part of this bounty will involve implementing the json encoding for the missing auras.
41+
42+
43+
44+For the JSON to noun direction, we will implement two generators, one which accepts an example JSON and another which accepts a JSON schema. Both generators will output a cord containing an example hoon parser for the input JSON. The expectation is that the user will use this parser as a starting point for their own. The generators will produce a structurally correct parser for the target JSON. The user may have to modify the parsing rules inside each entry to get their desired result, but the structure of the parser must be correct.
45+
46+
47+
48+To illustrate how we expect these generators to be used, we provide an example below:
49+
50+
51+
52+Given an example json:
53+
54+```
55+
56+[ ~[ %o
57+
58+ p
59+
60+ { [p='id' q=[%s p='1234']]
61+
62+ [p='name' q=[%s p='James']]
63+
64+ [p='contact_number' q=[%n p='4132549899']]
65+
66+ }
67+
68+ ]
69+
70+]
71+
72+```
73+
74+
75+
76+Or a schema:
77+
78+
79+
80+```
81+
82+{
83+
84+ "$schema":"http://json-schema.org/draft-04/schema#",
85+
86+ "title":"User",
87+
88+ "description":"A user request json",
89+
90+ "type":"object",
91+
92+ "properties":{
93+
94+ "id":{
95+
96+ "description":"The unique identifier for a user",
97+
98+ "type":"integer"
99+
100+ },
101+
102+ "name":{
103+
104+ "description":"Name of the user",
105+
106+ "type":"string"
107+
108+ },
109+
110+ "contact_number":{
111+
112+ "type":"number"
113+
114+ }
115+
116+ },
117+
118+ "required":[
119+
120+ "id",
121+
122+ "name",
123+
124+ "contact_number"
125+
126+ ]
127+
128+}
129+
130+```
131+
132+
133+
134+The generator will produce this piece of hoon code as a cord:
135+
136+
137+
138+```
139+
140+++ req-parser-ot
141+
142+%- ot:dejs-soft:format
143+
144+:~ [%id so:dejs:format]
145+
146+[%name so:dejs:format]
147+
148+[%contact_number no:dejs:format]
149+
150+==
151+
152+```
153+
154+
155+
156+
157+
158+# Deliverable(s)
159+
160+1 Generator which can directly convert from noun to JSON.
161+
162+1 Generator that can produce an example hoon parser given an example input JSON.
163+
164+1 Generator that can produce an example hoon parser given a JSON schema.
165+
166+
167+
168+# Compensation
169+
170+2 Stars upon completion of the grant.
content/grants/2023/kNock-property-testing.mdnew file+71
@@ -0,0 +1,71 @@
1++++
2+
3+title = "kNock and Property Tests"
4+date = "2023-04-11"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Executable Semantics of Nock in the K Framework, universal testing and verification"
13+reward = "7 Stars"
14+assignee = ["Runtime Verification, Inc."]
15+champion = ["~rovnys-ricfer"]
16+grant_id = "P0255"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Property Testing for Hoon
23+
24+Hoon currently supports pure unit tests. The tests have no entropy and no inputs. This is of course useful. But functional languages have a history of using QuickCheck and similar frameworks for even more powerful tests. Property testing allows testing across a large input space. It relies on writing more general tests, where the programmer specifies properties of their program which should always hold, regardless of input. A typical example is, after writing a sort function, that the resulting list has the same length as the input list, that it is in fact sorted, and that sorting it again causes no changes. This should hold for any input list, and a QuickCheck-like framework will feed many, many different types of lists to the test to find ways it could break.
25+
26+Apart from a test runner, QuickCheck-like frameworks also require an intelligent and modular input builder. For simple and common inputs – atoms, lists of atoms, and other simple data structures – the input builder should a) be able to generate inputs without any programmer effort, b) try progressively more interesting inputs, such as [], [0], [0 0], [1 0], [0 0 1] etc: starting small and going higher, and c) be able to shrink inputs from a failure: if the list [0 2 2 4 3] fails to sort correctly due to the algorithm picking the middle element as pivot in odd length list and discarding elements identical to the pivot, the shrinking should be able to try progressively smaller inputs until it finds something like [2 2 2] as an example.
27+
28+## Future uses
29+
30+The combination of kNock (https://github.com/runtimeverification/knock) and a property testing library means it's possible to move directly from testing to formal verification. This concept is even mentioned in the original QuickCheck paper (https://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/quick.pdf) (Section 5.2). Runtime Verification has also developed a similar tool for Ethereum smart contracts, using the combination of an existing property testing library and a formal verification framework.
31+
32+In 2022, Runtime Verification developed KEVM-Foundry. Foundry is a testing framework for Solidity: property tests are written in Solidity, compiled to EVM and executed in a fast implementation of the EVM written in Rust. This setup, with property tests written in the same language as the program being tested, allows us to leverage our K semantics (https://kframework.org/) of that language for proving. Property tests – which take randomized inputs and assert properties of programs using those inputs – can be seen as formal program specifications with symbolic inputs. In the case of KEVM-Foundry, we can run the tests directly in K with symbolic inputs.
33+
34+Anecdotally, this has lead to higher quality code – formally specifying your code tends to have that effect – while also making formal verification a more tractable proportion: the human verifier can write correct specifications faster – working in Solidity is easier than writing K specifications directly and being able to fuzz the specifications means trivial specification errors are caught much faster. The same framework can also be used to quickly create execution traces built with the summarizer: simply assert something impossible and set the prover off trying to prove it, exploring all possible branches.
35+
36+More info and demos: https://www.youtube.com/live/staXNgpBjEI?feature=share&t=10820
37+
38+# Deliverables
39+
40+We build, in Hoon, a property testing library. This could be added to the existing -test thread, by inspecting whether a test is a gate, and if so, generate a random sample for it; or the library could be added as a new thread. Reusing the existing thread and having the types of tests co-exist likely makes for the best user experience, compared to having different types of files for different types of tests. The suggested invocation (assuming it is baked into the -test thread) is:
41+
42+`> -test <path> <entropy> ~`
43+
44+For example:
45+
46+`> -test /=landscape=/tests eny ~`
47+
48+The explicit passing of entropy means a failing test is easy to replay with the exact same command (the printout of results will contain the entropy used). If no entropy is passed, 0 is used as entropy.
49+
50+A property test is nothing more than a regular test which is a gate. Running it means generating a sample to the gate. Optionally, a test can have a generator which is responsible for generating its sample: this is necessary, for example, in order to generate arbitrarily large data structures such as trees. It's also useful in order to generate random values more intelligently than the default generator, which can help exercise edge cases. For example, Mitgaard found a 20 year old bug in the data structure Patricia trees by tweaking QuickCheck inputs to hit on otherwise extremely unlikely edge cases (https://janmidtgaard.dk/papers/Midtgaard%3aTFP17.pdf). There are several possible designs for generating arbitrary data -- using arms in the test with names starting in "gen-", specifying them along with the gate for the tests, etc. Which implementation is both easy to use in the default case and powerful in the hands of a power user is something that will require some interaction and community discussion.
51+
52+## Deliverables for property testing in Hoon
53+
54+Implement basic property testing: the user should be able to write a test arm as a gate using the existing test primitives (such as expect-eq, expect-fail), and the test runner should create random samples and repeatedly slam the gate.
55+Implement custom sample generation: the user should be able to specify a gate which produces custom inputs based on given entropy.
56+Implement sample re-generation, allowing the test to put restricting assumptions on the input. For example, an [@ud @ud] sample testing (sub a b) might require (lte b a), and the user should be able to specify this, rejecting any samples which don’t conform, reporting that inputs were discarded without the test failing.
57+Implement sample shrinking, trying to create the smallest possible failure example.
58+Write documentation for the urbit.org website.
59+Write an example property test suite, showing off the various capabilities of the test framework, for some relevant core functionality from the Hoon standard library.
60+
61+# Timeline and Compensation
62+
63+Timeline: 1-2 Months
64+
65+Reward: 7 Stars
66+
67+# Who we are
68+
69+Runtime Verification, Inc. is a specialist in formal verification, auditing and security products for smart contracts and blockchains. We are the main developers and supporters of the K Framework which we are constantly optimizing and extending.
70+
71+Rikard Hjort (~bithex-topnym) is an auditor and verification engineer at Runtime Verification. He’s an MSc in Computer Science from Chalmers University of Technology, the creator of kNock, a Hoon School finisher, and the host of the Urbit Berlin meetups.
content/grants/2023/lick.mdnew file+82
@@ -0,0 +1,82 @@
1++++
2+
3+title = "%lick"
4+date = "2023-02-23"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "An Earth Communication Vane"
13+reward = "7 Stars"
14+assignee = ["~mopfel-winrux"]
15+champion = ["~lagrev-nocfep, ~rovnys-ricfer"]
16+grant_id = "P0244"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Introduction
23+This is a grant for a new vane called %lick. This will act as a way for `Gall` agents to open and close a communication port to Earth processes; enabling communication with various devices and processes ranging from cryptographic hardware keys and dongles, embedded devices speaking on common communication interfaces (UART, SPI, I2C, etc), and IoT connected devices.
24+
25+How %lick will work is best explained with the following usecase:
26+
27+I have a receipt printer that communicates through UART communication. I want it to print out any %rumors I recieve.
28+
29+This usecase will act as an end to end test of the entire system (described below) and allow incremental experimentation until the final product.
30+
31+This grant is split into 4 parts
32+
33+1. Creation of the vane (%lick and lick.c)
34+2. Gall agent (%receipt)
35+3. Earth process which communicates with lick's port and the receipt printer
36+4. Documentation and Tutorial
37+
38+# Vane
39+The Arvo vane exposes an interface for opening and communicating with a host device through Unix IPC ports. `%lick` extends `%galls` pokes to Earth based processes.
40+
41+An agent will be able to `%spin` up a port (type `path`) and `vere` will create it in the piers `.urb/dev` folder. An agent will also be able to `%shut` this port. When an Earth process connects to the IPC port `vere` will send a `%soak` to the `duct` that opened the port. The soak will have the `mark` `%connect`. When the Earth process disconnects `vere` will send a `%soak` with a `%disconnect` `mark`. Whenever an earth process is connected the `gall` agent will be able to `%spit` a noun with the structure `[=mark =noun]`. The `gall` agent should also be able to receive a `%soak` with a similar noun structure.
42+
43+Data being transfered along the IPC port will be `jam`med nouns.
44+
45+
46+# Gall Agent
47+Once the vane and library is tested work will begin on implementing a gall agent that subscribes to the %rumors app by ~paldev. The app will begin by `%spin`ing a port. When an earth process connects to the port it will subscribe to %rumors and on recieving one it will send the correct command for the printer to output it.
48+
49+# Earth Process
50+
51+The Earth process will connect to a given IPC port and wait for a `%print` mark with a `@ta`. It will use `vere`'s eval function to `cue` the noun from the port and parse the hoon pretty printer to correctly print the message.
52+
53+This will be fine for a receipt printer but future work will have to be done to implement a noun library in a given language.
54+
55+# Documentation and Tutorial
56+Documentation of how the vane works is vital to the succuss of it. The benefit of having a working app alongside the vane is to show users how to use the vane. The resulting gall agent and earth process will be written into a tutorial that should allow anyone to replicate this work.
57+
58+
59+# Milestones
60+
61+## Milestone 1: Vane
62+Payment: 3 Stars
63+
64+This milestone includes a working vane that we can send nouns back and forth too.
65+
66+
67+## Milestone 2: Gall Agent
68+Payment: 2 stars
69+
70+This milestone is complete when a user can install `%receipt` and have it print rumors.
71+
72+## Milestone 3: Earth Process
73+Payment: 1 star
74+
75+This milestone is complete when a user can install the app and have the printer print its rumors
76+
77+
78+## Milestone 4: Documentation and Tutorial
79+Payment: 1 star
80+
81+This milestone is complete with the delivery of a documentation and tutorial package.
82+
content/grants/2023/mapping-ids.mdnew file+106
@@ -0,0 +1,106 @@
1++++
2+
3+title = "Mapping Urbit IDs to Web 2 Domains"
4+date = "2023-06-13"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = ""
13+reward = "5 Stars"
14+assignee = ["Web23"]
15+champion = ["~rovnys-ricfer"]
16+grant_id = "P0262"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Overview
23+
24+Urbit has a striking design that makes Urbit IDs scarce, full of utilities and many more new use cases would evolve around them.
25+
26+Urbit IDs also have an analogy with the Unix file systems where hostname resolves to the loopback address of the localhost. Further, an address will be reachable via network packets as well as be accessible via a local naming system.
27+
28+This structure of hostnames mapped with the IP addresses evolved to DNS at large. Urbit is perfectly aligned to evolve Urbit IDs into a true decentralized DNS structure.
29+
30+Domain names run over Web2 stack & current technological stack is in a transition state. For example, Web3 domains, let’s say john.eth or john.crypto are not recognized by the existing DNS and hence the resolvers & browsers. Typing john.eth in Chrome will not take a user to john.eth even if a dAPP is running over john.eth
31+
32+Additionally, with the Decentralized Identifiers (DIDs) evolving as the perfect way to identify the assets over the chain, it becomes imperative to look-up for DIDs and resolve them for multiple use cases.
33+
34+To fill the technical discontinuity amongst Web2 domainers & Web3 domainers, we propose a hinge between Urbit IDs & Web2 domains and also propose to build the DID resolver.
35+
36+# Why?
37+ - Web2 domains still serve as the starting points for most of the things on the Internet. (Even when Web3 products start their journey, maybe one of the first steps is to register a Web2 domain.)
38+ - People across the world know, understand & value Web2 domains more than any other thing (for example, a dot com)
39+ - There are millions of Web2 domainers who have no idea of Web3 landscape & considering them the long tail it is far more easier to use Web2 domains and nudge them towards Web3
40+
41+# The Proposal
42+
43+1. Chain agnostic Web23 domain centric wallet, first of it’s kind with the capabilities of Ethereum, Solana, Hedera Hashgraph to allow:
44+1
45+ - Existing Web2 domainers (likes of .com, .link) to explore, mint new Urbit IDs (from within the wallet) - pulled via GoDaddy, Tucows etc.
46+ - Existing Web3 domainers (likes of .eth, .sol, .hbar) to explore, mint new Urbit IDs (from within the wallet)
47+2. Decentralized application with the web interface to allow minting of new Urbit IDs via:
48+ - Web2 domains pulled over GoDaddy & Web3 domains pulled via Metamask (for Ethereum) or Phantom (for Solana) or Blade (for Hedera Hashgraph)
49+3. Integrated DID resolver:
50+ - To be accessed within the entire galaxy/ships of Urbit - an application layer in the form of NPM based libraries - could be used by all the calls/requests
51+ - To be accessed within the Web23 wallet as eventually DIDs would be the best fit & initial hook for the wallet - allowing end users to map multiple assets along with their DIDs
52+
53+# Timeline and Compensation
54+
55+This proposal will be completed in multiple phases, beginning with:
56+
57+Web23 wallet in the form of Chrome Extension for the Urbit community with the capabilities to map Web2 domains + Web3 domains of Ethereum, Solana, Hedera Hashgraph, Concordium along with the Urbit IDs:
58+ - Option to buy new Urbit IDs
59+ - Option to configure existing Urbit IDs
60+ - Access to Urbit IDs via sub-domains of the existing Web2 domains in question. For example, john.com may have ~Urbit ID.john.com
61+ - Option to exchange DMs (Direct Messages) within the wallet amongst each other
62+
63+Timeline: 8 weeks from start of project
64+
65+Reward: 5 Stars
66+
67+# Future Work
68+
69+The next two phases of work will consist of:
70+
71+1. Web based decentralized application to allow Web2 domain holders + Web3 domain holders of Ethereum, Solana, Hedera Hashgraph & Concordium to:
72+ - Map their existing Urbit IDs with the Web2 or Web3 domains (as indicated above)
73+ - Buy new Urbit IDs
74+ - Configure Urbit IDs
75+ - Decentralized application to allow connectivity for the respective wallets of the chains (one wallet each chain)
76+ - Exchange DMs using the Urbit IDs as hook and accessible over decentralized application
77+
78+
79+2. Integration of DID Resolver for Urbit allowing:
80+ - Ships to resolve to DIDs
81+ - Web23 wallet to resolve DIDs since Urbit IDs would be mapped to the
82+wallet
83+ - Decentralied apps to resolve DIDs
84+
85+# Overall Benefits
86+
87+ - Web2 domains get coupled with Urbit IDs for future sign-ups over dApps - for enhanced utilities of Urbit IDs
88+ - Insertion of Urbit IDs into the zone files of Web2 domains - for future readiness when DNS resolvers may have to query about the Urbit IDs
89+ - Easy access of Urbit IDs or dApp running web pages via integrated hosting services. For example, ravmel-ropdyl.john.com if Urbit ID ~ravmel-ropdyl creates a hinge with john.com
90+ - Integration of DID resolving part from within the proposed Web23 wallet- allowing users to keep & manage Urbit IDs, DIDs, Web2 domains and even Web3 domains -lying over Ethereum, Solana & Hedera Hashgraph
91+ - Push of Urbit IDs to all the Web2 domainers
92+
93+# Why Us?
94+
95+ - Our core expertise & experience run in decades of man hours in the Unix/Linux & domains, DNS at large
96+ - [Web23](https://web23.io/) is one of the grantees of Hedera Hashgraph - we have developed complete naming system for .hbar and various project TLDs over Hedera
97+ - Web23 has collaborated with many ICANN registrars & registries to bring in the Web2 domainers to the evolving webspace of Web3
98+ - Web23 is working to transform any Web2 domain to a Web3 domain
99+
100+# Specific Deliverables
101+
102+ - Web23 domain centric wallet
103+ - DID resolver as NPM based library
104+ - Integrated DID resolver within the Web23 wallet as well as the application layer for the ships
105+ - A decentralized web application with integrations of Metamask, Phantom & Blade to allow buying, mapping of Urbit IDs to Web2 domains
106+
content/grants/2023/network-weather.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+
3+title = "Network Weather Simulator for %pyro/%aqua"
4+date = "2023-03-02"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Network Weather Simulator for `%pyro`/`%aqua"
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1004"
17+completed = false
18+canceled = false
19++++
20+
21+`%pyro` and `%aqua` are virtualization tools that allow developers to run one or many virtual ships within their ship. This opens up many testing possibilities, since it's possible to spin up an entire fleet of virtual ships with state and orchestrate them within your ship. But since all of hte ships run one one computer, the network conditions are unrealistically good. In the real world, network connections fail, time out and generally perform in unexpected ways.
22+
23+Write a library that allows developers to easily add realistic "network weather" to fleet testing in `%pyro`/`%aqua`
24+
content/grants/2023/oauth2-stella-fixa-rfp.mdnew file+31
@@ -0,0 +1,31 @@
1++++
2+title = "Build a Single-Sign-On App for Urbit"
3+date = "2023-05-11"
4+
5+[taxonomies]
6+grant_type = ["RFP"]
7+grant_category = ["App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Produce an OAuth-compatible token issuer and login manager."
12+reward = "TBD"
13+assignee = [""]
14+champion = [""]
15+grant_id = "P1001"
16+completed = false
17+canceled = false
18+
19++++
20+
21+OAuth has widespread support in Web 2.0 circles. OAuth issues permissioned tokens for service providers to manage sessions. There are burgeoning tools for Web3 integration.
22+
23+OAuth focuses on access delegation, meaning that one can authenticate into a third-party session using a primary identity but without giving one’s password to the third-party service provider. “OpenID is a way to use a single set of user credentials to access multiple sites, while OAuth facilitates the authorization of one site to access and use information related to the user's account on another site.”
24+
25+By providing Urbit with OAuth support, the ability to use Urbit to log into a variety of Web 2.0 services will be unlocked.
26+
27+Some resources that may be helpful in scoping such a project:
28+
29+- https://oauth.net/getting-started/
30+- https://www.oauth.com/oauth2-servers/getting-ready/
31+- https://www.pmail.com/devnews.htm
content/grants/2023/osmosis-client.mdnew file+48
@@ -0,0 +1,48 @@
1++++
2+
3+title = "Osmosis Client on Urbit"
4+date = "2023-03-26"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "The Urbit client for the Osmosis multi-chain DEX."
13+reward = "3 Stars + Bonus"
14+assignee = ["~larryx-woldyr"]
15+champion = [""]
16+grant_id = "B0234"
17+completed = true
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0234&prefill_Grant+Name=Osmosis%20Client%20for%20Urbit"
20+deliverable = "~larryx-woldyr/osmosis"
21+
22++++
23+
24+
25+## Overview
26+
27+An Urbit app that serves a personal client for the [Osmosis](https://app.osmosis.zone) multi-chain DEX.
28+
29+## Rationale
30+
31+Osmosis is the leading decentralized exchange for the Cosmos ecosystem. Most users access this DEX through [the front end developed](https://github.com/osmosis-labs/osmosis-frontend) by the Osmosis team and deployed at [app.osmosis.zone](https://app.osmosis.zone).
32+
33+Like many Dapps, the most used Osmosis front end is hosted on a central server. This falls short of the promise of decentralization and makes the application less resilient. On Urbit, it is easy for users to host their own front ends, making the system truly decentralized.
34+
35+Osmosis uses local browser storage for user configuration. This is not portable across browsers on the same machine or on different devices. The storage of this metadata on a user's urbit allows the data to remain private to the user and will survive swapping browsers and devices. At a later date, this configuration can be used by other apps and expand the scope of interoperability, eg. displaying which ships in a chat have a Cosmos wallet.
36+
37+## Scope / Implementation
38+
39+The first phase of this project is to bundle the [existing Osmosis front end](https://github.com/osmosis-labs/osmosis-frontend) and make it possible to serve from an Urbit.
40+
41+Once this is accomplished, a simple gall back end will be developed to replace the Osmosis client's use of browser `localStorage`. It may be necessary to fork the `osmosis-labs` code in order to replace API calls to localStorage with calls to the Urbit back end.
42+
43+Developer can assume that users will access this client through a browser that can install the Keplr wallet extension. There are currently projects in process to create an in-Urbit Cosmos wallet, but that integration is out of scope for this bounty.
44+
45+## Compensation
46+
47+3 Stars with a 1500 USDC bonus to be provided by the Osmosis foundation.
48+
content/grants/2023/pastebin-RFP.mdnew file+28
@@ -0,0 +1,28 @@
1++++
2+
3+title = "Pastebin on Urbit"
4+date = "2023-03-02"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Share plaintext snippets on Urbit"
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1000"
17+completed = true
18+canceled = false
19+
20++++
21+
22+# Description
23+Tools like pastebin and Github gists allow users to easily share plain text snippets. This is useful for sharing code or simple writeups.
24+
25+Implement minimal plaintext snippet sharing for Urbit, with support for both public (anyone with the path can read the snippet) and private (only invited individuals can read snippets).
26+
27+# Link to Proposal
28+[Pastebin on Urbit](https://urbit.org/grants/pastebin-proposal)
content/grants/2023/pastebin-proposal.mdnew file+33
@@ -0,0 +1,33 @@
1++++
2+
3+title = "Pastebin on Urbit"
4+date = "2023-06-05"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = ""
13+reward = "1 Star"
14+assignee = ["~polwex"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "P0271"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Description #
23+
24+One of the promises of Urbit, perhaps the biggest one, is making the Internet peer-to-peer again. That's what it's designed to do. If I want to share data with other people I should be able to share it directly. I should not need to use other people's computers (the "cloud") to share a file, or a text snippet.
25+
26+While Dropbox-like functionality will take some time to arrive to Urbit, one thing we can do right now is more simple data sharing. Pastebin is a very useful website, but again it boggles the mind that you need to use an external service to share a simple piece of text with your friends. It should be easier. We will make it so.
27+
28+This proposal will create an Urbit application to share arbitrary text. You will be able to produce a link that will display a piece of text that you saved. You will be able to expose that document to the clearweb, only inside Urbit, or to selected Urbit ships of your choice.
29+
30+# Compensation #
31+Reward: 1 star
32+#
33+Note: This proposal was modified from the [Pastebin on Urbit RFP](https://urbit.org/grants/pastebin-RFP).
content/grants/2023/portal-features-1.mdnew file+82
@@ -0,0 +1,82 @@
1++++
2+
3+title = "Advanced Portal Features Phase 1"
4+date = "2023-04-13"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = ""
13+reward = "3 Stars"
14+assignee = ["~toptyr-bilder", "~dilryd-mopreg", "~foddur-hodler"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "P0251"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Rationale
23+
24+Portal currently allows for simple discovery of groups and apps, but there are still outstanding problems in user onboarding and advanced curation and discovery. In particular, first-time users would benefit from an onboarding flow that provides personalized recommendations and an overview of Portal’s functionality. Further, curators should have the flexibility to make their posts and collections high-quality and personalized, and to create recurring relationships with users via follow and notification features. By solving these problems we further improve Urbit user activation and retention, and we aim to increase Portal’s weekly active user (WAU) count.
25+
26+For context on previous work, see our [previous grant](https://urbit.org/grants/app-store) and its [M4 redefinition](https://docs.google.com/document/d/10tZgF8ZA9KQbRYD7MDZ7v-iuIeO2nPNppj9CMRBVg7g/edit#).
27+
28+# Milestones Overview
29+
30+The grant will consist of many small features per milestone. We expect to be flexible on the actual grouping and focus rather on shipping features that will increase WAU. (Phase 1 will consist of Milestones 1 -3.)
31+
32+## Milestone 1
33+ - Build a real-time global feed
34+ - Build an indexer to accomplish the above
35+ - Build out unified data model and schemas for different types of items
36+## Milestone 2
37+ - %blogs and %groups notebooks integration
38+ - Basic custom feeds
39+ - Replace react with Svelte
40+## Milestone 3
41+ - Support comments on all items
42+ - Re-share posts
43+ - Pre-populate posts to share desks and groups that the user hosts
44+ - Publish content to web2
45+
46+# Future Work
47+## Milestone 4
48+ - Follow other users
49+ - Implement paywalls
50+ - Fully-featured posts
51+ - Markdown support for items
52+ - Groups and apps can only be posted by their host
53+## Milestone 5
54+ - %pals integration
55+ - Tags can be applied to all items (lists, curators, etc)
56+ - Richer post metadata like number of app downloads/app versioning/poster info
57+ - Fully-featured profiles
58+ - Richer profile metadata
59+ - Markdown support for profile descriptions
60+
61+# User Stories
62+## Milestone 1
63+1. I’m a first-time Urbit user and I want good suggestions for content so that I can find my people on Urbit
64+2. I’m a return user and I want personalized curation integrated into my experience so that I can find relevant content without trying
65+## Milestone 2
66+3. I’m a user and I want to be able to make my content discoverable quickly and easily so that I can get distribution
67+4. I’m a user and I want a synopsis of the content being shared in a group so that I can quickly pick out the most interesting parts of the conversation
68+## Milestone 3
69+5. I’m a user and I want to be able to reference and comment on other people’s items so that I can build on others’ content
70+6. I’m a user and I want to be able to make my content discoverable quickly and easily so that I can get distribution
71+7. I’m a user and I want to be able to make my content discoverable on web2 so that I can share my Urbit content more broadly
72+## Milestone 4
73+8. I’m a user and I want to know which developers and content creators are notable and trustworthy so that I can find good content
74+9. I’m a content creator and I want to be able to leverage markdown in my posts so that I can create more attractive + organized content
75+## Milestone 5
76+10. I’m a curator/developer/content creator and I want to have a fully-featured, professional-looking profile page so that I can create a good reputation
77+11. I’m a user and I want to know that the app I’m downloading is trusted and safe so that I don’t get malware
78+
79+# Timeline and Compensation
80+Each milestone is expected to be completed over the course of roughly 1 month. Along with the prescribed features (which may be subject to slight reprioritization), completion of each milestone is dependent upon increasing Portal’s WAUs by 10% over baseline, as measured before any of the current milestone’s features have been introduced. Meeting these criteria will yield compensation of 1 star per milestone.
81+
82+
content/grants/2023/privacy-msg.mdnew file+89
@@ -0,0 +1,89 @@
1++++
2+
3+title = "Privacy Messaging"
4+date = "2023-04-07"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "Communicating Urbit's unique privacy potential"
13+reward = "4 Stars"
14+assignee = ["~dibnyt-wisfyn"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "P0257"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Overview #
23+
24+The goal of this work is to improve Urbit’s appeal to potential developers by highlighting and communicating its unique privacy potential.
25+
26+## Initial Insights
27+
28+ - Urbit is currently focused on attracting developers who will build the apps that bring users to the platform
29+ - Even some currently active developers don’t fully understand the full offering of Urbit
30+ - Urbit isn’t inherently private - it’s “privacy prone”
31+ - Urbit OS does so much for developers that they can add in features for almost nothing - privacy is one of those features
32+
33+# Work Summary #
34+
35+## Research
36+
37+ - Interviews to examine and understand current state of Urbit’s offering
38+ - Explore where Urbit wants to go in the future
39+ - Interviews to examine what developers are creating and motivations for coming to the platform
40+ - Determine what related offerings are being missed by existing developers
41+
42+## Development
43+
44+ - New messaging strategy and copywriting based on research
45+ - Incorporate growth strategy to target the ideal developers and grow our developer base in sync with Urbit’s theory of change
46+ - Exploration of ideal implementation - comms channels, structure, media formats
47+ - Rounds of feedback internally and externally (developers) to improve messaging
48+
49+## Implementation
50+
51+ - Messaging strategy presented internally to guide thinking for Urbit Foundation, Tlon, and other established developers
52+ - Messaging incorporated to assets presented to new and potential developers - (website and videos)
53+ - Potentially guidance verging on curricula - opportunity to incorporate into Hoon School
54+
55+# Guiding Principles #
56+
57+ - Overall - Develop a shared language around Urbit’s privacy features that both supports Urbit Foundation’s vision for the future and speaks to the practical implications for developers
58+ - Research - Ensure project success by making sure all stakeholder viewpoints are heard and considered from the earliest stages in the process
59+ - Development - Strive to approach communications in a way that feels interactive and engaging
60+ - Implementation - Identify and collaborate with the individuals within Urbit Foundation that need to greenlight any actions early on in the process
61+
62+# Growth Framework #
63+Through attracting new developers, deepening understanding, or a combination of both we can see three general types of growth:
64+
65+ - Attract new developers with a basic understanding of Urbit features
66+ - Expand capabilities of existing developers
67+ - Attract new developers interested in novel implementations of Urbit OS
68+
69+# How This Can Support Future Work #
70+
71+Privacy is one of many features that Urbit offers. This means that this project can model and test an approach to messaging replicable across all aspects of Urbit. The goal is to create something that is not solely top-down (led by Urbit Foundation) or bottom-up (led by 3rd party developers). Rather we want to support both the vision of Urbit and the motivations of developers and meet somewhere in the middle.
72+
73+# Timeline and Compensation #
74+
75+Timeline: Approximately 10 weeks
76+
77+ - Stakeholder Identification ~ .75 wks
78+ - Interview Prep + Scheduling ~ .75 wks
79+ - Internal + External Interviews ~ 2 wks
80+ - Analysis & Reframing ~ 1 wks
81+ - Ideation & Feedback ~ 2.5 wks
82+ - Development & Implementation ~ 3 wks
83+
84+Reward: 4 Stars
85+
86+# Summary #
87+
88+While the underlying technology behind Urbit is incredible, the current messaging strategy is not focused enough on the value that tech brings to our core audience. This hinders conversion of new developers to the platform and limits the capabilities of existing developers.
89+By addressing this issue (starting with the topic of privacy), this work will be invaluable in helping Urbit grow. Additionally, it will model a systematic yet flexible process of working with stakeholders—both internally and externally—that can be used to improve messaging across any number of topics.
content/grants/2023/quorum-2.mdnew file+84
@@ -0,0 +1,84 @@
1++++
2+title = "Quorum 2"
3+date = "2023-03-20"
4+
5+[taxonomies]
6+grant_type = ["Proposal"]
7+grant_category = ["App Dev"]
8+
9+[extra]
10+image = ""
11+description = "Improve the usability and accessibility of Quorum in the Urbit ecosystem"
12+reward = "6 stars"
13+assignee = ["~tamlut-modnys", "~litlep-nibbyt", "~sidnym-ladrut"]
14+grant_id = "P0254"
15+champion = ["~lagrev-nocfep"]
16+completed = false
17+canceled = false
18++++
19+
20+# Purpose #
21+
22+Quorum needs many usability and accessibility improvements to make it an impactful part of the Urbit ecosystem. Its latent utility to capture and retain domain knowledge across the ecosystem has been hindered by its “minimum viable product” feature set and its existence as disjoint to Tlon’s more central Groups product (with which it overlaps on many organizational features).
23+
24+The work proposed for this grant will address these issues by:
25+1) Extending Quorum into a custom Q&A channel type in Tlon’s Groups with the added goal of becoming a blueprint for future third-party Groups integrations.
26+2) Adding essential Q&A board functionalities to Quorum such as post editing, content moderation tools, and enhanced search.
27+3) Implementing quality of life improvements to the Quorum frontend which will make the UI more user friendly.
28+
29+# User Stories #
30+
31+## `%groups` User Stories ##
32+
33+- As a %groups admin with %quorum installed, I can create Q&A channels in my groups, which have a name, host ship, and permissions options identical to the existing channel types (i.e. open to all, members only, or admins only).
34+- As a %groups admin with %quorum installed, I can modify my Q&A channels like other channel types, e.g. by renaming the channel, deleting the channel, and so forth.
35+- As a %groups user with %quorum installed, I can see and join Q&A channels in my groups.
36+- As a %groups user with %quorum installed, I can browse and manipulate the content of Q&A channels in the %groups interface.
37+
38+## `%quorum` User Stories ##
39+
40+- As a %quorum admin, I can remove posts from my Q&A channels.
41+- As a %quorum admin, I can edit the content (i.e. title, text, and tags) of any post made to my Q&A channels.
42+- As a %quorum admin, I can create and edit a set of allowed tags for posts made within my Q&A channels.
43+- As a %quorum admin, I can run a `dojo` command in order to import a legacy %quorum board into the new interface.
44+- As a %quorum user, I can browse through the paginated archive of posts on my Q&A channels.
45+- As a %quorum user, I can perform a string or tag-based query and view the paginated results on my Q&A channels.
46+- As a %quorum user, I can edit the posts I’ve authored.
47+- As a %quorum user, I can delete the posts I’ve authored.
48+- As a %quorum user, I can view the history of a post that has been edited.
49+- As a %quorum user, I can paste a %groups reference into a question or answer submission to copy its content from %groups.
50+
51+# Timeline #
52+
53+## Milestone #1 - Permissions Refactor & QoL Improvements ##
54+
55+- **Reward**: 3 stars
56+- **Tasks**:
57+ - Refactor %quorum to gate board entry based on %groups permissions.
58+ - Add front-end subscription support for reliable post-poke page updates.
59+ - Enable authors and board admins to edit post content.
60+ - Enable authors and board admins to delete posts.
61+ - Update the post voting indicator to display the personal vote cast rather than the aggregate score direction.
62+
63+## Milestone #2 - New Features & Groups Integration ##
64+
65+- **Reward**: 2 stars
66+- **Tasks**:
67+ - Enable users to browse each post’s edit history.
68+ - Allow users to view the different edited versions of a post in the thread view (i.e. as different standalone versions without diffs).
69+ - Display all authors involved in constructing a post (original author & editors).
70+ - Add result pagination for board and question listings, including search results.
71+ - Implement tag-based search via (1) the search bar and (2) clicking on a post tag.
72+ - Allow admins to optionally create a set of eligible tags for their boards.
73+ - Enable %groups “refs” submissions for posts, which will be replaced on publication with the original %groups content.
74+
75+## Milestone #3 - Groups Plugin Support ##
76+
77+- **Reward**: 1 star
78+- **Tasks**:
79+ - Revamp the %quorum user interface to improve the UX for %groups embedding.
80+ - Replace the navigation bar actions with in-form buttons.
81+ - Replace the search bar with a form of floating/toggled search menu.
82+ - Integrate %quorum as a %groups channel type plugin.
83+ - Create scry endpoint(s) for %groups channel type metadata and coordination.
84+ - Add poke endpoint(s) for any necessary %groups join and leave behaviors.
content/grants/2023/replit.mdnew file+52
@@ -0,0 +1,52 @@
1++++
2+
3+title = "Replit & Replit Integration for Site"
4+date = "2023-06-21"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "Produce a Replit-compatible binary and instance."
13+reward = "4 stars"
14+assignee = [""]
15+champion = ["~mastyr-bottec"]
16+grant_id = "B0282"
17+completed = false
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0282&prefill_Grant+Name=Replit%20%26%20Replit%20Integration%20for%20Site"
20+
21++++
22+
23+# Replit & Replit Integration for Urbit Developer Site
24+
25+A Replit instance lets you specify the running status of a ship and associated files. In practice, this means a fakezod which is automatically logged in, has `%base` `|mount`ed, and has `|autocommit` set for ease of use. The instance should connect to the file in some cases, the Dojo terminal in others.
26+
27+We anticipate that the biggest part of this bounty will focus not on designing the Replit environment but instead on building a Prybar binary for full REPL compatibility.
28+
29+By forking from your base instance, you should be able to prepare a base instance which meets the above basic setup criteria. Then from that, build forks which automatically inject the correct code when a generator or other specified expression has been supplied to the student.
30+
31+## Milestones
32+
33+### Milestone 1 (3 stars)
34+
35+Build a working Replit-compatible binary and base instance. This Replit instance should be [Prybar](https://github.com/replit/prybar)-compatible so that the Replit console can directly run the Dojo instance. (That is, no `screen` or `tmux` screen management is necessary for the user.)
36+
37+This may require using `%khan` and other affordances to interact with Dojo or a primary agent.
38+
39+The final deliverable should include the Prybar binary, a base Replit instance, and a Docker image suitable for use with Replit.
40+
41+### Milestone 2 (1 star)
42+
43+The Hoon School docs will benefit from direct integration of executable code blocks. To claim this bounty, you will need to prepare and include customized Replit instances at every appropriate explanation, exercise, and challenge in [the Hoon School docs](https://developers.urbit.org/guides/core/hoon-school). (This does not mean everywhere there are code blocks now; you will work with your grant champion to identify all of these.)
44+
45+(This can be split into a separate bounty based on temperament of the grantee completing Milestone 1.)
46+
47+## Resources
48+
49+- https://docs.replit.com/programming-ide/configuring-repl
50+- https://github.com/replit/prybar
51+- https://replit.com/@matthew-levan/Urbit-1#README.md
52+- https://docs.replit.com/hosting/embedding-repls
content/grants/2023/school-support-23q1.mdnew file+43
@@ -0,0 +1,43 @@
1++++
2+
3+title = "School Support"
4+date = "2023-01-25"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Supporting online course teaching and composing grading apps."
13+reward = "2 stars"
14+assignee = ["~tamlut-modnys"]
15+champion = ["~lagrev-nocfep"]
16+grant_id = "B0225"
17+completed = true
18+canceled = false
19+link = ""
20+
21++++
22+
23+# Rationale
24+
25+A teaching assistant and developer will support App School Live and Hoon School
26+Live, including producing basic courseware tools as command-line apps and agents.
27+Some of this will involve further developing Urbit Forms or another backend to
28+facilitate grading of submissions and allow us to natively showcase that tool in
29+a course setting.
30+
31+# Implementation
32+
33+The basic spec for this proposal:
34+
35+- support teaching and grading ASL and HSL
36+- course grading CLI tools (grading agent or thread from reference answer to student answer yielding final grade)
37+- course admin CLI tools (gradebook store with DM reporting agent or thread)
38+- maybe Urbit Forms upgrade/update (postponing)
39+
40+(So about three agents/threads.)
41+
42+# Compensation
43+Reward: 2 Stars
content/grants/2023/splitwise-rfp.mdnew file+26
@@ -0,0 +1,26 @@
1++++
2+
3+title = "Expense Sharing App for Urbit"
4+date = "2023-04-03"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Create a crypto and fiat expense sharing app for Urbit "
13+reward = "1 Star"
14+assignee = ["~talfus-laddus"]
15+champion = [""]
16+grant_id = "P0279"
17+completed = true
18+canceled = false
19+
20++++
21+
22+The Urbit community hosts many IRL events and, inevitably, this means splitting tabs with other Urbiters. Urbit needs its own expense sharing app that seamlessly keeps track of all expenses and IOUs in one place and works with both crypto and fiat.
23+
24+The Urbit version can be loosely modeled on the expense sharing app [Splitwise](https://www.splitwise.com). Splitwise uses centralized cloud infrastructure, but an Urbit version could be architected so that accounts payable and receivable are kept on your ship. The Urbit version should also be mobile-first, so it's easy to use on the go.
25+
26+See the full proposal [here](https://urbit.org/grants/splitwise)
content/grants/2023/splitwise.mdnew file+129
@@ -0,0 +1,129 @@
1++++
2+
3+title = "Expense Sharing App"
4+date = "2023-06-22"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = ""
13+reward = "1 Star"
14+assignee = ["~talfus-laddus"]
15+champion = [""]
16+grant_id = "P0279"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Motivation
23+The Urbit community hosts many IRL events and, inevitably, this means splitting tabs with other Urbiters. Urbit needs its own expense sharing app that seamlessly keeps track of all expenses and IOUs in one place and works with both crypto and fiat [RFP](https://urbit.org/grants/splitwise-rfp).
24+
25+Urbit is for small communities. And those need a way to keep track of and to split shared expenses.
26+
27+# Basic User Story
28+A member of a group wants to keep track of all expenses in order to eventually settle debts with a minimal number of transactions.
29+
30+# Basic User Tasks
31+ - Create or select a group
32+ - Invite other people to the group
33+ - Add an expense involving other group members
34+ - View all expenses
35+ - Edit an expense
36+ - Delete an expense
37+ - Retrieve a suggestion on how to balance debts with minimal number of transactions
38+
39+# Basic User Flow
40+1. Select a group
41+2. Add an expense
42+3. Check balance
43+ - Who is owed, and who owes money to the group and how much?
44+4. Settle debts
45+ - The app suggests an efficient way to settle debts in the group
46+ - Mark outstanding expenses as paid
47+
48+# Architecture
49+The architecture will be loosely modeled on existing expense sharing apps such as [Splitwise](https://www.splitwise.com/) and [Tricount](https://www.tricount.com/en/).
50+
51+An expense can involve only a subset of all group members. It has the following attributes:
52+
53+- title (For what reasons?)
54+ - payer (Who paid?)
55+ - involves (For whom?)
56+ - date (When?)
57+ - amount (How much?)
58+ - currency
59+ - note
60+
61+All group members are ships (`@p`). A list of group members and all expenses of the group will be stored on the ship of the group initiator. Other group members will read and write from/to there.
62+
63+In order to find a minimum number of transaction to settle debts in the group ("simplified debts"), shared expenses will be modeled as a flow network. Money flows from the participants who owe money to the group (debitors) to the participants who are owed money by the group (creditors). Using [Edmonds–Karp algorithm](https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm), the [maximum flow](https://en.wikipedia.org/wiki/Maximum_flow_problem) of this network will be computed. From the resulting residual network transactions to balance out shared expenses will be derived. A Python reference implementation can already be found [here](https://git.sr.ht/~talfus-laddus/splt-exps-py).
64+
65+*Note: The trivial case of settling debts among two person (group size of two) is of course supported.*
66+
67+# Backend
68+The backend will be a gall agent with a basic set of operations addressing the user's needs listed above. Alongside the gall agent, a couple of libraries will be created: A library implementing the Edmonds-Karp algorithm and a library handling currency exchange rates and conversions.
69+
70+# Frontend
71+[Keep it simple, stupid!](https://en.wikipedia.org/wiki/KISS_principle)
72+The frontend will be a mobile-first website.
73+
74+It is an open question whether the frontend will in the initial phase be served from Mars or Earth. The website should eventually be served from the ship.
75+
76+# Milestones
77+Documentation and tests throughout the code base will be present. The source code will be available in a public git repository and licensed under MIT.
78+
79+## Milestone 1 - Proof of Concept
80+Completion: Beginning of App School Live (August 2023)
81+
82+Payment: None
83+
84+Deliverables: Edmonds-Karp Library
85+
86+The Proof of Concept (POC) demonstrates how to model shared expenses as a flow network and how to derive from it the minimum number of transactions needed to settle debts. The POC implements the Edmonds-Karp algorithm as well as the logic of how to construct the flow network from a list of expenses and how to derive a list of transactions from the residual network.
87+
88+## Milestone 2 - Minimal Viable Product
89+Completion: End of App School Live before Assembly (October 2023)
90+
91+Payment: 1 Star
92+
93+Deliverables : Gall Agent: Website
94+
95+The Minimal Viable Product (MVP) consists of a gall agent as backend and a website as frontend.
96+
97+Iterations
98+1. Create a gall agent containing a basic set of operations to manage groups and to add, store, delete and retrieve group expenses.
99+2. Create a simple, stupid and mobile-first website as an interface to the gall agent.
100+3. Add a feature to “simplify debts” by integrating the Edmonds-Karp library into the gall agent. The agent can suggest a way to balance out shared expenses with a minimal number of transactions.
101+4. Synchronize expenses among the group members.
102+5. Handle different currencies. Retrieve the current exchange rate and do conversions between currencies.
103+6. Make the app available through Software Distribution.
104+
105+# Limitations
106+Since the list of expenses is stored on the group initiator's ship, when it is down other people can not synchronize their state of the application.
107+
108+# Additional Future Work
109+The future of the app could entail:
110+
111+ - A robust decentralization/synchronization mechanism which addresses the limitation raised above
112+ - A more polished interface
113+ - An integration into Groups
114+ - Apps for Android and iOS
115+ - A new feature to categorize expenses and derive statistics
116+ - Yet unforeseen improvements
117+
118+# About Me
119+I am in search of something worthwhile to contribute my time and effort to.
120+
121+My name is Matthias Schaub (`~talfus-laddus`). Even though I work part-time as a software developer for a non-profit corporation dedicated to better society and environment, I feel the need to spend my time on projects of which I am more confident that they provide sustained value to society (or at least have the potential to). That is why I am invested to contribute to the Urbit ecosystem by learning Hoon and how to build applications on Urbit. A more basic motivation is to have my flat mates on Urbit. Beside a chat, we need a way to handle shared expenses.
122+
123+I attended Hoon School and registered for App School. Alongside the App School curriculum, I want to foster my learning by building this application. On Earth side I have solid Python and basic HTML, CSS, and JavaScript skills. I am proficient in git, and I am used to working with a terminal on a Linux machine. In the past, I wanted to read the reference of a Hoon rune without leaving Vim. So I wrote a Python script to convert Hoon rune references from Markdown to Vimdoc. The result is a Vim helpfile in disguise of a plugin ([hoon-runes.vim](https://git.sr.ht/~talfus-laddus/hoon-runes.vim)). Shortly after, I did the same for the documentation of the Hoon standard library ([hoon-stdlib.vim](https://git.sr.ht/~talfus-laddus/hoon-stdlib.vim)).
124+
125+In order to find out more about my previous works:
126+ - [Personal website](https://talfus-laddus.de/)
127+ - [Sourcehut](https://git.sr.ht/~talfus-laddus)
128+ - [GitHub](https://github.com/matthiasschaub)
129+
content/grants/2023/text-search.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+
3+title = "Generic Text Search Tool for Urbit"
4+date = "2023-03-02"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Build Urbit's answer to grep."
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1002"
17+completed = false
18+canceled = false
19+
20++++
21+
22+Text search is a key part of many different use cases, but Urbit currently has no equivalent to `grep`, the general purpose GNU search tool.
23+
24+Build Urbit's answer to `grep`.
content/grants/2023/tinygrad.mdnew file+24
@@ -0,0 +1,24 @@
1++++
2+
3+title = "Tinygrad ML Library in Hoon"
4+date = "2023-03-02"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Implement a small machine learning library (and jets!) in hoon."
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1003"
17+completed = false
18+canceled = false
19+
20++++
21+
22+Geohot has published the [Tinygrad library](https://github.com/geohot/tinygrad) for doing basic machine learning. This library is small and simple which makes it a potentially good target for jetting. Doing so would give basic ML functionality in Urbit.
23+
24+Implement Tinygrad (with jets) in Urbit
content/grants/2023/treesitter.mdnew file+71
@@ -0,0 +1,71 @@
1++++
2+
3+title = "Treesitter Hoon Parser"
4+date = "2023-05-11"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Create a better hoon parser with Treesitter"
13+reward = "2 Stars"
14+assignee = ["~hosweg-silpur"]
15+champion = [""]
16+grant_id = "P0263"
17+completed = false
18+canceled = false
19+
20++++
21+
22+# Summary
23+
24+Tree-sitter is a fast parser that supports smarter syntax highlighting that makes use of the syntax tree.
25+
26+# Background
27+
28+Current syntax-highlighters are based off complicated regex that are overly complicated and inaccurate. Tree-sitter parses the whole document and creates an abstract syntax tree (AST) which can then be used to correctly highlight syntax.
29+
30+The current syntax highlighters available for hoon are:
31+
32+- **Hoon-lsp**: Decent, but due to being a semantic highlighter it naively highlights using regex matches. As an example it does not know the difference between `!=(a)` and `!=(a 1)`. (The first is the `zaptis` rune taking `a` as a sample, the second is `!` applied to an equality check between `a` and `1`)
33+
34+- **Hoon.vim/hoon-mode.el**(emacs package): This is also a regex matcher and suffers from the same problems above.
35+
36+In conclusion, creating a tree-sitter parser will allow for superior Hoon highlighting to be used in more code-editors.
37+
38+
39+# Milestones and Compensation
40+## Milestone 1: Writing the grammar
41+
42+**Estimated Completion**: Completed
43+
44+**Payment**: 1 star
45+
46+ - Write a tree-sitter grammar that parses Hoon
47+ - Create unit tests for each syntax component (runes, irregular syntax, mold, strings...)
48+
49+
50+## Milestone 2: Code editor Integration
51+
52+**Estimated Completion**: May 2023
53+
54+**Payment**: 1 star
55+
56+Integrate the tree-sitter parser with various code-editors.
57+
58+Desktop editors:
59+ - VScode
60+ - Emacs
61+ - Neovim
62+ - Atom
63+Online editors:
64+ - Monaco
65+ - Codemirror
66+
67+# Future Work
68+
69+- GitHub Gist alternative on Urbit
70+- Online IDE with `%pyro` sandbox
71+- Collaborative Hoon code-editing with CRDTs
content/grants/2023/turf.mdnew file+205
@@ -0,0 +1,205 @@
1++++
2+
3+title = "Turf"
4+date = "2023-05-17"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Build a thriving and customizable virtual world on Urbit"
13+reward = "9 Stars"
14+assignee = ["~midlev-mindyr"]
15+champion = ["~reb"]
16+grant_id = "P0265"
17+completed = false
18+canceled = false
19+
20++++
21+
22+## Summary
23+
24+Turf is like if [gather.town](http://gather.town/) were fully customizable, interconnected, and lived on Urbit. However, to start out with, it will have a lot less content and features. Turf will be good for Urbit for the following reasons:
25+
26+- it will be fun / it will give people another reason to use Urbit day-to-day
27+- it will enable spontaneous and casual social interactions
28+- it will be a space that people can mold and construct freely, which means it can naturally develop into a vibrant, complex virtual world
29+- it will cause people to crave app interoperability like never before, which will mean I can later build a plugins system (Monkey) and actually convince people to use it
30+
31+Each turf is made up of pixelated tiles which can be customized with a variety of items, and people can run around in them and chat with voice and text. Everyone can make their own turfs, and (with consent) make portals to other turfs. At the end of the final milestone, we hope to have a thriving, organically self-organizing web of connected turfs, where people know how to get where they’re going and have lots of new things to discover all around them.
32+
33+## Why me
34+
35+I have some amateur gamedev experience, some hoon experience, plenty of frontend experience (see Astrolabe). I have been thinking about something like Turf for a while, but I’m actually proposing it now because it seems like a necessary step to generate interest in a plugin system I want to build (plus it sounds fun!). So, I want to be the one to build Turf so that I can use it to demonstrate and promote Monkey (the plugin system).
36+
37+## User Stories
38+
39+After each user story is the short code for the milestone which will implement it:
40+
41+SP - Single-Player MVP
42+
43+MP - Multiplayer
44+
45+HT - Hometowns
46+
47+AI - Advanced Items
48+
49+SS - Super Speed with WebRTC
50+
51+TP - Advanced Turfs & Permissions
52+
53+?? - Some Future Grant??
54+
55+**My Avatar**
56+
57+- I can customize my avatar’s appearance somewhat (SP)
58+
59+**My Turf**
60+
61+- I can have a turf (SP)
62+- I can have multiple turfs (TP)
63+- I can resize my turf(s) (SP)
64+- I can customize my turf’s appearance by placing items (floor, walls, furniture, decor, objects, portals) (SP)
65+- I can move around in a turf (SP)
66+- I can explicitly specify who can and can’t enter my turf (SP)
67+- I can specify advanced permissions for my turf(s) (TP)
68+- I can grant write access to part of a turf (even if I'm not a star) (TP)
69+- I can transfer ownership of my turf to someone else (TP)
70+
71+**Items**
72+
73+- I can create my own items (wearable, wall, floor, furniture, etc) (AI)
74+- I can add items I find in the wild to my library (AI)
75+- I can make my custom items do cool custom things (??)
76+
77+**Multiplayer**
78+
79+- I can see other people moving around (MP)
80+- I can see other people moving around in realtime (SS)
81+- I can chat with other people over text (MP)
82+- I can chat with other people over voice (SS)
83+- I can create portals to other turfs (MP)
84+- I can walk through portals to travel between turfs (MP)
85+- I can summon people when I’m in a turf I admin (MP)
86+- I can teleport home to my turf from anywhere (MP)
87+- I can place my turf in a hometown (HT)
88+- As a star, I can grant plots of turf to planets for embedding (HT)
89+
90+**Misc**
91+
92+- I can integrate other apps with my turf (using %monkey) (??)
93+
94+# Milestones
95+
96+I’m asking for 9 stars for 6 milestones, which I plan to complete in 46 weeks, working part-time with a couple built-in vacations. These milestones may be accelerated if I’m able to spend fewer days on my day job. The Due Dates assume a contract is signed before May 20th, 2023. Milestones 4-6 may be reordered based on user feedback.
97+
98+## Milestone #1 - Single-Player MVP
99+
100+Reward: 1 star
101+
102+Time: 6 weeks (plus a bit of time I’ve already put in)
103+
104+Due Date: June 25th, 2023
105+
106+- You have a little pixel-art character which you can customize with basic wearable items (facial features, skin color, hats, hair, shirts, pants)
107+- You have a turf associated with your ship, composed of tiles
108+ - Each tile has a square image 32x32px image
109+ - You can place a limited set of basic items (e.g. walls, floor, grass, tables, chairs)
110+ - You can resize your turf
111+- You can move around on the grid
112+
113+## Milestone #2 - Multiplayer
114+
115+Reward: 2 stars
116+
117+Time: 9 weeks (I’d say 6, but I will have less time to work on Turf during this period)
118+
119+Due Date: August 27th, 2023
120+
121+- Through mutual agreement, two players can link their turfs with a 2-way portal. Players can visit each other by traveling through those portals.
122+- When in a turf with other players, you can see them move around (with some ames lag)
123+- You can send ephemeral, turf-scoped text chats which appear in a bubble overhead and in a chatbox sidebar
124+- Very basic permissions: I can choose to blacklist or whitelist @ps to gate visitors to my turf (prevent unwanted neighbors of neighbors)
125+- You can summon people to your turf
126+- You can teleport yourself home from anywhere
127+
128+## Milestone #3 - Hometowns
129+
130+Reward: 1 star
131+
132+Time: 5 weeks
133+
134+Due Date: October 1st, 2023
135+
136+- When I walk off my turf, I appear in my hometown, which is a star’s turf
137+- I can choose what star I want as my hometown and place my house in it, although some may require manual approval
138+- My turf/house has some little house avatar in the hometown which is customizable in some way
139+- Basic permissions for allowing people to claim (or request to claim) write access for a plot of land
140+
141+## Milestone #4 - Advanced Items
142+
143+Reward: 2 stars
144+
145+Time: 9 weeks
146+
147+Due Date: December 3rd, 2023
148+
149+- You can create custom items w/ custom art (tile, furniture, decor, wearable)
150+ - Enable png import
151+ - In-app pixel art canvas
152+- Items can have basic interactions like:
153+ - portal: teleport the activator to a particular turf (with or without coordinates)
154+ - sign: display some text, markdown, or html in a popup
155+- Items can have a foreground and/or a background image
156+- Items can have simple animations
157+- Items can be oversized (e.g. a tree which is taller than 1 tile)
158+ - Items turn partially transparent when a person walks behind them
159+- Sharing items: when you see a cool item in someone else’s turf, you can add it to your personal item library
160+
161+## Milestone #5 - Advanced Turfs & Permissions
162+
163+Reward: 1 star
164+
165+Time: 10 weeks (would be 7 or 8, but for Christmas-time)
166+
167+Due Date: Feb 11th, 2024
168+
169+- You can create multiple turfs (and link them together, of course)
170+- You can transfer your turf to someone else
171+- You can ban all comets and/or moons from your turf
172+- You can grant people/lists of people permission to do the following wrt your turf
173+ - Join, move around, and chat (whole turf)
174+ - Redecorate tiles, add/remove items, create custom items (for sections or whole turf)
175+ - Claim sections of turf (with limits, of course)
176+ - Full admin (for sections or whole turf)
177+- Permission lists
178+ - You can assemble lists of people to more easily whitelist or blacklist the same people over and over. E.g. if you want to make the same 5 people and some of your moons admins in multiple of your turfs
179+ - You can sync a list to a group so that only members of the group have access to the land
180+ - There’s a “pals” list
181+
182+## Milestone #6 - Super Speed with WebRTC
183+
184+Reward: 2 stars
185+
186+Time: 7 weeks (hard to estimate, because I’ve never done anything with WebRTC)
187+
188+Due Date: March 31st, 2024
189+
190+- Use WebRTC for low latency movement and chat
191+- Use WebRTC for proximity voice chat
192+- Enable private voice chat areas
193+
194+## Some other time
195+
196+- Use a plugin system (Monkey) to enable other apps to embed content, e.g. shared whiteboards; %radio streams; interacting with an item automatically requests a gora; link the text chat to a groups channel
197+- Item animations? (or include in Advanced Items milestone)
198+- Item inventories (allow some items to be picked up, carried, and set down elsewhere by visitors with no write access)
199+- Custom items with custom code so you can turn your turf into a full game or an economy or whatever
200+- Decentralized turfs
201+ - When you want to visit a galaxy turf that’s not turf-enabled, you instead ask one of its turf-enabled stars (if any) for its opinion on the layout of that galaxy-turf
202+ - Stars can coordinate to maintain agreement about what the fictional galaxy-turf looks like
203+ - When in a galaxy-turf, you can interact with any other people who have the same idea of what it looks like, even if they got it from a different star
204+ - The same can be done between galaxies for the notional “root turf”
205+ - The same can perhaps be done between any group of ships for some arbitrary unrooted turf
content/grants/2023/uc-concierge.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+
3+title = "Urbit Community Support Concierge"
4+date = "2023-02-03"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "The Urbit Community concierge will triage Urbit support issues that come in through the Urbit Community Group."
13+reward = "1 Star"
14+assignee = ["~sarlev-sarsen", "~ripnyt-ripnyt", "~doppeg-tonwel"]
15+champion = ["~poldec-tonteg"]
16+grant_id = "B0232"
17+completed = false
18+canceled = false
19+
20++++
21+
22+## Overview
23+
24+The Urbit Community concierge will triage Urbit support issues that come in through the Urbit Community Group. Some of these issues are routine, whereas occasionally complex issues arise that need to be escalated to the right people. Ideal candidates will also help synthesize support data to inform product feature work and documentation.
25+
26+## Responsibilities
27+
28+- Triage support issues in Urbit Community
29+- Write a weekly digest of issues addressed
30+- Attend a recurring meeting with Foundation staff
31+
32+## Qualifications
33+
34+- Helpfulness
35+- Familiarity with running urbit in a variety of environments (cloud server, laptop)
36+- Ability/interest in synthesizing support data and recommending new features or documentation
37+- Dilligence
38+- **Considering applications from contributors in Asia time zones UTC (GMT) +4 to UTC (GMT) +10 only.**
39+
40+## Compensation and Timeline
41+
42+1 Star for 3 months of work, at which time the agreement may be renewed.
content/grants/2023/update-mass.mdnew file+26
@@ -0,0 +1,26 @@
1++++
2+
3+title = "Modernize |mass"
4+date = "2023-03-02"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "Update the |mass utility to reinject the output into arvo from the runtime."
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1001"
17+completed = false
18+canceled = false
19+
20++++
21+
22+`|mass` is a utility for measuring a pier's resource usage. It is used for debugging and development. Currently, the output of this utility is a mixture of data from within arvo and from the runtime. This heterogeneity means that what is produced is not a noun but interleaved print statements to the terminal.
23+
24+Once `|mass` produces a noun, it can be sent to other ships over `%ames` for bug reports, collected in a central location or analyzed for further action by arvo.
25+
26+Update the `|mass` utility to reinject the output into arvo from the runtime.
content/grants/2023/urbit-ninja-strike-team.mdnew file+38
@@ -0,0 +1,38 @@
1++++
2+
3+title = "Urbit Ninja Strike Team"
4+date = "2023-05-16"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Other"]
9+
10+[extra]
11+image = ""
12+description = "Win a hackathon using Urbit."
13+reward = "1 star"
14+assignee = [""]
15+champion = ["~lagrev-nocfep"]
16+grant_id = "B0270"
17+completed = false
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0270&prefill_Grant+Name=Urbit%20Ninja%20Strike%20Team%20Bounty"
20+
21++++
22+
23+## Overview
24+
25+Urbit is a superior development platform. Show this to the world. A team using Urbit’s ability to immediately deploy a server, identity system, and peer-to-peer communications will have an edge in programming competitions.
26+
27+To obtain this bounty, you must:
28+
29+1. Participate in a hackathon and write your submission using Urbit.
30+2. If you receive an award in the hackathon, we will award you a star for highlighting Urbit.
31+
32+Not every hackathon will qualify, so please clear it with us first at `grants@urbit.org` or in office hours. (Most competitions will qualify; we just want to avoid e.g. high school competitions or the like.)
33+
34+This bounty may be claimed multiple times by multiple teams.
35+
36+## Compensation
37+
38+1 Star
content/grants/2023/urbit-react-docs.mdnew file+124
@@ -0,0 +1,124 @@
1++++
2+
3+title = "Modernize Urbit React Developer Documentation"
4+date = "2023-02-23"
5+
6+[taxonomies]
7+grant_type = ["Proposal"]
8+grant_category = ["Documentation"]
9+
10+[extra]
11+image = ""
12+description = "Modernize Urbit React Developer Documentation"
13+reward = "1 Star"
14+assignee = ["~sidnym-ladrut"]
15+champion = ["~lagrev-nocfep"]
16+grant_id = "P0242"
17+completed = true
18+canceled = false
19+
20++++
21+
22+## Rationale ##
23+
24+
25+
26+The front-end React examples provided in Urbit's developer documentation (i.e. the ["Chat Lightning Tutorial"][ex-1] and ["App School II: Full-Stack"][ex-2] pages) use legacy, class-based React patterns that have largely been phased out over the past few years in favor of [modern, hook-based React style][re-hook]. These examples should be refactored to use this modern style to improve the developer onboarding experience (as increasing amounts of [React learning materials use hooks][re-tut]) and future-proof the material presented (as the official React documentation eventually migrates to [primarily present the modern style][re-docs]).
27+
28+
29+
30+## Overview ##
31+
32+
33+
34+The content for the Urbit React examples is split across two repositories:
35+
36+
37+
38+1. [urbit/doc-examples][git-ex]: Contains the source code for the React examples.
39+
40+2. [urbit/developers.urbit.org][git-org]: Contains the web-hosted documentation for the React examples, which can be viewed at [developers.urbit.org](developers.urbit.org).
41+
42+
43+
44+Within these repositories, the content associated with the following examples needs to be updated to the modern React style:
45+
46+
47+
48+1. ["Chat Lightning Tutorial"][ex-1]: Will require edits primarily in the source references, particularly those in the ["Additional commentary" section][ex-1-edit].
49+
50+2. ["App School II: Full-Stack"][ex-2]: Will require nearly a full rewrite, though many source references will look similar.
51+
52+
53+
54+## Features in scope ##
55+
56+
57+
58+- Refactor the ["Chat" example][git-chat-src] to replace React classes with React hooks wherever possible.
59+
60+- Refactor the ["Journal" example][git-jour-src] to replace React classes with React hooks wherever possible.
61+
62+- Revise the ["Chat Lightning Tutorial"][git-chat-doc] documentation to update source references and add commentary to any new and nontrivial references.
63+
64+- Rework the ["App School II: Full-Stack"][git-jour-doc] documentation to explain the flow and key operations (i.e. peeks, pokes, and subscriptions) of the refactored React "Journal" code.
65+
66+
67+
68+## Implementation Notes ##
69+
70+
71+
72+The refactored React examples will take architectural inspiration and library
73+
74+cues from popular React applications in the Urbit ecosystem (e.g. [`%landscape`][git-landscape] and [`%sphinx`][git-sphinx]) to further improve their utility for learning developers.
75+
76+
77+
78+## Milestones and Compensation ##
79+
80+
81+
82+The grantee will receive 1 star upon fulfillment of this grant.
83+
84+
85+
86+
87+
88+[git-ex]: https://github.com/urbit/docs-examples
89+
90+[git-org]: https://github.com/urbit/developers.urbit.org
91+
92+[git-chat-src]: https://github.com/urbit/docs-examples/blob/main/chat-app/react-frontend/src/App.jsx
93+
94+[git-chat-doc]: https://github.com/urbit/developers.urbit.org/blob/main/content/guides/quickstart/chat-guide.md
95+
96+[git-jour-src]: https://github.com/urbit/docs-examples/blob/main/journal-app/ui/src/App.js
97+
98+[git-jour-doc]: https://github.com/urbit/developers.urbit.org/blob/main/content/guides/core/app-school-full-stack/7-app-logic.md
99+
100+[git-landscape]: https://github.com/tloncorp/landscape-apps
101+
102+[git-sphinx]: https://github.com/arthyn/sphinx
103+
104+
105+
106+[re-hook]: https://reactjs.org/blog/2019/02/06/react-v16.8.0.html
107+
108+[re-tut]: https://beta.reactjs.org/learn/tutorial-tic-tac-toe
109+
110+[re-docs]: https://beta.reactjs.org/
111+
112+
113+
114+[ex-1]: https://developers.urbit.org/guides/quickstart/chat-guide
115+
116+[ex-1-edit]: https://developers.urbit.org/guides/quickstart/chat-guide#additional-commentary
117+
118+[ex-2]: https://developers.urbit.org/guides/core/app-school-full-stack/7-app-logic
119+
120+[ex-2-get]: https://developers.urbit.org/guides/core/app-school-full-stack/7-app-logic#getting-entries
121+
122+[ex-2-sub]: https://developers.urbit.org/guides/core/app-school-full-stack/7-app-logic#subscription
123+
124+[ex-2-add]: https://developers.urbit.org/guides/core/app-school-full-stack/7-app-logic#add-edit-delete
content/grants/2023/vere-eyre-cache.mdnew file+38
@@ -0,0 +1,38 @@
1++++
2+
3+title = "Vere Support for Eyre Cache"
4+date = "2023-02-23"
5+
6+[taxonomies]
7+grant_type = ["Bounty"]
8+grant_category = ["Core Dev"]
9+
10+[extra]
11+image = ""
12+description = "The second of a two-part bounty to add a cache to eyre."
13+reward = "3 stars"
14+assignee = ["~watter-parter"]
15+champion = ["~rovnys-ricfer"]
16+grant_id = "B0246"
17+completed = true
18+canceled = false
19+work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefillGrant+ID=&prefillGrant+Name=Vere%20Support%20for%20Eyre%20Cache"
20+
21++++
22+
23+## Rationale
24+
25+Urbit's performance as a webserver is suboptimal, partially because the runtime does not expose a cache for GET requests. We will add a cache for GET requests that will allow inbound GET requests to avoid the Arvo event loop. This will drastically speed up the most common requests.
26+
27+This is the second of a two-part bounty. The first part, [successfully completed by ~watter-parter](https://github.com/urbit/urbit/pull/5927), added the necessary support for this feature in the Eyre vane. This part will update the Vere runtime to make use of this new affordance in Eyre. Once this bounty is completed, both PRs can be merged into the codebase and be tested for release.
28+
29+## Implementation
30+
31+The implementation of the runtime portion of this work will involve changes to the runtime to mirror the change made to Eyre in the first section. ~rovnys-ricfer will meet periodically with ~watter-parter to discuss the best course of action.
32+
33+The bounty will be successful when a cache has been successfully added and is being hit under normal usage. The test use case will be the serving of a blog or static page.
34+
35+## Compensation
36+
37+3 Stars
38+
content/grants/2023/wiki-stella-fixa-rfp.mdnew file+26
@@ -0,0 +1,26 @@
1++++
2+
3+title = "Implement a wiki on Urbit"
4+date = "2023-05-11"
5+
6+[taxonomies]
7+grant_type = ["RFP"]
8+grant_category = ["App Dev"]
9+
10+[extra]
11+image = ""
12+description = "Design and implement a wiki-like service on Urbit"
13+reward = "TBD"
14+assignee = [""]
15+champion = [""]
16+grant_id = "P1001"
17+completed = false
18+canceled = false
19+
20++++
21+
22+Urbit is a personal server, and it's a natural fit for a personal knowledge management system. It can even serve as a community knowledge management system—apps like Quorum gesture in this direction.
23+
24+A wiki-like system (but likely based on Markdown with internal references instead of Wikitext) would be a straightforward extension from existing capabilities in serving and storing pages.
25+
26+You could even imagine doing this in sync with an external interface like [Obsidian](https://obsidian.md/).
content/grants/community-meetups.mddeleted−43
@@ -1,43 +0,0 @@
1−+++
2−title = "Community Meetup"
3−date = "2022-07-22"
4−
5−[taxonomies]
6−grant_type = [ "Bounty" ]
7−grant_category = [ "Community" ]
8−
9−[extra]
10−image = ""
11−description = "Earn stars by building culture through local, recurring, and in-person urbit events"
12−reward = "1 star"
13−assignee = [""]
14−grant_id = "B0165"
15−champion = "~dalweb-donfun"
16−completed = false
17−work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0165&prefill_Grant+Name=Meetup%20Bounty"
18−+++
19−
20−# Requirements
21−- Meetups should be geographically based; if you have distributed, interest-based communities of which you are a part, check out Urbit Embassies for a way to build digital communities on Mars.
22−- Meetups must be publicized and include a public web line with event details (time, date, location), and should be actively promoted via social media, in-person recruitment, flyers, a website, etc. If you need a signal boost, email support@urbit.org.
23−- You must host a total of six meetups, with a targeted cadence of once a month.
24−- Creation and admin of an Urbit group for your locality to which all meetup attendees will be invited or a fully public group. This group should be actively maintained with info about upcoming events, copies of past presentation materials, and any other related meetup content.
25−- Sharing of materials generated in service of your meetup; similarly, things like presentation materials, flyers, and FAQs from other meetups will be made available for utilization, forking, or inspiration. For more info, contact ~sarlev-sarsen or ask for help in ~siddef/uf-meetups
26−- Completion of a pull request to the urbit.org github repo to add your meetup's information to the urbit.org/community/meetups page. If you have never submitted a pull request on github before, let us know and we will teach you how. You will need to provide the following:
27− - Location (City, State, GEO)
28− - `@p` of host(s)
29− - A link to your urbit group
30− - A link to your clearweb presence (i.e. Meetup.com)
31− - a short description of your meetup and typical events (<50 words)
32−- Regular and timely completion of the meetup report form, including:
33− - Number of attendees
34− - Email address for attendees who, in your judgement, have earned a planet
35− - Submission of presentation materials or notes on topics discussed, including presentation recordings if available.
36− - top 3-5 questions asked and the technical prowess of the questioner
37−# Encouraged Features
38−- Semi-regular presentations that introduce Urbit to newcomers, help members boot a comet, or introduce the more technical side of urbit are strongly suggested. Depending on the makeup of your meetup attendees, these presentations may be highly technical or they may be more philosophical--your call! Materials to get you started are available at ~wolref-podlex/foundation or by reaching out to ~sarlev-sarsen
39−- Having a collection of 'recommended groups' to which you can direct meetup attendees, such that they can begin to explore the Urbit network.
40−- As one of the main goals of meetups is to get people building on Urbit, once your meetup gains some traction, consider looking into proposal development for a grant on which members of your meetup can collaborate!
41−- While the specific requirements of the meetup bounty listed below can be summarized as "run a regular meetup", the overarching goal is to build a local community and onboard people to Urbit. Successful meetups will be judged by metrics like how many proposals have attendees submitted and completed and how many people have been onboarded who go on to positively contribute to the culture, technology, or creativity of the network. This does not mean that every meetup is expected to be full of developers or that a meetup that does not have a huge and ever-growing attendee list would be considered a failure. What it does mean is that community organizers and participants should become true champions for Urbit who can't help but share with everyone around them how Urbit can offer solutions to many of the pains of modern networked computing.
42−# Compensation
43−- Upon the completion of six meetup events and the associated meetup reports, one star will be paid out to the organizer.
content/groups/~bitdeg/assembly22.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Assembly 2022"
3+shortcode = "~bitdeg/assembly22"
4+description = "Official group for Urbit Assembly 2022"
5+type = "Public"
6+tile = "https://storage.googleapis.com/media.urbit.org/assembly/groupicon.png"
7+participant_range = "100+"
8++++
9+
10+The official group for Urbit Assembly 2022 in Miami. Coordinate with other attendees and get ready for a great time.
content/groups/~dalten/aera.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Quartus"
3+shortcode = "~mister-hilper-dozzod-dalten/quartus"
4+description = "Applications, Tech Support, and Community with Quartus"
5+type = "Public"
6+tile = "https://freedom-club.sfo2.digitaloceanspaces.com/rabsef-bicrym/2022.2.03..19.39.35-vertical_on_corporate_by_logaster.png"
7+participant_range = "200+"
8++++
9+
10+The Quartus public group is a place to find up to date application distribution information, get hands on tech support, and build community with other urbiters using the tools we build.
content/groups/~dibref-labter/arbit.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "arbit"
3+shortcode = "~dibref-labter/arbit"
4+type = "Public"
5+tile = "https://upload.wikimedia.org/wikipedia/commons/9/92/Johann_Melchior_Dinglinger_-_Sun_mask_with_facial_features_of_August_II_%28the_Strong%29_as_Apollo%2C_the_Sun_God_-_Google_Art_Project.jpg"
6+participant_range = "32"
7++++
8+
9+urbit argentina
content/groups/~dister-dozzod-lapdeg/battery-payload.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "[battery payload]"
3+shortcode = "~dister-dozzod-lapdeg/battery-payload"
4+type = "Public"
5+tile = "#FFCDE0"
6+participant_range = ""
7++++
8+
9+The official developer community group of `[battery payload]`.
content/groups/~halbex-palheb/uf-public.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "UF Public"
3+shortcode = "~halbex-palheb/uf-public"
4+description = "Public group for the Urbit Foundation"
5+type = "Public"
6+tile = "https://interstellar.nyc3.digitaloceanspaces.com/battus-datsun/2022.11.07..19.39.22-Sig.png"
7+participant_range = "100+"
8++++
9+
10+The best place to get the latest updates from the team at the Urbit Foundation.
content/groups/~hocwyn-tipwex/uqbar-event-horizon-forever.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Uqbar Event Horizon"
3+shortcode = "~hocwyn-tipwex/uqbar-event-horizon-forever"
4+type = "Public"
5+tile = "https://fra1.digitaloceanspaces.com/habsulbucket/habsul-rignyr/2022.12.31..08.53.06-uqbar.png"
6+participant_range = "600+"
7++++
8+
9+Uqbar Event Horizon is the place to learn about and discuss Urbit's own Ethereum zk-rollup, Uqbar.
10+
11+Uqbar are also the makers of EScape and %pokur. To learn more about Uqbar, join the Event Horizon or find us on the web at https://uqbar.network.
content/groups/~martyr-sarlev-sarsen/assembly-hackers.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Assembly Hackers"
3+shortcode = "~martyr-sarlev-sarsen/assembly-hackers"
4+description = "For participants of the 2022 Assembly Hackathon"
5+type = "Public"
6+tile = "#000000"
7+participant_range = "20+"
8++++
9+
10+Originally generated for participants of the 2022 Assembly Hackathon, this group is being made public through the end of 2022 so that the broader community can access the full set of hackathon submissions and project groups.
content/groups/~mister-hilper-dozzod-dalten/quartus.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Quartus"
3+shortcode = "~mister-hilper-dozzod-dalten/quartus"
4+description = "Applications, Tech Support, and Community with Quartus"
5+type = "Public"
6+tile = "https://freedom-club.sfo2.digitaloceanspaces.com/rabsef-bicrym/2022.2.03..19.39.35-vertical_on_corporate_by_logaster.png"
7+participant_range = "200+"
8++++
9+
10+The Quartus public group is a place to find up to date application distribution information, get hands on tech support, and build community with other urbiters using the tools we build.
content/groups/~nibset-napwyn/tlon-public.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Tlon Public"
3+shortcode = "~nibset-napwyn/tlon"
4+description = "Updates, announcements, and broadcasts from Tlon."
5+type = "Public"
6+tile = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/tlon.png"
7+participant_range = "200+"
8++++
9+
10+Tlon Public is a hub for the community-at-large to learn about what we're working on, hear from team members on their processes, and see some of the references that influence their work.
content/groups/~rondev/group-discovery.mddeleted−10
@@ -1,10 +0,0 @@
1−+++
2−title = "Group Discovery"
3−shortcode = "~rondev/group-discovery"
4−description = "A group for finding other groups"
5−type = "Public"
6−tile = "https://urbit.me/images/icons/icon-512x512.png"
7−participant_range = "1000+"
8−+++
9−
10−A group for finding other groups
content/groups/~sillus-mallus/toki-pona.md+1
@@ -3,6 +3,7 @@ title = "toki pona"
33shortcode = "~sillus-mallus/toki-pona"
44type = "Public"
55tile = "https://personal-server.fra1.digitaloceanspaces.com/sillus-mallus/tp-lg.png"
6+description = "The world's smallest language."
67participant_range = "100"
78+++
89
content/groups/~witbep-witbep/embark.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Embark"
3+shortcode = "~witbep-witbep/embark"
4+type = "Public"
5+tile = "https://i.imgur.com/cup57ou.jpg"
6+participant_range = "90+"
7++++
8+
9+Get your permanent ID on Embark. Embark is a group that centralizes info on who is selling or distributing planets, as well as the latest info on individual hosting services and independently produced Urbit-related merchandise.
10+
11+As a star or planet owner, you can also find sponsors willing to adopt you should your existing sponsor be inactive.
content/groups/~wolref-podlex/foundation.mddeleted−10
@@ -1,10 +0,0 @@
1−+++
2−title = "Foundation"
3−shortcode = "~wolref-podlex/foundation"
4−description = "Town Square for the Urbit Foundation"
5−type = "Public"
6−tile = "https://interstellar.nyc3.digitaloceanspaces.com/battus-datsun/2022.6.10..21.28.21-urbit-inverted.png"
7−participant_range = "1000+"
8−+++
9−
10−The best place to get in touch with the team at the Urbit Foundation.
content/highlights/highlight-1.mdnew file+6
@@ -0,0 +1,6 @@
1++++
2+title = "Using Urbit in 2023"
3+url ="https://urbit.org/blog/using-urbit-in-2023"
4+image = "https://storage.googleapis.com/media.urbit.org/blog/usingurbit-2023.jpg"
5+description = "There are more ways to run Urbit than ever, and more options coming soon."
6++++
content/highlights/highlight-2.mdnew file+6
@@ -0,0 +1,6 @@
1++++
2+title = "The Roadmap"
3+image = "https://storage.googleapis.com/media.urbit.org/site/featured/roadmap-icon.jpg"
4+url="https://roadmap.urbit.org/"
5+description = "Explore the technical plan for making Urbit ready for mass adoption."
6++++
content/highlights/highlight-3.mdnew file+6
@@ -0,0 +1,6 @@
1++++
2+title = "Hoon School Live Summer '23"
3+image = "https://storage.googleapis.com/media.urbit.org/site/featured/hsl-june-2023.png"
4+url="https://developers.urbit.org/courses/hsl"
5+description = "Sign up now to learn the foundations of Urbit development."
6++++
content/ids/ballun-dilsup.mdnew file+7
@@ -0,0 +1,7 @@
1++++
2+ship = "~ballun-dilsup"
3+nickname = "Bus Driver Chris"
4+bgColor = "#000000"
5+image = ""
6++++
7+
content/ids/bintud-bitnev.mdnew file+8
@@ -0,0 +1,8 @@
1++++
2+ship = "~bintud-bitnev"
3+nickname = ""
4+bgColor = "#008080"
5+image = ""
6++++
7+
8+feelsgood.jpg
content/ids/botbyn-dolrum.mdnew file+7
@@ -0,0 +1,7 @@
1++++
2+ship = "~botbyn-dolrum"
3+nickname = ""
4+bgColor = "#000000"
5+image = ""
6++++
7+
content/ids/datder-sonnet.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+ship = "~datder-sonnet"
3+nickname = "Tom Holford"
4+bgColor = "#ffffff"
5+image = ""
6++++
7+
8+Engineer at Tlon. Code slinger, nature enjoyer, hockey player.
9+
10+
11+- [Portfolio](https://tholf.org/)
12+- [Github](https://github.com/tomholford)
13+- [Twitter](https://twitter.com/tholford0)
content/ids/datnut-pollen.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+ship = "~datnut-pollen"
3+nickname = "jonathan"
4+bgColor = "#000000"
5+image = "https://datnut-pollen.nyc3.digitaloceanspaces.com/datnut-pollen/2022.8.09..17.17.13-298319738_1121477868442197_1654123872496208254_n.jpg"
6++++
7+
8+Engineer at Tlon. Before that, I was a mathematician studying quantum topology
9+and quantum computing.
10+
11+Interested in applying ideas from swarm intelligence, biomimicry, and applied
12+category theory to Urbit, especially in the context of industrial internet of things.
13+
14+Blog at [Discordja](https://datnut-pollen.discordja.net/discordja)
15+
content/ids/datryn-ribdun.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+ship = "~datryn-ribdun"
3+nickname = ""
4+bgColor = "#f0aa33"
5+image = ""
6++++
7+
8+Developer, explorer, Urbit-fanboy
9+
10+See my work on github, or message me on the network. I'm also addicted to Trill, so follow me there.
11+
12+[https://github.com/datryn-ribdun/](https://github.com/datryn-ribdun/)
content/ids/datsyr-radser.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+ship = "~datsyr-radser"
3+nickname = "Urbit Guide"
4+bgColor = "#000000"
5+image = "https://urbitguide.com/wp-content/uploads/2023/03/Urbit-Guide-website.jpg"
6++++
7+
8+Urbit Guide offers clear explanations of what Urbit is and how it works, without any technical jargon that might confuse or overwhelm newcomers. Whether you're interested in exploring the decentralized web or just want to learn more about this innovative platform, Urbit Guide has everything you need to get started. Check out today and start your Urbit journey with confidence.
9+
10+Website: https://urbitguide.com/
11+
12+Twitter: https://twitter.com/urbitguide
content/ids/dopbet-larped.mdnew file+7
@@ -0,0 +1,7 @@
1++++
2+ship = "~dopbet-larped"
3+nickname = ""
4+bgColor = "#000000"
5+image = ""
6++++
7+
content/ids/finmep-lanteb.md+15−3
@@ -5,7 +5,18 @@ bgColor = "#0dd33f"
55image = ""
66+++
77
8−The infamous hacker known as Urbit
8+**THE INFAMOUS HACKER KNOWN AS URBIT**
9+
10+General Manager of the Urbit hockey team
11+
12+Tlön employee
13+
14+Urbit Chess Ecosystem:
15+https://github.com/thecommons-urbit/chess
16+
17+Hoon Language Plugin for IntelliJ IDEA:
18+https://plugins.jetbrains.com/plugin/19294-hoon-language
19+https://github.com/ashelkovnykov/idea-hoon-plugin
920
1021Urbit FAQ:
1122https://github.com/ashelkovnykov/urbit-faq
@@ -13,5 +24,6 @@ https://github.com/ashelkovnykov/urbit-faq
1324Urbit Hosting:
1425https://github.com/ashelkovnykov/urbit-hosting
1526
16−Urbit Wordlists:
17−https://github.com/ashelkovnykov/urbit-wordlists
27+Urbit Wordlists (used by Gonetia):
28+https://github.com/ashelkovnykov/urbit-wordlists
29+https://github.com/tomholford/gonetia
content/ids/haddef-sigwen.md+4−2
@@ -5,6 +5,8 @@ bgColor = "#dcedce"
55image = "https://s3.us-east-1.amazonaws.com/haddefsigwen1/haddef-sigwen/2021.2.24..20.22.37-bw400.png"
66+++
77
8−Tlon Corporation (2019-2021), Urbit Foundation (2022-)
8+[Tlon Corporation](https://tlon.io) (2019-2021), [Reciprocal Ltd.](https://reciprocal.ltd) (2022-)
99
10−Lawful neutral, interactive media artist, mercenary for hire. [Decept.org](https://decept.org) proprietor. More projects at [my website](https://matildepark.ca).
10+Lawful neutral, "computational creative", all-purpose gynoid. [Decept.org](https://decept.org) proprietor.
11+
12+Previous interactive and creative projects at [my website](https://matildepark.ca).
content/ids/hocmed-lidrev.mdnew file+8
@@ -0,0 +1,8 @@
1++++
2+ship = "~hocmed-lidrev"
3+nickname = ""
4+bgColor = "#4E9EFD"
5+image = ""
6++++
7+
8+Software Developer
content/ids/lagrev-nocfep.md+5−3
@@ -1,6 +1,8 @@
11+++
22ship = "~lagrev-nocfep"
3−nickname = "𐐝𐐮𐐾𐐮𐑊𐐰𐑌𐐻𐐨"
4−bgColor = ""
5−image = "https://pbs.twimg.com/profile_images/1508135477664268288/5VhAqOUI_400x400.jpg"
3+nickname = "𐐝𐐮𐐾𐐮𐑊𐐰𐑌𐐻𐐨 / Sigilante"
4+bgColor = "#000000"
5+image = "https://raw.githubusercontent.com/sigilante/pixiesticks/master/sigil-jaguar-cloth.png"
66+++
7+
8+Urbit Foundation · Learn Deseret · Scholia Pugillātōria
content/ids/monnys-riphet.mdnew file+7
@@ -0,0 +1,7 @@
1++++
2+ship = "~monnys-riphet"
3+nickname = "yy"
4+bgColor = "#000000"
5+image = ""
6++++
7+
content/ids/nallux-dozryl.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+ship = "~nallux-dozryl"
3+nickname = ""
4+bgColor = "#000000"
5+image = "https://urbitas.sgp1.digitaloceanspaces.com/nallux-dozryl/2022.10.31..16.59.28-image.png"
6++++
7+
8+Data should belong to the individual.
9+
10+Software engineer at nativeplanet.io
11+
12+My work: https://github.com/nallux-dozryl
content/ids/sarlev-sarsen.md+2−2
@@ -2,7 +2,7 @@
22ship = "~sarlev-sarsen"
33nickname = ""
44bgColor = "#ffffff"
5−image = ""
5+image = "https://sarlev-sarsen.sfo3.digitaloceanspaces.com/sarlev-sarsen/2022.12.15..03.13.58-roof%20koreans%20voting.jpg"
66+++
77
8−liberty, growth, crypto, hijinks, innovation, agency. allocating capital via grants from the urbit foundation.
8+liberty, growth, crypto, hijinks, innovation, agency.
content/ids/tagdyl-ponwyn.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+ship = "~tagdyl-ponwyn"
3+nickname = ""
4+bgColor = "#bbdddd"
5+image = ""
6++++
7+
8+In my day job I do R&D and bioinformatics to make DNA sequencing kits robust and easy to use.
9+
10+I believe Urbit is the future, or at least the one I want, so in my free time I am working on learning Hoon to help build it.
content/ids/tambes-palped.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+ship = "~tambes-palped"
3+nickname = "Hackalife"
4+bgColor = "#000000"
5+image = ""
6++++
7+
8+Ali Hackalife.
9+Based in Germany.
10+23, Artist, Developer, Wikipedia Editor.
content/ids/tobrun-tomnet.mdnew file+8
@@ -0,0 +1,8 @@
1++++
2+ship = "~tobrun-tomnet"
3+nickname = "somkirann"
4+bgColor = "#000000"
5+image = ""
6++++
7+
8+1st page being set-up
content/ids/topfet-parmed.mdnew file+6
@@ -0,0 +1,6 @@
1++++
2+ship = "~topfet-parmed"
3+nickname = ""
4+bgColor = "#000000"
5+image = ""
6++++
content/organizations/assemblycapital.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Assembly Capital"
3+description = "engineer-led early stage vc investing in things that matter, mostly urbit"
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/assemblycapital.jpg"
5+URL = "https://assembly.capital"
6+twitter = "assemblycap"
7+ships = ["~nodmyn-dosrux"]
8++++
9+
10+engineer-led early stage vc investing in things that matter, mostly urbit
content/organizations/dalten.md+2−1
@@ -3,7 +3,8 @@ title = "Dalten Collective"
33description = "Dalten is a distributed fellowship of like minded individuals."
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/dalten.jpg"
55URL = "https://dalten.org"
6−ships = ["~dalten", "~magped-magped-rabsef-bicrym", "~mirler-dozzod-talwet"]
6+twitter = "_dalten"
7+ships = ["~dalten", "~mirler-dozzod-talwet"]
78+++
89
910Dalten is a distributed fellowship of like minded individuals. We are a sustainable for-profit member-focused organization devoted to the individual success of every member. Dalten practices and builds sovereignty both personal and collective.
content/organizations/holium.md+3−2
@@ -1,9 +1,10 @@
11+++
22title = "Holium"
33description = "Holium's mission is to enable the networked state."
4−image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/holium.png"
4+image = "https://media.urbit.org/site/ecosystem/organizations/holium-logo.jpg"
55URL = "https://holium.com"
6−ships = ["~livdel-binmun-lomder-librun", "~lomder-librun"]
6+twitter = "HoliumCorp"
7+ships = ["~livdel-binmun-lomder-librun", "~lomder-librun", "~hostyv"]
78+++
89
910Holium's mission is to enable the networked state, starting by enabling DAOs, building digitally sovereign colonies, and then making them physically sovereign. Are you ready to build your world?
content/organizations/labyrinthdao.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Labyrinth DAO"
3+description = "Labyrinth DAO is a new decentralized autonomous organization investing in Urbit projects."
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/labyrinth.jpeg"
5+URL = "https://labyrinthdao.io/"
6+ships = []
7+twitter = "labyrinth_dao"
8++++
9+
10+Labyrinth DAO is a new decentralized autonomous organization investing in Urbit projects. Supported by [Tribute Labs](https://tributelabs.xyz/), Labyrinth DAO will foster the growth and development of Urbit as it paves the way for the new internet. Find Labyrinth DAO on Twitter or connect at labyrinthdao.io to get involved.
content/organizations/mars-review-of-books.md+1
@@ -3,6 +3,7 @@ title = "The Mars Review of Books"
33description = "The Mars Review of Books is a magazine in print and on Urbit which combines ruthlessly intelligent and fearless sense-making on subjects of global importance with today’s most stylish belletristic writing on contemporary arts and culture."
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/marsreview.jpg"
55URL = "https://store.marsreview.org"
6+twitter = "marsreviewer"
67ships = []
78+++
89
content/organizations/nativeplanet.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Native Planet"
3+description = "Native Planet builds Urbit-centric hardware and software that simplifies sovereign self hosting and ship management."
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/nativeplanet2.png"
5+URL = "https://www.nativeplanet.io/"
6+twitter = "NativePlanetIO"
7+ships = []
8++++
9+
10+Native Planet builds Urbit centric hardware and software that simplifies sovereign self hosting and ship management. Native Planet's open source software enables users to turn nearly any computer into an Urbit dedicated server in minutes.
content/organizations/quartus.md+4−3
@@ -3,7 +3,8 @@ title = "Quartus by Dalten"
33description = "We build software using the novel affordances of Urbit."
44image = "https://freedom-club.sfo2.digitaloceanspaces.com/ab_Quartus-03.jpg"
55URL = "https://www.quartus.co/"
6−ships = ["~mister-dozzod-dalten", "~laddys-dozzod-dalten", "~magped-magped-rabsef-bicrym", "~doller-doller-rabsef-bicrym"]
6+ships = ["~mister-hilper-dozzod-dalten", "~dister-dozzod-dalten"]
7+twitter = "QuartusCo"
78+++
89
910### Quartus is Fulfilling Urbit's Covenant with Users
@@ -16,6 +17,6 @@ We build software, according to specification, on a contract basis. Contact one
1617
1718### Quartus is
1819
19−Headed by [~rabsef-bicrym](https://urbit.org/ids/~rabsef-bicrym), with Chief Products Officer [~sogrum-savluc](https://urbit.org/ids/~sogrum-savluc) and Chief Technical Officer [~wicrum-wicrun](https://urbit.org/ids/~wicrum-wicrun).
20+Headed by [~rabsef-bicrym](https://urbit.org/ids/~rabsef-bicrym), with Chief Product Officer [~sogrum-savluc](https://urbit.org/ids/~sogrum-savluc), and Chief Technical Officer [~wicrum-wicrun](https://urbit.org/ids/~wicrum-wicrun), along with [~sarlev-sarsen](https://urbit.org/ids/~sarlev-sarsen) and [~simfur-ritwed](https://urbit.org/ids/~simfur-ritwed).
2021
21−Founded by [~sicdev-pilnup](https://urbit.org/ids/~sicdev-pilnup) and ~rabsef-bicrym, as a product of the [Dalten Collective](https://dalten.org/).
22+Founded by [~sicdev-pilnup](https://urbit.org/ids/~sicdev-pilnup) and [~rabsef-bicrym](https://urbit.org/ids/~rabsef-bicrym), as a product of the [Dalten Collective](https://dalten.org/).
content/organizations/sortug.md+1
@@ -4,6 +4,7 @@ description = "Sortug is an Urbit development DAO based on Earth Time UTC+08:00.
44image = "https://s3.urbit.cloud/sortug/logo.png"
55URL = "https://sortug.com"
66ships = ["~sortug", "~polwex", "~sonwet", "~dovwex", "~sovwex", "~ticrel", "~nodwet"]
7+twitter = "SortugDev"
78+++
89
910Sortug is a DAO focused on software development and promotion of Urbit to a global audience. We are focused on creating and distributing Urbit applications and on integrating Urbit in Earth business and communities through innovative gatekeeping ideas.
content/organizations/third-earth.md+1
@@ -4,6 +4,7 @@ description = "Third.Earth is an Urbit hosting and development company focused o
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/thirdearth.png"
55URL = "https://third.earth"
66ships = ["~botwet"]
7+twitter = "ThirdEarth3"
78+++
89
910Third.Earth is an Urbit hosting and development company focused on bridging Web2 capabilities to the Urbit ecosystem. We currently assist Urbit startups with their hosting needs with our fully automated platform integrated seamlessly with their current UI/UX and workflow. By utilizing the latest in cloud technology, we help bring Urbit to the masses.
content/organizations/tirrel.md+1
@@ -4,6 +4,7 @@ description = "Tirrel Corporation is an Urbit product studio."
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/Tirrel%20Corp%20Logo.png"
55URL = "https://tirrel.io"
66ships = ["~tirrel"]
7+twitter = "tirrelcorp"
78+++
89
910### Tirrel Corporation is an Urbit product studio.
content/organizations/tlon.md+2−1
@@ -3,7 +3,8 @@ title = "Tlon"
33description = "The first developer of Urbit. Their work continues to maintain core infrastructure development in addition to designing products for communities on the network."
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/tlon.png"
55URL = "https://tlon.io"
6−ships = ["~mister-dister-dozzod-dozzod", "~lander-dister-dozzod-dozzod"]
6+ships = ["~mister-dister-dozzod-dozzod", "~lander-dister-dozzod-dozzod", "~sogryp-dister-dozzod-dozzod"]
7+twitter = "tloncorporation"
78+++
89
910[Tlon Corporation](https://tlon.io) is the first developer of Urbit, and their work continues to maintain core infrastructure development in addition to designing products for communities on the network. Tlon’s primary products are Hosting, cloud storage for your urbit, Landscape, an operating system and interface, and Groups, a communication suite.
content/organizations/uqbar.md+2−1
@@ -3,7 +3,8 @@ title = "Uqbar"
33description = "Uqbar is a one-stop coding environment that makes writing and deploying smart contracts simple, efficient, and secure."
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/uqbar.png"
55URL = "https://uqbar.network"
6−ships = ["~dister-fabnev-hinmur", "~hocwyn-tipwex"]
6+ships = ["~fabnev-hinmur", "~dister-dozzod-bacdun", "~hocwyn-tipwex"]
7+twitter = "uqbarnetwork"
78+++
89
910Uqbar is a one-stop coding environment that makes writing and deploying smart contracts simple, efficient, and secure.
content/organizations/urbit-foundation.md+1
@@ -4,6 +4,7 @@ description = "Urbit Foundation is a non-profit organization whose mission is to
44image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/urbit-foundation.png"
55URL = "https://urbit.org"
66ships = ["~lapdeg"]
7+twitter = "urbitfoundation"
78+++
89
910Urbit Foundation is a non-profit organization whose mission is to ensure Urbit's success as a technology.
content/organizations/zorp.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Zorp"
3+description = "We assure critical computation using zero-knowledge proofs"
4+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/organizations/zorp.jpeg"
5+URL = "https://zorp.io/"
6+twitter = "ZorpZK"
7+ships = []
8++++
9+
10+Zorp has built a secure-by-design zero-knowledge virtual machine (zkVM) with a uniquely minimal software supply chain which utilizes Nock as its instruction set. Nock, Urbit’s low-level language, is a famously simple instruction set. That property aligns itself well with what you might create if you were designing a language from first principles to do zero-knowledge proofs. Zorp’s zkVM could unlock new possibilities for crypto and more. Check back at Zorp’s website and Twitter for more info.
content/overview/people-history.md+36−31
@@ -8,61 +8,66 @@ image = "https://media.urbit.org/site/understanding-urbit/project-history/projec
88
99So who builds this thing? Where does it come from? What’s the history?
1010
11−Today, Urbit is built and maintained by three organizations, a community of contributors and core developers, infrastructure (star) operators, and governance (galaxy) node owners.
11+Urbit is an open-source project that anyone can work on. The Urbit Foundation, a non-profit organization, is charged with shepherding the network toward a successful future. [Tlon](https://tlon.io/) was the first private company founded for the purposes of working on Urbit, back in 2013. Now there are several more.
12+
13+These include [Uqbar](https://uqbar.network/), [Holium](https://www.holium.com/), [Tirrel](https://tirrel.io/), [Native Planet](https://nativeplanet.io/), and others. Beyond that, an ecosystem has sprung up around Urbit that includes [funds](https://assembly.capital/), [DAOs](https://labyrinthdao.io/), and [publications](https://marsreview.org/). And of course there are many community contributors, many of whom have received [grants](https://urbit.org/grants) from the Urbit Foundation.
1214
1315Let’s talk first about these individual groups within the Urbit community, then about the history of the project and how it came to be.
1416
1517Organizations {% .font-bold .subpixel-antialiased .pt-8 %}
1618
17−There are currently three principal organizations involved in Urbit’s development and maintenance: Tlon, Urbit.live and the Urbit Foundation.
19+The Urbit Foundation was formally established in 2021 when it split off from Tlon. The Foundation runs the grants program, maintains [urbit.org](https://urbit.org/), the [network explorer](https://network.urbit.org/), [education](https://developers.urbit.org/courses/hsl), and it organizes Urbit events like [Assembly](https://assembly.urbit.org/). Recently, the Urbit Foundation has also taken the lead on Urbit's [core development](https://roadmap.urbit.org/).
1820
19−Tlon has been around since 2013 or so, and is primarily focussed on the development of Urbit OS and its user experience. Urbit.live was started in 2018 to make the on ramp into Urbit as easy as possible. Both companies contribute regularly to the code base.
21+[Tlon Corporation](https://tlon.io/) was founded in 2013 to bootstrap Urbit. Currently it is building a hosting service and a suite of Urbit applications, including [Groups](/applications/~sogryp-dister-dozzod-dozzod/groups), [Talk](/applications/~sogryp-dister-dozzod-dozzod/talk), and Small Talk.
2022
21−Tlon was originally granted about half of the Urbit ID address space, and has used that to fund its operations so far. Over time, Tlon plans to offer hosting and services to make using Urbit as easy as possible.
23+[Tirrel Corporation](https://tirrel.io/) was founded in 2021, it creates tools for creators to build their communities, share content, and make money. most notably the subscription application [Studio](https://urbit.studio/). They also produce the Urbit desktop environment Scene.
2224
23−Urbit.live started selling Urbit IDs very early once that became possible, and also plans to offer services within the Urbit ecosystem.
25+[Uqbar](http://uqbar.network), founded in 2022, is working on an L2 blockchain on Urbit. Uqbar uses Urbit’s native language, Hoon, for its smart contracts, enabling developers to write smart contracts and decentralized off-chain applications that utilize them all in one language and stack. They have also produced the Urbit apps Pongo, Pokur, and [Blog](/applications/~hanrut-sillet-dachus-tiprel/blog). 
2426
25−The Urbit Foundation was formally established in 2021. The Foundation runs the grants program, maintains urbit.org, the network explorer, and organizes Urbit events like Assembly.
27+[Holium](http://holium.com), founded in 2022, builds Realm. An Urbit-backed desktop (and soon mobile) environment focused on collaborative computing. Realm allows you to create Spaces in which a group of people interact with the same applications, e.g. shared dictionary, meme library, group chat, voice chats, shared cursors, code editors, web browser.
2628
27−The community of contributors and core developers has been steadily contributing to the code base since before Tlon existed, and they’re still going strong. They can primarily be found on Urbit itself, in the Urbit Community ([~bitbet-bolbel/urbit-community](/groups/~bitbet-bolbel/urbit-community)), the urbit-dev mailing list and on GitHub.
29+[Quartus](http://quartus.co/), founded in 2022, provides custom tooling stacks for Urbit companies. They produce applications such as [Keep](/applications/~dister-dozzod-dalten/keep), a recovery tool for Urbit computers and Urdl, an Urbit version of the popular Wordl game. 
2830
29−Timeline {% .font-bold .subpixel-antialiased .pt-8 %}
31+[Zorp](http://zorp.io), founded in 2022, works on Zero Knowledge proofs of Nock.
3032
31−At the beginning, Urbit was just a few people with the right combination of imagination and discipline to try to rebuild computing.
33+The community of contributors and core developers has been steadily contributing to the code base since before the Urbit Foundation existed, and they're still going strong. They can primarily be found on Urbit itself, in the Urbit Community group [~bitbet-bolbel/urbit-community](/groups/~bitbet-bolbel/urbit-community), the [urbit-dev](https://groups.google.com/a/urbit.org/g/dev?pli=1) mailing list and on [GitHub](https://github.com/urbit). See also The Urbit Foundation's public group at [~halbex-palheb/uf-public](/groups/~halbex-palheb/uf-public).
3234
33−**2002**
34−Urbit starts as an open-ended personal project. An “independent study PhD” to reinvent computing for a network-centric world.
35+Timeline {% .font-bold .subpixel-antialiased .pt-8 %}
3536
36−**2008**
37−Nock, the foundation of Urbit, works. Coming in at 32 lines of code, that’s 1 line of code every two months.
37+In the beginning, Urbit was just a few people with the right combination of imagination and discipline to try to rebuild computing.
3838
39−**2012**
40−Hoon, Urbit’s programming language, compiles itself to Nock. Writing Hoon is much easier than writing Nock.
39+**2022**
40+The Urbit Foundation's split from Tlon becomes complete, and the Foundation organizes [Urbit NYC](https://urbit.org/groups/~ladtem-filmyr/urbit-ny-week) and [Assembly 2022](https://assembly.urbit.org/) in Miami while launching a highly successful education project, new developer documentation and many other things. Read the Foundation's full annual report [here](https://storage.googleapis.com/media.urbit.org/site/overview/~2023%20Retrospective%20%26%20Plan%20PUBLIC.pdf). New Urbit companies Uqbar, Holium, Quartus, and Zorp are formed.
4141
42−**2013**
43−Arvo, Urbit’s OS kernel, boots and the first live Urbit network is started with a command-line chat.
42+**2021**
43+Tlon hosts the first Urbit Assembly and the Urbit Foundation is formally organized.
4444
45−**2014**
46−Tlon is founded to help support Urbit development (and is < 8 people for the next four years).
45+**2019**
46+Tlon spends the year stabilizing Arvo and building Landscape.
4747
48−**2015**
49−Urbit has its first web interface and serves its own website.
48+**2018**
49+Tlon sells about 8% of its stake in the network to accelerate Urbit development.
50+
51+**2017**
52+Urbit’s test network runs for ten months without a reboot. Tlon's private sale of address space, shared only with its mailing list, sells out in six hours — limit two per person.
5053
5154**2016**
5255The first sale of Urbit address space sells out in four hours.
5356
54−**2017**
55−Our test network runs for ten months without a reboot.
57+**2015**
58+Urbit has its first web interface and serves its own website.
5659
57−Our private sale, shared only with our mailing list, sells out in six hours — limit two per person.
60+**2014**
61+Tlon is founded to help support Urbit development (and is < 8 people for the next four years).
5862
59−**2018**
60−Tlon sells about 8% of its stake in the network to accelerate Urbit development. urbit.live gets going and starts selling Urbit IDs to the public.
63+**2013**
64+Arvo, Urbit’s OS kernel, boots and the first live Urbit network is started with a command-line chat.
6165
62−**2019**
63−Tlon spends the year stabilizing Arvo and building Landscape.
66+**2012**
67+Hoon, Urbit’s programming language, compiles itself to Nock. Writing Hoon is much easier than writing Nock.
6468
65−**2021**
66−Tlon hosts the first Urbit Assembly and the Urbit Foundation is formally organized.
69+**2008**
70+Nock, the foundation of Urbit, works. Coming in at 32 lines of code, that’s 1 line of code every two months.
6771
68−Building Urbit is about building a future where technology doesn’t control us. Instead, we look forward to a future where technology is simpler, more reliable and less invasive.
72+**2002**
73+Urbit starts as an open-ended personal project. An “independent study PhD” to reinvent computing for a network-centric world.
content/overview/urbit-id.md+1−1
@@ -25,7 +25,7 @@ The Urbit ID registry is live and deployed to the Ethereum blockchain. Urbit ID
2525
2626Each Urbit ID is really just a number. From that number we generate a pronounceable name and a visually identifiable sigil. ~dalwel-fadrun is 3,509,632,436, for example.
2727
28−Urbit IDs are distributed by a sponsorship tree. At the top of the tree are 28 (256) galaxies. Each galaxy issues 28 stars, making a total of 2^16^ (65K). Stars then each can issue 216 planets, making for 2^32^ (~4B). As you might expect, each planet issues 2^32^ moons.
28+Urbit IDs are distributed by a sponsorship tree. At the top of the tree are 2^8^ (256) galaxies. Each galaxy issues 2^8^ stars, making a total of 2^16^ (65K). Stars then each can issue 2^16^ planets, making for 2^32^ (~4B). As you might expect, each planet issues 2^32^ moons.
2929
3030![](https://media.urbit.org/site/overview/overview-id.png)
3131
content/podcasts/2022-02-27_the-combine.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "The Combine with ~poldec-tonteg"
3+podcast = "The Stack"
4+date = "2022-02-27"
5+URL = "https://podcasts.apple.com/bh/podcast/the-combine-with-poldec-tonteg/id1539596322?i=1000552343329"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with Anthony Arroyo, better known on the network as poldec-tonteg.
10+
11+
12+Anthony is now HMFIC at the Combine, an Urbit Foundation initiative to invest in teams who want to build businesses on Urbit. In the following episode, Andy and I will offer a masterclass in pitching a podcast. And as usual, the Stack is pitch perfect, baby.
13+
content/podcasts/2022-03-04_nockin.mdnew file+18
@@ -0,0 +1,18 @@
1++++
2+title = "This Man's a-Nockin'"
3+podcast = "The Stack"
4+date = "2022-03-04"
5+URL = "https://podcasts.apple.com/bh/podcast/this-mans-a-nockin/id1539596322?i=1000552917999"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week, we speak with Neal Davis, otherwise known as ~lagrev-nocfep.
10+
11+
12+Our topics this week are:
13+
14+
15+The advantages of Urbit over traditional development paradigms.
16+
17+Hoon school and how to get some. What species of lunatic writes Hoon. And pedagogy and the performance of teaching.
18+
content/podcasts/2022-03-11_mars-review.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Ep 034: Mars Review with ~librex-dozryc"
3+podcast = "The Stack"
4+date = "2022-03-11"
5+URL = "https://podcasts.apple.com/bh/podcast/ep-034-mars-review-with-librex-dozryc/id1539596322?i=1000553689792"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with Noah Kumin (~librex-dozryc) about the Mars Review of Books, an attempt to bring the forces of NYC and Urbit together to make a product inspired by the early NYRB.
10+
11+
12+
content/podcasts/2022-04-07_in-lehmans-terms.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "Ep 037 In Lehman's Terms with ~wolref-podlex"
3+podcast = "The Stack"
4+date = "2022-04-07"
5+URL = "https://podcasts.apple.com/bh/podcast/ep-037-in-lehmans-terms-with-wolref-podlex/id1539596322?i=1000556504088"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with Josh Lehman, Executive Director of the Urbit Foundation.
10+
11+
12+We discuss Foundation initiatives for education and future projects, the art of pouring tea, and the role and constitution of the Urbit Foundation Board.
content/podcasts/2022-04-19_robot-opera.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Ep 038: Robot Opera with ~rovnys-ricfer"
3+podcast = "The Stack"
4+date = "2022-04-19"
5+URL = "https://podcasts.apple.com/bh/podcast/ep-038-robot-opera-with-rovnys-ricfer/id1539596322?i=1000558054281"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with Ted Blackman, Engineering Manager at Tlon.
10+
11+We discuss Robot Opera, Inertial Navigation Systems, Y Combinator, the failure of Gesture Based Computer Interfaces, and the looming release of the remote scry protocol, which promises, upon release, to complete the system of German Idealism.
content/podcasts/2022-05-22_cincinnati-chili.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Ep039: Cincinnati Chili with ~ritpub-sibsyl"
3+podcast = "The Stack"
4+date = "2022-05-22"
5+URL = "https://podcasts.apple.com/us/podcast/ep039-cincinnati-chili-with-ritpub-sibsyl/id1539596322?i=1000559688466"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with Edward Amsden, engineer at Tlon and better known to the network as ~ritpub-sibsyl. We cover Cincinnati Chili, the warm dumpster runoff of Javascript, the origins of React, UrchatFM, and New Mars.
10+
content/podcasts/2022-06-04_market-bedshite.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Market Bedshite"
3+podcast = "The Stack"
4+date = "2022-06-04"
5+URL = "https://podcasts.apple.com/us/podcast/market-bedshite/id1539596322?i=1000565248540"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+Market bedshite, Urbit & Uqbar, China nonsense
10+
content/podcasts/2022-07-04_enable-people-to-run-their-own-servers.md+1−1
@@ -113,4 +113,4 @@ Who to follow if you liked this episode:
113113
114114urbit.org/grants
115115
116−DM ~sarlev-sarsen
116+DM ~sarlev-sarsen
content/podcasts/2022-08-04_middling.mdnew file+10
@@ -0,0 +1,10 @@
1++++
2+title = "Ep042: Middling with ~midsum-salrux"
3+podcast = "The Stack"
4+date = "2022-08-04"
5+URL = "https://podcasts.apple.com/us/podcast/ep042-middling-with-midsum-salrux/id1539596322?i=1000575001146"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we speak with ~midsum-salrux about average women, Urbit bots, and Ruby on Rails.
10+
content/podcasts/2022-08-11_probing-questions.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Ep043 Probing Questions wth ~ribben-donnyl"
3+podcast = "The Stack"
4+date = "2022-08-11"
5+URL = "https://podcasts.apple.com/us/podcast/ep043-probing-questions-wth-ribben-donnyl/id1539596322?i=1000575746635"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+Welcome back to The Stack!
10+
11+This week we speak to ribben-donnyl, Urbit’s foremost authority on hindquarters.
12+
13+We talk about how ribben got into Urbit (hint: not through the front entrance), the Portugal, the note-taking app Funes, and ribben’s hardline pro-state stance.
14+
content/podcasts/2022-08-19_the-blind.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "Ep044 The Blind Beating Up the Blind with ~sarlev-sarsen"
3+podcast = "The Stack"
4+date = "2022-08-19"
5+URL = "https://podcasts.apple.com/us/podcast/ep044-the-blind-beating-up-the-blind-with-sarlev-sarsen/id1539596322?i=1000576585097"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/thestack.jpg"
7++++
8+
9+This week we talk about beating up poor, helpless blind people and earning Urbit grants. These are two unrelated thoughts (so far).
content/podcasts/2022-08-26_the-harvard-finance-bro.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "The Harvard Finance Bro Building an Urbit Network State in El Salvador"
3+podcast = "Other Life"
4+date = "2022-08-26"
5+URL = "https://podcast.otherlife.co/episodes/the-harvard-finance-bro-building-an-urbit-network-state-in-el-salvador"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/full_1639502000-artwork.jpg"
7++++
8+
9+~Nilrun-mardux is co-host of The Network Age podcast and founder of AlephDAO, an early network state project on Urbit via El Salvador.
10+
11+Show Notes
12+~Nilrun-mardux is co-host of The Network Age podcast and founder of AlephDAO, an early network state project on Urbit via El Salvador.
content/podcasts/2022-09-14_insanely-bullish-on-urbit.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "Insanely Bullish on Urbit With Uqbar Founder ~timluc-miptev"
3+podcast = "Other Life"
4+date = "2022-09-14"
5+URL = "https://podcast.otherlife.co/episodes/insanely-bullish-on-urbit-with-uqbar-founder-timluc-miptev"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/full_1639502000-artwork.jpg"
7++++
8+
9+Timluc is a top Urbit engineer and founder of Uqbar, a zero-knowledge ETH Layer 2 built on Urbit.
10+Show Notes
11+Timluc is a top Urbit engineer and founder of Uqbar, a zero-knowledge ETH Layer 2 built on Urbit.
12+
13+Timluc is one of the highest-conviction Urbit bulls in the world. We talked about why he has so much confidence in Urbit, what people misunderstand about Urbit, why he went from BTC Maxi to ETH Maxi, and what he learned about crypto living in Ukraine when the war broke out.
content/podcasts/2022-09-21_the-worlds-best-crypto-investor.mdnew file+12
@@ -0,0 +1,12 @@
1++++
2+title = "The World's Best Crypto Investor Invested in Urbit with Joey Krug of Pantera Capital"
3+podcast = "Other Life"
4+date = "2022-09-21"
5+URL = "https://podcast.otherlife.co/episodes/the-worlds-best-crypto-investor-invested-in-urbit-with-joey-krug-of-pantera-capital"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/full_1639502000-artwork.jpg"
7++++
8+
9+Joey Krug is Co-Chief Investment Officer at Pantera Capital, the biggest crypto hedge fund in the world.
10+
11+Show Notes
12+Joey Krug is Co-Chief Investment Officer at Pantera Capital, the biggest crypto hedge fund in the world. Joey's AngelList syndicate is also one of the most successful ever. We talk about Urbit as an investment and how to identify underpriced value more generally.
content/podcasts/2022-09-30-neal-davis-urbit-sentience-daos.mdnew file+33
@@ -0,0 +1,33 @@
1++++
2+title = "Neal Davis: Urbit, Sentience, and DAOs | The UIUC Talkshow #21"
3+podcast = "The UIUC Talkshow"
4+date = "2022-09-30"
5+URL = "https://www.youtube.com/watch?v=jO9HwAbf-tY"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/uiuc.png"
7++++
8+
9+Neal Davis is a Computer Science Professor at UIUC and Urbit's director of developer experience.
10+
11+Since we started the UIUC Talkshow, we've said the show is about people who are sane in a way most people are crazy. Neal Davis is exactly one of them. It’s not surprise he believes we need to be weirder.
12+
13+He started as a nuclear engineer but throughout his life, he's reflected on the definition of a "good and wise life." This led him to want to "elevate sentience" in his life and the life of others. A beautiful and unique pursuit.
14+
15+That philosophy guides the type of work he devotes himself to and that’s he how he found Urbit, an ambitious project to rebuild and rethink the internet from first principles.
16+
17+Join us on this conversation to learn more about Urbit, Decentralized Autonomous Organizations (DAOs), Balaji’s Network States, and why the best things that happen to you are accidents.
18+
19+This is the UIUC Talkshow.
20+
21+
22+EPISODE LINKS:
23+
24+
25+Neal Davis' Twitter: https://twitter.com/sigilante
26+
27+Neal Davis’ Urbit: ~lagrev-nocfep
28+
29+Urbit's Website: https://urbit.org/
30+
31+Urbit's Hackaton: https://uc4uc.com/
32+
33+
content/podcasts/2022-10-04-reality-maximalism-josh-lehman.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "Reality Maximalism, Small Data, and Urbit"
3+podcast = "Virgils"
4+date = "2022-10-04"
5+URL = "https://www.youtube.com/watch?v=e6E5ytMnz0w"
6+image = "https://media.urbit.org/site/ecosystem/podcasts/virgils.jpeg"
7++++
8+
9+Josh is the executive director of the Urbit Foundation. Previously, he was the Chief Product Officer at Tlon, which is the primary developer of Urbit.
content/podcasts/2022-10-06_urbit-maxi-episode copy.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E12 - The Gang Does an Urbit Maxi Episode"
3+podcast = "The Network Age"
4+date = "2022-10-06"
5+URL = "https://rss.com/podcasts/thenetworkage/645340/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by Theodore Blackman (~rovnys-ricfer), Engineering Manager at Tlon, to discuss Assembly, composability, Uqbar, and the bright future of Urbit. All this, plus Holium, Stripe, an extended carpentry metaphor, and how ~timluc has forced ~bichul to slave away in the coding gulags of Hoon School.
content/podcasts/2022-12-22_epicenter-ted-blackman-gary-lieberman.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Gary Lieberman & Ted Blackman: Urbit – Decentralized Computing Platforms"
3+podcast = "Epicenter"
4+date = "2022-12-22"
5+URL = "https://www.youtube.com/watch?v=Jd1qxbNHAmE&t=1s"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/epicenter.jpg"
7++++
8+
9+When discussing the widespread adoption of true, peer-to-peer decentralization, one could easily identify various social and political obstacles. However, there is also an often overlooked technological impairment as the underlying architecture of computer networks was not designed to achieve global-scale decentralization. Ideally a complete restructuring would be necessary, from applications and programming language, to as profound as rewriting operating system kernels. This is what Urbit is trying to achieve; a decentralized network where users have full control over their computer, running a unified operating system, where applications function seamlessly, without centralized chokepoints.
10+
11+We were joined by Ted Blackman, CTO of Urbit Foundation, and Gary Lieberman, the Chorus One Team Lead for Urbit, to discuss how Urbit reshapes the way we interact with computers, its current development stage, and what challenges it has to overcome.
content/podcasts/2023-01-05_lets-get-personal.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E21 - Let's Get Personal...AI feat. (Owen Barnes)"
3+podcast = "The Network Age"
4+date = "2023-01-05"
5+URL = "https://rss.com/podcasts/thenetworkage/767653/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by blockchain entrepreneur and decentralization advocate Owen Barnes (~locruc-fonmec) to discuss the rise of personal artificial intelligence tools, the importance of user interface, and how to design a new internet from the ground up. Then, they explore how new AI platforms (such as Chat GPT and Codex) can empower programmers, whether AI will protect (or exploit) personal data, and the role of crypto in curation of AI content. All this plus digital reincarnation of departed loved ones, algorithmic broadway musicals, and sign placement on the London Underground.
content/podcasts/2023-01-19_crypto-metaphysics.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E22 - Crypto Metaphysics feat. Grant Hummer and Matt Liston"
3+podcast = "The Network Age"
4+date = "2023-01-19"
5+URL = "https://rss.com/podcasts/thenetworkage/786206/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+In this extra special episode, the boys are joined by Grant Hummer and Matt Liston, two of Ethereum's most original gangsters, to discuss the blockchain's complicated past, its mistakes and pitfalls, and what the future might hold for our favorite L1. Matt, a cofounder of Augur and Gnosis, previously worked for the Ethereum foundation, while Grant founded San Francisco's oldest Ethereum developer meetup. Assisted by your handsome co-hosts, our guests also explore the future of blockchain on Urbit, the pitfalls of inadequate leadership, startup pessimism, how to found a crypto religion, and the metaphysical ecstasy of blockchain contemplation. This is an episode you won't want to miss.
content/podcasts/2023-01-24_reject-triviality.mdnew file+13
@@ -0,0 +1,13 @@
1++++
2+title = "What does it mean to reject and transcend triviality?"
3+podcast = "Crazy Wisdom"
4+date = "2023-01-24"
5+URL = "https://podcasts.apple.com/us/podcast/what-does-it-mean-to-reject-and-transcend-triviality/id1354589767?i=1000597317474"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/crazywisdom.jpg"
7++++
8+
9+An interview with Trent Gillham, Founder of Holium.
10+
11+Urbit: [~lomder-librun](/ids/~lomder-librun)
12+
13+Twitter: [@AidenSolaran](https://twitter.com/AidenSolaran)
content/podcasts/2023-01-26_building-future-states-with-nation3.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E23 - Building Future States with Nation3 (feat. Luis Cuende and Anastasiya Belyaeva)"
3+podcast = "The Network Age"
4+date = "2023-01-26"
5+URL = "https://rss.com/podcasts/thenetworkage/795280/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by Luis Cuende and Anastasiya Belyaeva of Nation3, the world's first internet-native jurisdiction and "cloud nation." Luis (cofounder of Aragon) and Anastasiya discuss their network state optimism, how DAOs and smart contracts will shape a digital court system, and the benefits of becoming a Nation3 citizen. Then, they dive into capital formation in special economic zones, how digital states can support values-driven community, and the relative value of patriotism.
content/podcasts/2023-01-29_urbit-for-idiots.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Urbit for Idiots | Galen Wolfe-Pauly, Tlon Corporation"
3+podcast = "Boys Club"
4+date = "2023-01-29"
5+URL = "https://podcasts.apple.com/us/podcast/urbit-for-idiots-galen-wolfe-pauly-tlon-corporation/id1616327892?i=1000597057523"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/boysclub.jpg"
7++++
8+
9+Galen Wolfe-Pauly joins the pod to talk about Urbit, a decentralized personal server platform. They talk about what Urbit is, and why owning your own 'space' on the internet is valuable. Galen answers a bunch of questions like, is Urbit a computer? Can you send an email on Urbit? How will Urbit ever get users? This podcast is perfect for Urbit beginners.
10+
11+Draft tweets close out the episode. Feelings check-in to return on the next pod.
content/podcasts/2023-02-09_crypto-narratives-new-and-old.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E24 - Crypto Narratives, New and Old (feat. CoinDesk Reporters Marc Hochstein and Tracy Wang)"
3+podcast = "The Network Age"
4+date = "2023-02-09"
5+URL = "https://rss.com/podcasts/thenetworkage/818546/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by esteemed CoinDesk reporters Marc Hochstein (~fodrex-malmev) and Tracy Wang to discuss the major crypto narratives of 2022. In particular, they dive into FTX (covered in-depth by Tracy for CoinDesk) and its implications for the coming year, as well as the general craziness of crypto reporting and the importance of being "long volatility." Then, the crew looks to 2023 to consider federal crypto regulation, the rise of zero-knowledge rollups, and protocol-level advances for Ethereum. All this plus polycules, Urbit, and buying Bitcoin in person from a man in the park.
content/podcasts/2023-02-13_distributed-networked-computing.mdnew file+17
@@ -0,0 +1,17 @@
1++++
2+title = "What are the use cases for distributed networked computing instead of centralized systems?"
3+podcast = "Crazy Wisdom"
4+date = "2023-02-13"
5+URL = "https://crazywisdom.libsyn.com/what-are-the-use-cases-for-distributed-networked-computing-instead-of-centralized-systems-eric-helal"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/crazywisdom.jpg"
7++++
8+
9+Eric Helal Founder of Quartus a Dev shop for Urbit Apps
10+
11+~rabsef-bicrym on Urbit
12+
13+https://twitter.com/SafePen
14+
15+~dalten/new-aera
16+
17+https://twitter.com/_dalten
content/podcasts/2023-02-23_the-urbit-episode.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E25 - The Urbit Episode (feat. Sam Frank)"
3+podcast = "The Network Age"
4+date = "2023-02-23"
5+URL = "https://rss.com/podcasts/thenetworkage/837778/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys (sans ~timluc) are joined by Sam Frank (~todset-partug) of the Urbit Foundation to discuss his defection from the New York literary scene to the frontiers of distributed technology. As an early investor to both Ethereum and Urbit, Sam has witnessed how digital-first communities can organize around shared values and the pursuit of knowledge. Together, Sam and our hosts dive into the future of Urbit, the wild world of Miladies, and Sam's own journey as a writer and esoteric explorer. All this plus Urbit marriages, psychic abilities, and the importance of throwing a really good party.
content/podcasts/2023-03-09_reclaiming-web-1.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E26 - Reclaiming Web 1 (feat. ~dachus-tiprel)"
3+podcast = "The Network Age"
4+date = "2023-03-09"
5+URL = "https://rss.com/podcasts/thenetworkage/858056/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by Uqbar developer, Urbit explorer, and Network Age frontiersman ~dachus-tiprel to discuss the joys of peer-to-peer programming with a Web 1 aesthetic. We also touch on a few of ~dachus' recent projects, including %blog, a p2p publishing platform you can host from your own server, and %pyro, a testing script that has transformed into one of Urbit's most promising methods for low-cost hosting. All this plus "exiting", the instantiation of an IRL Party DAO, and whether programmers are more like artists or plumbers. Don't miss it.
content/podcasts/2023-03-23_how-to-invest-in-web3-like-a-cool-kid.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E27 - How to Invest in Web3 Like a Cool Kid (feat. Shad)"
3+podcast = "The Network Age"
4+date = "2023-03-23"
5+URL = "https://rss.com/podcasts/thenetworkage/878369/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by Shad (~narpel-machul), the GP of Giga Corp, a crypto marketing and investment firm, to discuss liquid lobbying (using capital allocation to direct the positive development of public goods in Web3), blockchain conferences, and how to tell a real DAO from a fake one. The squad also dives deep on Urbit culture, the untapped potential of being cool in crypto, and the accelerating fusion of lifestyle with technology. All this plus diarrhea, fighting on a volcano, crypto breakfasts in Kyiv, and frontier favelas. Don't miss it.
content/podcasts/2023-03-28_pupusas-volcanoes-and-databases.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "Pupusas, Volcanoes and Databases with ~hodzod-walrus"
3+podcast = "ZeroK - UF"
4+date = "2023-03-28"
5+URL = "https://www.youtube.com/watch?v=W7oMxY39tl8"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/ZeroK-logo.png"
7++++
8+
9+In this inaugural episode, ~poldec-tonteg and ~roslet-tanner recap the Urbit Volcano Summit, new Hoon School and App School classes, growth metrics for Urbit and the news that, finally, you can fit at least one movie from the Shrek franchise in your Urbit. Enjoy!
content/podcasts/2023-04-03_legacy-internet-new-internet.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "Legacy internet vs New Internet?"
3+podcast = "Crazy Wisdom"
4+date = "2023-04-03"
5+URL = "https://crazywisdom.libsyn.com/legacy-internet-vs-new-internet-aj-lamarc"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/crazywisdom.jpg"
7++++
8+
9+AJ is a software engineer interested in Urbit and data composability.
10+
11+Twitter: https://twitter.com/ajlamarc
12+
13+https://www.ajlamarc.com/
14+
15+Keep an eye out on Holium, and making it easier to code in Javascript for Urbit
content/podcasts/2023-04-06_the-ai-episode.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E28 - The AI Episode (feat. Jake Brukhman)"
3+podcast = "The Network Age"
4+date = "2023-04-06"
5+URL = "https://rss.com/podcasts/thenetworkage/896645/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys (including OG host ~timluc-miptev) are joined by Jake Brukhman (~ranter-tapper), the founder and CEO of Coinfund, as well as an engineer, technologist, investor, and cosmonaut exploring the frontiers of AI. The crew discusses the creation of Jargon, a Chat GPT pseudolanguage, which Jake used to build a personal AI Spanish teacher, and the implications of recent AI development. In particular, they focus on AI's implications for privacy, the intersection of AI and Web3 (including crypto as a force of decentralization), and the many types of doom that could be facing us. All this, plus how to use Chat GPT to optimize your personal life, the role of AI in education, the coming marriage between Urbit and AI, and whether interacting with AI is a religious experience. Don't miss it.
content/podcasts/2023-04-11_its-urbits-all-the-way-down-with-dachus-tiprel.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "It's Urbits All the Way Down with ~dachus-tiprel"
3+podcast = "ZeroK - UF"
4+date = "2023-04-11"
5+URL = "https://www.youtube.com/watch?v=hgVE_EZiyms"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/ZeroK-logo.png"
7++++
8+
9+On the newest episode of Zero K, ~poldect-tonteg interviews ~dachus-tiprel of Uqbar network about his virtualization system, Pyro. Also discussed: Exiting college, how he got linked up with Uqbar through the grants program and the ultimate Urbit hosting solution.
content/podcasts/2023-04-14_epicenter-tim-galebach.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Tim Galebach: Uqbar – Smart Contracts on Urbit"
3+podcast = "Epicenter"
4+date = "2023-04-14"
5+URL = "https://www.youtube.com/watch?v=stEn6RacXtY"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/epicenter.jpg"
7++++
8+
9+Building a truly decentralised, peer-to-peer network, based on a built-in identity system, limits the ecosystem’s interoperability with the outside world. Onboarding developers and users to Urbit was only the first hurdle. On-ramping crypto was a whole different & daunting task. Uqbar set out to build an execution layer on top of Urbit, enabling smart contracts, which would ultimately settle, via a ZK rollup, on Starknet.
10+
11+We were joined by Tim Galebach, founder of Uqbar, to discuss the different design choices involved, from Hoon programming DevEx to a hybrid ZK-optimistic rollup.
content/podcasts/2023-04-20_artificial-qintelligence.mdnew file+9
@@ -0,0 +1,9 @@
1++++
2+title = "E29 - Artificial Qintelligence (feat. Xianyang)"
3+podcast = "The Network Age"
4+date = "2023-04-20"
5+URL = "https://rss.com/podcasts/thenetworkage/914980/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys welcome a new cohost, ~habsul-rignyr of the OG Urbit podcast, The Stack (Rest in Power). More importantly, our trio of idiots is joined by famed translator, scholar, technologist, and sinophile Xianyang (~forlyt-novmep) to discuss AI-enhanced gaming, Taoist philosophy, and the creation of DAObi, a token-based simulation game of an ancient Chinese state. Then, we dive into Lexicat, Xianyang's natural language processing platform, and dissect her attempts to create GPT Burmese. All this plus: economic incentives to instantiate the AI apocalypse, the startling Confucian-Taoist rivalry, a scandalous battle for DAObi Chancellor, digital wife swapping, and how to murder a cat.
content/podcasts/2023-04-27_hoon-only-legal-ui-with-hastuc-dibtux.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "Hoon Only Legal UI with ~hastuc-dibtux"
3+podcast = "ZeroK - UF"
4+date = "2023-04-27"
5+URL = "https://www.youtube.com/watch?v=jF5hY-CduTI"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/ZeroK-logo.png"
7++++
8+
9+In new episode of Zero K, ~poldec-tonteg interviews the mysterious hooner/aesthetic crusader known as ~hastuc-dibtux
10+
11+Witness a discussion of immorality of javascript, the importance of a sovereign UI and much more
content/podcasts/2023-05-11_full-metal-urbit-with-mopfel-winrux.mdnew file+15
@@ -0,0 +1,15 @@
1++++
2+title = "Full Metal Urbit with ~mopfel-winrux"
3+podcast = "ZeroK - UF"
4+date = "2023-05-11"
5+URL = "https://www.youtube.com/watch?v=tW2FlJmUy8w"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/ZeroK-logo.png"
7++++
8+
9+Live from my heartland headquarters, another exciting episode of Zero K, an interview with ~mopfel-winrux, hardware extraordinaire.
10+
11+~mopfel has a deep background in hardware: chips, robots, wiring harnesses. Today he talks about the interaction between your Urbit and the metal that it runs on.
12+
13+He also touches on a project that has since been named %lick which lets your Urbit directly control hardware like peripherals and GPUs.
14+
15+You might also get a glimpse or two at the hardware plans of his company Native Planet, leading many to ask: When Urbit phone?
content/podcasts/2023-05-18_crypto-takes-flight.mdnew file+11
@@ -0,0 +1,11 @@
1++++
2+title = "E31 - Crypto Takes Flight (feat. Brian Crain)"
3+podcast = "The Network Age"
4+date = "2023-05-18"
5+URL = "https://rss.com/podcasts/thenetworkage/955387/"
6+image = "https://storage.googleapis.com/media.urbit.org/site/ecosystem/podcasts/networkage.jpg"
7++++
8+
9+On this extra special episode, the boys are joined by technologist and investor Brian Crain (~minwyc-dablen), CEO and co-founder of Chorus One and host of crypto's longest running podcast, Epicenter. They discuss his work building Web3 infrastructure, the evolution of Urbit (Brian just joined the Urbit Foundation board), and the next five years of crypto narratives. Then, they dive into Brian's work on Epicenter, his favorite guests, and what he has learned from spending so many years in the space. All this plus government regulation, AI-crypto integrations, and tips from a master podcaster on how we can improve The Network Age. Don't miss it.
10+
11+Our thoughts go out to Brian, who is currently in the hospital recovering from his experience on this podcast.x3
content/privacy.md+1−1
@@ -76,7 +76,7 @@ We do not knowingly collect, maintain, or use personal information from children
7676
7777### International visitors
7878
79−The Services are hosted in the United States and are intended for visitors located within the United States. If you choose to use the Services from the European Union or other regions of the world with laws governing data collection and use that may differ from U.S. law, then please note that you are transferring your personal information outside of those regions to the United States for storage and processing. Also, we may transfer your data from the U.S. to other countries or regions in connection with storage and processing of data, fulfilling your requests, and operating the Services. By providing any information, including personal information, on or to the Services, you consent to such transfer, storage, and processing.
79+[Omitted long matching line]
8080
8181### Changes to this Privacy Policy
8282
content/proposals.md+21−41
@@ -1,6 +1,6 @@
11+++
22title = "Submit a Proposal"
3−date = "2022-01-03"
3+date = "2023-01-04"
44weight = 1
55description = "A comprehensive guide to creating a grant proposal"
66+++
@@ -11,9 +11,9 @@ We have a track record of funding many different kinds of different projects: ne
1111
1212Ready to get started? Here's how the process works:
1313
14−1. [Create your proposal](#create-your-proposal) as a group on Urbit
15−2. Submit your proposal using [this form](https://airtable.com/shrCi54rEDxgSZr3z)
16−3. Obtain [approval](#community-approval) from a member of our community and finalize your proposal
14+1. Submit your proposal using [this form](https://airtable.com/shrCi54rEDxgSZr3z)
15+2. Obtain [approval](#approval-by-the-foundation) from the Urbit Foundation and find a member of our community to champion your proposal
16+3. When your proposal is approved the Urbit Foundation and you will start looking for a suitable [champion](#looking-for-a-champion)
17174. Sign our [grant agreement](#paperwork)
18185. [Submit invoices](#getting-paid) after obtaining community signoff
1919
@@ -21,21 +21,6 @@ Ready to get started? Here's how the process works:
2121
2222Submitting a proposal starts by clearly articulating your idea and the value it will bring to the Urbit network. Getting the Urbit Foundation's signoff requires [approval from an established member of our community](#community-approval) and a compelling reason for receiving the requested amount of funding.
2323
24−### Create a group
25−
26−The first step is to create a group in Landscape's Groups app &mdash; this will be installed by default on your ship. If you don't have a ship running, check out our [Getting Started](https://urbit.org/getting-started) guide.
27−
28−Your group should:
29−
30−- Be **named** after your proposal
31−- Be **public** so our community can join
32−- Contain **a notebook** called `proposal`
33−- Contain **a chat channel** called `discussion`
34−
35−You'll write your proposal in markdown into the notebook, and engage with community members that would approve your proposal in the discussion channel.
36−
37−After writing up your proposal, [fill out this form](https://airtable.com/shrCi54rEDxgSZr3z), including the name of your group. The group name can be found in the URL of your browser. For example, in the URL `https://your.ship.domain/apps/landscape/~landscape/ship/~wolref-podlex/foundation` the group name is `~wolref-podlex/foundation`.
38−
3924### Elements of a proposal
4025
4126Good proposals all include the following:
@@ -50,9 +35,12 @@ It's recommended to break your project into _milestones_, each of which must hav
5035
5136Here are some examples of exceptional proposals for reference:
5237
53−- [Azimuth CLI](https://urbit.org/grants/azimuth-cli)
54−- [Pokur: Texas Holdem on Urbit](https://urbit.org/grants/pokur)
55−- [Urbit Speech Recognition](https://urbit.org/grants/speech-recognition)
38+- [Urbit Forms](https://urbit.org/grants/urbit-forms) has great demonstration of thinking around technical architecture
39+- [Bitcoin Lightning Development](https://urbit.org/grants/lightning-development) shows well defined user stories and future development opportunities that can inspire potential collaborators
40+- [%pony](https://urbit.org/grants/pony-bounty) contains detailed thinking of current affordances of existing software if trying to build analogs to the traditional software stack
41+- [App Store](https://urbit.org/grants/app-store) blends the above with a nearly ideal balance of user stories mapped to milestones for clarity of completion, initial architectural thinking, and thinking around unique affordances and challenges of building on a distributed p2p system
42+
43+After writing up your proposal, [fill out this form](https://airtable.com/shrCi54rEDxgSZr3z) to submit your idea to the Foundation.
5644
5745### Funding
5846
@@ -60,11 +48,11 @@ The Urbit Foundation will provide funding of up to five stars for any one grant.
6048
6149Our formula for determining how much to value a particular grant is a function of time spent on the project, value to the Urbit universe, and track record of the contributor (either via past work within the grants program, or a relevant external background).
6250
63−If you're looking for more funding for a project that you're planning on devoting 100% of your full-time work to, you might instead consider [The Combine](https://the-combine.org).
51+Further funding may be available for continued development pending the successful completion of your grant. Additionally, contributors of exceptionally well completed grant proposals become eligible to mentor apprentices which can support continued development of their application for maintenence and feature additions.
6452
6553### Abandonment
6654
67−A proposal is considered abandoned when a milestone is more than a month behind schedule. When a proposal is considered abandoned, the Urbit Foundation may choose to compensate the work differently upon completion, or not at all.
55+A proposal is considered abandoned when a milestone is more than a month behind schedule and preemptive action is not taken to inform The Urbit Foundation of an adjusted timeline that has been approved by your Champion. When a proposal is considered abandoned, the Urbit Foundation may choose to compensate the work differently upon completion, or not at all.
6856
6957The intent of this policy is to:
7058
@@ -73,19 +61,11 @@ The intent of this policy is to:
7361
7462We try to use this rule in good faith. Reasonable delays due to unforseen life circumstances or project complexity will be tolerated, so long as the contributor is communicative with their champion and/or the Urbit Foundation. In these cases we'll encourage the contributor to modify the timelines and/or scope of their proposals to accommodate new information.
7563
76−## Community approval
77−
78−Your proposal will be considered approved when an established member of our community decides to _champion_ it. Only those that have made substantial past contributions to the project, generally through their own grants, are eligible to provide such a seal of approval.
79−
80−Approval from the community goes beyond simply clearing the project for funding. The community member that approves your project, called the _Champion_, will meet with you regularly to provide mentorship and support, help onboard you to the rest of the community, and ultimately be responsible for approving your work.
81−
82−### How it works
83−
84−After creating your group and [submitting it](https://airtable.com/shrCi54rEDxgSZr3z), the Urbit Foundation team will post your group to the community members that are approved for Championing proposals.
85−
86−The contents of your submission will be available to prospective champions, and if they're interested, they'll join your group and dive into the details with you (that's why that **discussion channel** is important).
64+### Approval by the Foundation
65+The Grants team of the Urbit Foundation looks at Grants on a bi-weekly basis. After they have decided on the grant they will inform you whether it is approved, rejected or needs some adjustments. In the latter case someone of the grants team will help you finetune your proposal so it can be reconsidered in the next round.
8766
88−When someone is sufficiently interested, they'll say so and ask to champion your project. If multiple people are interested in championing, you'll need to choose who to go with! This is, in our view, a good problem to have.
67+### Looking for a Champion
68+Finding a suitable champion is important for the success of your grant. Therefore we ask you to stay on the look-out for someone on the network who is capable to champion your proposal. The Foundation will assist you in finding a good champion.
8969
9070### Working with your Champion
9171
@@ -94,20 +74,20 @@ Your champion is invested in the success of your project &mdash; if they success
9474Here are some guidelines for how to engage with your champion:
9575
9676- **Meet regularly:** Those that can champion projects are chosen for their past contributions. This means that they're able to provide hands-on support. This structure works best if you set up a regular check-in, either once a week or every other week. If nothing else, having an accountability buddy is really helpful.
97−- **Stay in touch:** Leverage the Urbit network for keeping in touch about your project. Don't hesitate to ask questions!
77+- **Stay in touch:** Leverage the Urbit network for keeping in touch about your project. Don't hesitate to ask questions! The `[battery payload]` group (~dister-dozzod-lapdeg/battery-payload) is a great place to hang out with other developers, ask questions, and share your experiences.
9878- **Ask for connections:** Champions are well-connected throughout the network and know who's who. If you need support in a particular area that is beyond your Champion's expertise, they should be able to put you in touch with someone that can help.
99−- **Get your work reviewed:** Part of your Champion's job is to review your work and get others' eyes on it as well. Let them know when you need something reviewed.
79+- **Get your work reviewed:** Part of your Champion's job is to review your work and get others' eyes on it as well. Let them know when you need something reviewed. Particularly, this is required for getting review and signoff that you have completed a milestone, but can be helpful for other complex asks as well.
10080
10181If your Champion becomes unresponsive or is unhelpful, let someone at the Urbit Foundation know and we'll take care of it.
10282
10383## Paperwork
10484
105−After your proposal is Championed the Urbit Foundation will need to get a **signed contributor agreement** and **collect a small amount of personal information** from you as part of our KYC process.
85+After your proposal is approved and Championed, it will be added to this website, and the Urbit Foundation will need to get a **signed contributor agreement** and **collect a small amount of personal information** from you as part of our KYC process.
10686
10787The Urbit Foundation must comply with international law when distributing address space. We try to keep this process as minimal as we can, but there's no way to avoid it entirely without legally jeopardizing the Foundation's operations.
10888
10989## Getting Paid
11090
111−After you've finished your work and gotten signoff from your champion, you'll [submit an invoice](https://airtable.com/shrXXCs1uaxtNSBcg) to the Urbit Foundation for the amount agreed upon in your grant or milestone, which the Foundation will pay.
91+After you've finished your work on a given milestone, you will need to get signoff from your champion. To do this, you'll want to contact them to share the details of the milestone completed, any relevant instructions, github repos, or app download links, and solicit review from your champion. They can submit their approval by contacting `~marfun-pacpet`, at which point you are ready to [submit an invoice](https://airtable.com/shrXXCs1uaxtNSBcg). Once the Urbit Foundation receives approval from your champion and an invoice for the amount agreed upon in your grant or milestone, the Foundation will pay your star allocation to the Ethereum address you have provided.
11292
113−We approve and issue payments within 30 days of invoice receipt and approval, although often payment is made more quickly as transactions are batched with other grantees who have recently completed milestones. If you are having any issues accepting stars through [Bridge](https://bridge.urbit.org) please contact `~taller-ravnut` for assistance.
93+We approve and issue payments within 30 days of invoice receipt and approval, although often payment is made more quickly. If you have any questions regarding getting paid or submitting an invoice, please contact `~marfun-pacpet` for assistance.
content/rfps.mdnew file+40
@@ -0,0 +1,40 @@
1++++
2+title = "Requests for Proposals"
3+date = "2023-03-02"
4+weight = 1
5+description = "Everything you need to know about fulfilling a request for proposal or RFP"
6++++
7+
8+The imagination of people building on Urbit often outpaces the available development hours. For this case, we have Requests for Proposals (RFPs).
9+
10+These are ideas that the community would like to see come to fruition, but whose details haven't been completely ironed out. Since they're not fully fleshed out, they're a great opportunity for contributors to add their own ideas and creative approaches, while learning about developing and shipping on Urbit.
11+
12+If any of these RFPs sound compelling, we encourage you to come by the [Urbit Grants office hours](https://app.gather.town/app/xAYeiPI2XDYhRM9t/urbit-hacker-house?spawnToken=ufV1APwWTGmYVTgzyx0z) or DM [~poldec-tonteg](https://urbit.org/ids/~poldec-tonteg) to discuss drafting and submitting a proposal.
13+
14+# Jump in
15+
16+The Hacker House is a UF-hosted gather.town instance where contributors hang out, pair program and discuss all things Urbit. At the Office Hours, members from the UF team can help refine the Request idea and give you context about what needs to be built, potential use cases and architectural precedents in the codebase.
17+
18+Once you've got your mind around this, the next step is to draft the Proposal
19+
20+# Drafting a proposal
21+
22+All of the best practices outlined on the [Proposals](https://urbit.org/grants/proposals) section of the website apply equally to Proposals that respond to a Request.
23+
24+Good proposals all include the following:
25+
26+- A **detailed and clear description of the proposal**. If you're proposing something technical, user stories are a good idea.
27+- An overview of **why you are the right person for the job**. A description of your background, familiarity with the project, and professional/education experience are all good starts.
28+- Your estimate for **date of completion**.
29+- The **amount of funding** you'd like for the project, denominated in stars.
30+- What **specific deliverables** will look like.
31+
32+It's recommended to break your project into _milestones_, each of which must have its own completion dates, funding amounts and deliverables. In general, proposals should target a first deliverable within two months of the start of the project. Proposals should have a maximum of five milestones as scoping a project beyond that is impractical, and each milestone should constitute significant enough work to warrant the reward of a full star.
33+
34+Feel free to come to multiple office hours or connect on network to develop the proposal further. Once it's in a good state, submit it through [this form](https://airtable.com/shrCi54rEDxgSZr3z). Submitted proposals are then reviewed internall twice a week by the full grants team.
35+
36+The main distinction between a self-originating Proposal and one that responds to a Request is that the latter doesn't need to go through the further step of getting a champion, as the originator of the Request will fulfill that role.
37+
38+# Getting paid
39+
40+A good proposal will have clear success criteria for each milestone. At the completion of each milestone, submit an invoice to the UF for that milestones star compensation and your champion will have the opportunity to review work.
content/updates/2018-7-30-update.md+1−1
@@ -53,7 +53,7 @@ latest backend Landscape API's that _Isaac_ `~davtyr-nimren` has been improving.
5353Urbit is becoming more usable by the day.
5454
5555Last but not least, the Documentation team continued doing `~zod`'s work helping
56−teach Urbit to the world. _Josh_ `~taglux-nidsep` extended his new Hoon docs to cover Hoon cores, an introduction to the Hoon standard library, and a couple of Hoon examples with very detailed walkthrough commentary (drafts [here](https://github.com/joshuareagan/doc-drafts)). And _Robert_ `~lodleb-ritrul` extended the current Hoon-standard-library documentation on random atom generation and atom scrambling, as well as the Hoon cores for computing modular and signed-integer arithmetic (`urbit/docs` pull requests [here](https://github.com/urbit/docs/pulls)). Very soon you'll actually be able to understand how Urbit works.
56+[Omitted long matching line]
5757
5858Also: we'll be hosting another party this month on Friday, August 17th. Save the date! Link: [meetup.com: Urbit IRL ~2018.8](https://www.meetup.com/urbit-sf/events/253292678/)
5959
content/updates/2019-2-11-update.md+1−1
@@ -26,7 +26,7 @@ To stay up to date on network status, follow [@zodisok](https://twitter.com/zodi
2626
2727## Team
2828
29−_Ted_ `~rovnys-ricfer` and _Joe_ `~master-morzod` got an `%ames` rewrite to compile and are working on documentation and unit tests. _Elliot_ `~littel-ponys` is rewriting `%eyre`, our webserver, which is some of the gnarliest code in Arvo. Outbound web requests are now working, which has allowed us to delete old `%eyre` from the [lighter-than-eyre branch](https://github.com/urbit/arvo/tree/lighter-than-eyre), and work continues porting individual `%gall` applications over to `%light`. We’re looking forward to moving Landscape onto new `%eyre` soon. _Logan_ `~tacryt-socryp` is rewriting the HTTP client in Vere (Arvo’s interpreter) to better support HTTP/2. This will allow us to provide push notifications in the heretofore rumored Landscape iOS app. Finally, _Gavin_ `ridlur-figbud` and _Jimmy_ `fallyn-balfus` are working on a new design system to enable fast UI prototyping. We’re very excited to share more about that in the near future!
29+[Omitted long matching line]
3030
3131Shout-out to _Philip_ `wicdev-wisryt` for [this heroic weekend PR](https://github.com/urbit/arvo/pull/1072) that fixed persistent connectivity issues on the network after [Thursday’s breach](https://twitter.com/zodisok/status/1096225302210957312).
3232
gnosis-safe.md+1−1
@@ -11,7 +11,7 @@ image = ""
1111description = "An Urbit app that serves the Gnosis Safe UI, but with Urbit used for storing safe/wallet metadata and exchanging signatures."
1212reward = "1 star"
1313assignee = [""]
14−champion = "~dinleb-rambep"
14+champion = ["~dinleb-rambep"]
1515grant_id = "B0154"
1616completed = false
1717work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=B0154&prefill_Grant+Name=Gnosis%20Safe"
lib/buildGlossary.jsnew file+59
@@ -0,0 +1,59 @@
1+const fs = require("fs");
2+const path = require("path");
3+const matter = require("gray-matter");
4+const toml = require("@iarna/toml");
5+
6+const options = {
7+ engines: {
8+ toml: toml.parse.bind(toml),
9+ },
10+ language: "toml",
11+ delimiters: "+++",
12+};
13+
14+const glossary = [];
15+
16+function buildGlossary(dir) {
17+ const children = fs.readdirSync(dir, { withFileTypes: true });
18+ const pages = children.filter((f) => f.isFile() && f.name !== "_index.md");
19+ const subdirs = children.filter(
20+ (f) => f.isDirectory()
21+ );
22+ pages.map((page) => {
23+ const { data } = matter(fs.readFileSync(path.join(dir, page.name)), options);
24+ const glossaryEntry = data.glossaryEntry
25+ ? Object.values(data.glossaryEntry)
26+ .map((e) => ({
27+ ...e, ...{
28+ url: "https://urbit.org" + path.join(
29+ dir.substr(dir.indexOf("content") + 7),
30+ "/",
31+ page.name.replace(/.md$/, "")
32+ )
33+ }
34+ }))
35+ : [];
36+ glossaryEntry.forEach((entry) => glossary.push(entry));
37+ });
38+
39+ Object.fromEntries(
40+ subdirs.map((subdir) => [
41+ subdir.name,
42+ buildGlossary(path.join(dir, subdir.name)),
43+ ])
44+ );
45+}
46+
47+buildGlossary(path.join(process.cwd(), "content"));
48+const fileContents = `export const glossary = ${JSON.stringify(glossary)}`;
49+
50+try {
51+ fs.readdirSync("cache");
52+} catch (err) {
53+ fs.mkdirSync("cache");
54+}
55+
56+fs.writeFile("cache/glossary.js", fileContents, function (err) {
57+ if (err) return console.error(err);
58+ console.log("Site glossary created.");
59+});
lib/cache.js+14−7
@@ -15,16 +15,20 @@ const options = {
1515const index = [];
1616
1717function buildSearchIndex(dir) {
18+ // Assume years belong to Grants for now.
1819 const dirName = dir.split("/").slice(-1).join("");
20+ const parentName = String(Number(dirName)).length === 4
21+ ? "Grants"
22+ : dirName.charAt(0).toUpperCase() + dirName.slice(1);
1923 let metadata = {
2024 data: {
21− title: dirName.charAt(0).toUpperCase() + dirName.slice(1),
25+ title: parentName,
2226 },
2327 };
2428
2529 try {
2630 metadata = matter(fs.readFileSync(path.join(dir, "_index.md")), options);
27− } catch (err) {}
31+ } catch (err) { }
2832
2933 const children = fs.readdirSync(dir, { withFileTypes: true });
3034 const pages = children.filter((f) => f.isFile() && f.name !== "_index.md");
@@ -40,14 +44,17 @@ function buildSearchIndex(dir) {
4044 );
4145 const parsed = markdoc.parse(pageContent);
4246 const transform = markdoc.transform(parsed);
43− return {
44− title: pageData.title,
45− base: page.name,
46− slug: path.join(
47+ const slug = dir.includes("/grants/")
48+ ? `/grants/${page.name.replace(/.md$/, "")}`
49+ : path.join(
4750 dir.substr(dir.indexOf("content") + 7),
4851 "/",
4952 page.name.replace(/.md$/, "")
50− ),
53+ );
54+ return {
55+ title: pageData.title,
56+ base: page.name,
57+ slug,
5158 content: pageData.description || "",
5259 headings: transform.children
5360 .filter((e) => e.name === "h2" || e.name === "h3")
lib/constants.js+15−6
@@ -24,6 +24,7 @@ export const eventKeys = [
2424 "dark",
2525 "timezone",
2626 "darken_image",
27+ "tags"
2728];
2829
2930export const postKeys = [
@@ -75,17 +76,25 @@ export const footerData = [
7576 },
7677 { title: "Get Started", href: "/getting-started" },
7778 {
78− title: "Events",
79− href: "/events",
79+ title: "Overview",
80+ href: "/overview",
8081 },
8182 {
82− title: "Blog",
83− href: "/blog",
83+ title: "Ecosystem",
84+ href: "/ecosystem",
8485 },
8586 {
8687 title: "Grants",
8788 href: "/grants",
8889 },
90+ {
91+ title: "Events",
92+ href: "/events",
93+ },
94+ {
95+ title: "Blog",
96+ href: "/blog",
97+ }
8998 ],
9099 },
91100 {
@@ -101,8 +110,8 @@ export const footerData = [
101110 href: "https://github.com/urbit/urbit/releases",
102111 },
103112 {
104− title: "Urbit Client",
105− href: "https://github.com/urbit/port/releases",
113+ title: "Developer Mailing List",
114+ href: "https://groups.google.com/a/urbit.org/g/dev",
106115 },
107116 {
108117 title: "Issue Tracker",
lib/lib.js+134−60
@@ -3,7 +3,7 @@ import { join, parse } from "path";
33import matter from "gray-matter";
44import toml from "@iarna/toml";
55import { DateTime } from "luxon";
6−import { getPostBySlug, getPostSlugs } from "@urbit/foundation-design-system";
6+import { Markdown, getPostBySlug, getPostSlugs } from "@urbit/foundation-design-system";
77
88// NB Gavin: This could be much simpler if we converted everything to a more common standard, like YAML
99const options = {
@@ -97,74 +97,65 @@ export function formatDateAndTime(dateTimeObject) {
9797
9898// Returns an array of unique grants categories
9999export function getGrantsCategories() {
100− const paths = fs.readdirSync(directories("grants"));
101− const uniqueCategories = paths
102− // Get only markdown files
103− .filter((path) => parse(path).ext === ".md")
104− // Parse frontmatter
105− .map((path) =>
106− matter(fs.readFileSync(join(directories("grants"), path)), options)
107− )
108− // Each markdown file has an array of categories. Collapse these arrays into one array.
109− .reduce((acc, metadata) => {
110− return [...acc, ...metadata.data.taxonomies.grant_category];
111− }, [])
112− // Deduplicate single array of categories such that the output is an array where each category is represented only once.
113− .reduce((acc, uniqueItem) => {
114− if (acc.includes(uniqueItem)) {
115− return acc;
116− }
117− return [...acc, uniqueItem];
118− }, []);
100+ const years = fs.readdirSync(directories("grants"), { withFileTypes: true }).filter((f) => f.isDirectory());
101+ const uniqueCategories = Array.from(new Set(years.map((yearDir) => {
102+ return fs.readdirSync(join(directories("grants"), yearDir.name), { withFileTypes: true })
103+ .filter((path) => parse(path.name).ext === ".md")
104+ .map((path) => matter(fs.readFileSync(join(directories("grants"), yearDir.name, path.name)), options))
105+ .flat()
106+ .reduce((acc, metadata) => {
107+ return [...acc, ...metadata.data.taxonomies.grant_category]
108+ }, [])
109+ }).flat()));
119110 return uniqueCategories;
120111}
121112
122113// Returns an array of unique grants types
114+
123115export function getGrantsTypes() {
124− const paths = fs.readdirSync(directories("grants"));
125− const uniqueTypes = paths
126− // Get only markdown files
127− .filter((path) => parse(path).ext === ".md")
128− // Parse frontmatter to JSON
129− .map((path) =>
130− matter(fs.readFileSync(join(directories("grants"), path)), options)
131− )
132− // Each markdown file has an array of types. Collapse these arrays into one array.
133− .reduce((acc, metadata) => {
134− return [...acc, ...metadata.data.taxonomies.grant_type];
135− }, [])
136− // Deduplicate single array of types such that the output is an array where each type is represented only once.
137− .reduce((acc, uniqueItem) => {
138− if (acc.includes(uniqueItem)) {
139− return acc;
140− }
141− return [...acc, uniqueItem];
142− }, []);
116+ const years = fs.readdirSync(directories("grants"), { withFileTypes: true }).filter((f) => f.isDirectory());
117+ const uniqueTypes = Array.from(new Set(years.map((yearDir) => {
118+ return fs.readdirSync(join(directories("grants"), yearDir.name), { withFileTypes: true })
119+ .filter((path) => parse(path.name).ext === ".md")
120+ .map((path) => matter(fs.readFileSync(join(directories("grants"), yearDir.name, path.name)), options))
121+ .flat()
122+ .reduce((acc, metadata) => {
123+ return [...acc, ...metadata.data.taxonomies.grant_type]
124+ }, [])
125+ }).flat()));
143126 return uniqueTypes;
144127}
145128
146−// Returns a number which represents how many grants are open, or uncompleted
147−export function getOpenGrantsCount() {
148− const paths = fs.readdirSync(directories("grants"));
149− const count = paths
150− // Get only markdown files
151− .filter((path) => parse(path).ext === ".md")
152− // Parse frontmatter to JSON
153− .map((path) =>
154− matter(fs.readFileSync(join(directories("grants"), path)), options)
155− )
156− // Count grants which are both uncompleted and not assigned
157− .reduce((acc, metadata) => {
158− if (
159− !metadata.data.extra.completed &&
160− !metadata.data.extra.canceled &&
161− metadata.data.extra.assignee?.[0] === ""
162− ) {
163− return acc + 1;
129+// Grab which directory the grant post is in
130+
131+export function getGrantYear(slug) {
132+ const basePath = join(process.cwd(), 'content/grants')
133+ const years = fs.readdirSync(basePath, { 'withFileTypes': true }).filter((f) => f.isDirectory());
134+ const dir = years.find((year) => {
135+ const yearDir = fs.readdirSync(join(basePath, year.name), { 'withFileTypes': true });
136+ return yearDir.some((file) => file.name === `${slug}.md`)
137+ });
138+ return dir;
139+}
140+
141+export function getGrantsByShortcode(shortcode) {
142+ const basePath = join(process.cwd(), 'content/grants')
143+ const years = fs.readdirSync(basePath, { 'withFileTypes': true }).filter((f) => f.isDirectory());
144+ let found = [];
145+ // Get matching years by any matching grant.
146+ years.forEach((year) => {
147+ const yearDir = fs.readdirSync(join(basePath, year.name), { 'withFileTypes': true });
148+ return yearDir.forEach((file) => {
149+ const { data } = matter(fs.readFileSync(join(basePath, year.name, file.name)), options);
150+ if (data?.extra?.deliverable === shortcode.join("/")) {
151+ found.push({
152+ ...data, ...{ slug: file.name.replace('.md', '') }
153+ }
154+ )
164155 }
165− return acc;
166− }, 0);
167− return count;
156+ })
157+ });
158+ return found
168159}
169160
170161// Groups arrays into an array of arrays with 2 members
@@ -175,3 +166,86 @@ export const pair = (arr) =>
175166 rows
176167 );
177168 }, []);
169+
170+// Match ecosystem report to posts to inject metadata
171+export const matchEcosystemPost = (ecosystem) => {
172+ const articles = getAllPosts(
173+ ["title", "image", "date", "podcast", "slug"],
174+ "articles",
175+ "date"
176+ );
177+
178+ const marketplaces = getAllPosts(["title", "image", "slug"], "marketplaces");
179+ const podcasts = getAllPosts(
180+ ["title", "image", "date", "podcast", "slug"],
181+ "podcasts",
182+ "date"
183+ );
184+ const organizations = getAllPosts(
185+ ["title", "image", "slug"],
186+ "organizations"
187+ );
188+ const applications = fs
189+ .readdirSync(join(process.cwd(), "content/applications"), {
190+ withFileTypes: true,
191+ })
192+ .filter((f) => f.isDirectory())
193+ .map((dir) =>
194+ getAllPosts(
195+ ["title", "bgColor", "image", "slug", "description"],
196+ `applications/${dir.name}`
197+ )
198+ .map((e) => ({ ...e, ship: dir.name }))
199+ .flat()
200+ )
201+ .flat()
202+ .sort((a, b) => {
203+ const nameA = a.title.toLowerCase();
204+ const nameB = b.title.toLowerCase();
205+ return nameA < nameB ? -1 : 1;
206+ });
207+
208+ const groups = fs
209+ .readdirSync(join(process.cwd(), "content/groups"), {
210+ withFileTypes: true,
211+ })
212+ .filter((f) => f.isDirectory())
213+ .map((dir) =>
214+ getAllPosts(
215+ ["title", "tile", "slug", "description"],
216+ `groups/${dir.name}`
217+ )
218+ .map((e) => ({ ...e, ship: dir.name }))
219+ .flat()
220+ )
221+ .flat()
222+ .sort((a, b) => {
223+ const nameA = a.title.toLowerCase();
224+ const nameB = b.title.toLowerCase();
225+ return nameA < nameB ? -1 : 1;
226+ });
227+
228+ ["featured-1", "featured-2", "featured-3"].forEach((feat) => {
229+ if (ecosystem?.[feat]) {
230+ const matchedPost = [
231+ ...articles.map((e) => ({ ...e, type: "Article" })),
232+ ...applications.map((e) => ({ ...e, type: "Application" })),
233+ ...organizations.map((e) => ({ ...e, type: "Organization" })),
234+ ...podcasts.map((e) => ({ ...e, type: "Podcast" })),
235+ ...marketplaces.map((e) => ({ ...e, type: "Marketplace" })),
236+ ...groups.map((e) => ({ ...e, type: "Group" }))
237+ ].filter((e) => e.title === ecosystem[feat].title)?.[0];
238+ ecosystem[feat].image =
239+ ecosystem[feat].image || matchedPost?.image || null;
240+ ecosystem[feat].type = matchedPost?.type || "Podcast";
241+ ecosystem[feat].matchedPost = matchedPost || null;
242+ ecosystem[feat].content = JSON.stringify(
243+ Markdown.parse({
244+ post: { content: ecosystem[feat].content },
245+ })
246+ );
247+ }
248+ });
249+
250+ return ecosystem;
251+}
package-lock.json+370−325
@@ -12,7 +12,7 @@
1212 "@socialgouv/matomo-next": "^1.3.0",
1313 "@tailwindcss/aspect-ratio": "^0.4.0",
1414 "@tlon/sigil-js": "^1.4.5",
15− "@urbit/foundation-design-system": "^0.4.1",
15+ "@urbit/foundation-design-system": "0.7.3",
1616 "@urbit/markdoc": "^0.1.4",
1717 "axios": "^0.26.1",
1818 "buffer": "^6.0.3",
@@ -48,11 +48,11 @@
4848 }
4949 },
5050 "node_modules/@babel/runtime": {
51− "version": "7.18.9",
52− "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
53− "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
51+ "version": "7.20.1",
52+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz",
53+ "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==",
5454 "dependencies": {
55− "regenerator-runtime": "^0.13.4"
55+ "regenerator-runtime": "^0.13.10"
5656 },
5757 "engines": {
5858 "node": ">=6.9.0"
@@ -64,9 +64,9 @@
6464 "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
6565 },
6666 "node_modules/@mapbox/node-pre-gyp": {
67− "version": "1.0.9",
68− "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
69− "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
67+ "version": "1.0.10",
68+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz",
69+ "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==",
7070 "dependencies": {
7171 "detect-libc": "^2.0.0",
7272 "https-proxy-agent": "^5.0.0",
@@ -83,14 +83,14 @@
8383 }
8484 },
8585 "node_modules/@next/env": {
86− "version": "12.2.5",
87− "resolved": "https://registry.npmjs.org/@next/env/-/env-12.2.5.tgz",
88− "integrity": "sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw=="
86+ "version": "12.3.3",
87+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.3.tgz",
88+ "integrity": "sha512-H2pKuOasV9RgvVaWosB2rGSNeQShQpiDaF4EEjLyagIc3HwqdOw2/VAG/8Lq+adOwPv2P73O1hulTNad3k5MDw=="
8989 },
9090 "node_modules/@next/swc-android-arm-eabi": {
91− "version": "12.2.5",
92− "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz",
93− "integrity": "sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==",
91+ "version": "12.3.3",
92+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.3.tgz",
93+ "integrity": "sha512-5O/ZIX6hlIRGMy1R2f/8WiCZ4Hp4WTC0FcTuz8ycQ28j/mzDnmzjVoayVVr+ZmfEKQayFrRu+vxHjFyY0JGQlQ==",
9494 "cpu": [
9595 "arm"
9696 ],
@@ -103,9 +103,9 @@
103103 }
104104 },
105105 "node_modules/@next/swc-android-arm64": {
106− "version": "12.2.5",
107− "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz",
108− "integrity": "sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==",
106+ "version": "12.3.3",
107+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.3.tgz",
108+ "integrity": "sha512-2QWreRmlxYRDtnLYn+BI8oukHwcP7W0zGIY5R2mEXRjI4ARqCLdu8RmcT9Vemw7RfeAVKA/4cv/9PY0pCcQpNA==",
109109 "cpu": [
110110 "arm64"
111111 ],
@@ -118,9 +118,9 @@
118118 }
119119 },
120120 "node_modules/@next/swc-darwin-arm64": {
121− "version": "12.2.5",
122− "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz",
123− "integrity": "sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==",
121+ "version": "12.3.3",
122+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.3.tgz",
123+ "integrity": "sha512-GtZdDLerM+VToCMFp+W+WhnT6sxHePQH4xZZiYD/Y8KFiwHbDRcJr2FPG0bAJnGNiSvv/QQnBq74wjZ9+7vhcQ==",
124124 "cpu": [
125125 "arm64"
126126 ],
@@ -133,9 +133,9 @@
133133 }
134134 },
135135 "node_modules/@next/swc-darwin-x64": {
136− "version": "12.2.5",
137− "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz",
138− "integrity": "sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==",
136+ "version": "12.3.3",
137+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.3.tgz",
138+ "integrity": "sha512-gRYvTKrRYynjFQUDJ+upHMcBiNz0ii0m7zGgmUTlTSmrBWqVSzx79EHYT7Nn4GWHM+a/W+2VXfu+lqHcJeQ9gQ==",
139139 "cpu": [
140140 "x64"
141141 ],
@@ -148,9 +148,9 @@
148148 }
149149 },
150150 "node_modules/@next/swc-freebsd-x64": {
151− "version": "12.2.5",
152− "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz",
153− "integrity": "sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==",
151+ "version": "12.3.3",
152+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.3.tgz",
153+ "integrity": "sha512-r+GLATzCjjQI82bgrIPXWEYBwZonSO64OThk5wU6HduZlDYTEDxZsFNoNoesCDWCgRrgg+OXj7WLNy1WlvfX7w==",
154154 "cpu": [
155155 "x64"
156156 ],
@@ -163,9 +163,9 @@
163163 }
164164 },
165165 "node_modules/@next/swc-linux-arm-gnueabihf": {
166− "version": "12.2.5",
167− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz",
168− "integrity": "sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==",
166+ "version": "12.3.3",
167+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.3.tgz",
168+ "integrity": "sha512-juvRj1QX9jmQScL4nV0rROtYUFgWP76zfdn1fdfZ2BhvwUugIAq8x+jLVGlnXKUhDrP9+RrAufqXjjVkK+uBxA==",
169169 "cpu": [
170170 "arm"
171171 ],
@@ -178,9 +178,9 @@
178178 }
179179 },
180180 "node_modules/@next/swc-linux-arm64-gnu": {
181− "version": "12.2.5",
182− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz",
183− "integrity": "sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==",
181+ "version": "12.3.3",
182+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.3.tgz",
183+ "integrity": "sha512-hzinybStPB+SzS68hR5rzOngOH7Yd/jFuWGeg9qS5WifYXHpqwGH2BQeKpjVV0iJuyO9r309JKrRWMrbfhnuBA==",
184184 "cpu": [
185185 "arm64"
186186 ],
@@ -193,9 +193,9 @@
193193 }
194194 },
195195 "node_modules/@next/swc-linux-arm64-musl": {
196− "version": "12.2.5",
197− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz",
198− "integrity": "sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==",
196+ "version": "12.3.3",
197+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.3.tgz",
198+ "integrity": "sha512-oyfQYljCwf+9zUu1YkTZbRbyxmcHzvJPMGOxC3kJOReh3kCUoGcmvAxUPMtFD6FSYjJ+eaog4+2IFHtYuAw/bQ==",
199199 "cpu": [
200200 "arm64"
201201 ],
@@ -208,9 +208,9 @@
208208 }
209209 },
210210 "node_modules/@next/swc-linux-x64-gnu": {
211− "version": "12.2.5",
212− "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz",
213− "integrity": "sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==",
211+ "version": "12.3.3",
212+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.3.tgz",
213+ "integrity": "sha512-epv4FMazj/XG70KTTnrZ0H1VtL6DeWOvyHLHYy7f5PdgDpBXpDTFjVqhP8NFNH8HmaDDdeL1NvQD07AXhyvUKA==",
214214 "cpu": [
215215 "x64"
216216 ],
@@ -223,9 +223,9 @@
223223 }
224224 },
225225 "node_modules/@next/swc-linux-x64-musl": {
226− "version": "12.2.5",
227− "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz",
228− "integrity": "sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==",
226+ "version": "12.3.3",
227+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.3.tgz",
228+ "integrity": "sha512-bG5QODFy59XnSFTiPyIAt+rbPdphtvQMibtOVvyjwIwsBUw7swJ6k+6PSPVYEYpi6SHzi3qYBsro39ayGJKQJg==",
229229 "cpu": [
230230 "x64"
231231 ],
@@ -238,9 +238,9 @@
238238 }
239239 },
240240 "node_modules/@next/swc-win32-arm64-msvc": {
241− "version": "12.2.5",
242− "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz",
243− "integrity": "sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==",
241+ "version": "12.3.3",
242+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.3.tgz",
243+ "integrity": "sha512-FbnT3reJ3MbTJ5W0hvlCCGGVDSpburzT5XGC9ljBJ4kr+85iNTLjv7+vrPeDdwHEqtGmdZgnabkLVCI4yFyCag==",
244244 "cpu": [
245245 "arm64"
246246 ],
@@ -253,9 +253,9 @@
253253 }
254254 },
255255 "node_modules/@next/swc-win32-ia32-msvc": {
256− "version": "12.2.5",
257− "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz",
258− "integrity": "sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==",
256+ "version": "12.3.3",
257+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.3.tgz",
258+ "integrity": "sha512-M/fKZC2tMGWA6eTsIniNEBpx2prdR8lIxvSO3gv5P6ymZOGVWCvEMksnTkPAjHnU6d8r8eCiuGKm3UNo7zCTpQ==",
259259 "cpu": [
260260 "ia32"
261261 ],
@@ -268,9 +268,9 @@
268268 }
269269 },
270270 "node_modules/@next/swc-win32-x64-msvc": {
271− "version": "12.2.5",
272− "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz",
273− "integrity": "sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==",
271+ "version": "12.3.3",
272+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.3.tgz",
273+ "integrity": "sha512-Ku9mfGwmNtk44o4B/jEWUxBAT4tJ3S7QbBMLJdL1GmtRZ05LGL36OqWjLvBPr8dFiHOQQbYoAmYfQw7zeGypYA==",
274274 "cpu": [
275275 "x64"
276276 ],
@@ -323,17 +323,17 @@
323323 }
324324 },
325325 "node_modules/@swc/helpers": {
326− "version": "0.4.3",
327− "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.3.tgz",
328− "integrity": "sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==",
326+ "version": "0.4.11",
327+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
328+ "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
329329 "dependencies": {
330330 "tslib": "^2.4.0"
331331 }
332332 },
333333 "node_modules/@tailwindcss/aspect-ratio": {
334− "version": "0.4.0",
335− "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.0.tgz",
336− "integrity": "sha512-WJu0I4PpqNPuutpaA9zDUq2JXR+lorZ7PbLcKNLmb6GL9/HLfC7w3CRsMhJF4BbYd/lkY6CfXOvkYpuGnZfkpQ==",
334+ "version": "0.4.2",
335+ "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz",
336+ "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==",
337337 "peerDependencies": {
338338 "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
339339 }
@@ -358,16 +358,21 @@
358358 "dev": true
359359 },
360360 "node_modules/@urbit/foundation-design-system": {
361− "version": "0.4.1",
362− "resolved": "https://registry.npmjs.org/@urbit/foundation-design-system/-/foundation-design-system-0.4.1.tgz",
363− "integrity": "sha512-EFGtqABqIlJYQhaCJ7p/GlS0Wq2MrtF1H0vXC5p1l+na+aV5CGT0oXIR5dDt4hUgCD1gh9rX0QI9qnu2YKpAeA==",
361+ "version": "0.7.3",
362+ "resolved": "https://registry.npmjs.org/@urbit/foundation-design-system/-/foundation-design-system-0.7.3.tgz",
363+ "integrity": "sha512-txg6G2Gv7thd04YqStVilX2CJrkkwrLrWEZx7DaclB+tq1q7Eh9Uud51J2QIytIE/SvWak/innapLL0bUNZI0Q==",
364364 "dependencies": {
365365 "@iarna/toml": "^2.2.5",
366+ "@tlon/sigil-js": "^1.4.5",
366367 "core-js": "^3.23.1",
368+ "downshift": "^7.0.1",
367369 "gray-matter": "^4.0.3",
368370 "html-react-parser": "^1.4.14",
371+ "lodash.debounce": "^4.0.8",
369372 "luxon": "^3.0.1",
370− "prism-react-renderer": "^1.3.3"
373+ "prism-react-renderer": "^1.3.3",
374+ "react-swipeable": "^6.2.1",
375+ "urbit-ob": "^5.0.1"
371376 },
372377 "peerDependencies": {
373378 "@tailwindcss/aspect-ratio": "^0.4.0",
@@ -376,17 +381,32 @@
376381 "classnames": "^2.3.1",
377382 "next": "^12.1.6",
378383 "postcss": "^8.4.14",
379− "prismjs": "^1.28.0",
384+ "prismjs": "^1.29.0",
380385 "react": "^17.0.2",
381386 "react-dom": "^17.0.2",
382387 "tailwindcss": "^3.1.3",
383388 "tailwindcss-theme-swapper": "^0.6.2"
384389 }
385390 },
391+ "node_modules/@urbit/foundation-design-system/node_modules/downshift": {
392+ "version": "7.0.1",
393+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-7.0.1.tgz",
394+ "integrity": "sha512-AdFU8qJjUg9WZaLKzh7xAPfEwAB0dSqDGb7/Gnx/teldUXcNlaZrxhymOWedzDV+62xphMVustttAngmG33pXw==",
395+ "dependencies": {
396+ "@babel/runtime": "^7.14.8",
397+ "compute-scroll-into-view": "^1.0.17",
398+ "prop-types": "^15.7.2",
399+ "react-is": "^17.0.2",
400+ "tslib": "^2.3.0"
401+ },
402+ "peerDependencies": {
403+ "react": ">=16.12.0"
404+ }
405+ },
386406 "node_modules/@urbit/foundation-design-system/node_modules/luxon": {
387− "version": "3.0.1",
388− "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.0.1.tgz",
389− "integrity": "sha512-hF3kv0e5gwHQZKz4wtm4c+inDtyc7elkanAsBq+fundaCdUBNJB1dHEGUZIM6SfSBUlbVFduPwEtNjFK8wLtcw==",
407+ "version": "3.1.0",
408+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.1.0.tgz",
409+ "integrity": "sha512-7w6hmKC0/aoWnEsmPCu5Br54BmbmUp5GfcqBxQngRcXJ+q5fdfjEzn7dxmJh2YdDhgW8PccYtlWKSv4tQkrTQg==",
390410 "engines": {
391411 "node": ">=12"
392412 }
@@ -537,9 +557,9 @@
537557 }
538558 },
539559 "node_modules/autoprefixer": {
540− "version": "10.4.8",
541− "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz",
542− "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==",
560+ "version": "10.4.13",
561+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
562+ "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
543563 "funding": [
544564 {
545565 "type": "opencollective",
@@ -551,8 +571,8 @@
551571 }
552572 ],
553573 "dependencies": {
554− "browserslist": "^4.21.3",
555− "caniuse-lite": "^1.0.30001373",
574+ "browserslist": "^4.21.4",
575+ "caniuse-lite": "^1.0.30001426",
556576 "fraction.js": "^4.2.0",
557577 "normalize-range": "^0.1.2",
558578 "picocolors": "^1.0.0",
@@ -634,9 +654,9 @@
634654 }
635655 },
636656 "node_modules/browserslist": {
637− "version": "4.21.3",
638− "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
639− "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
657+ "version": "4.21.4",
658+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
659+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
640660 "funding": [
641661 {
642662 "type": "opencollective",
@@ -648,10 +668,10 @@
648668 }
649669 ],
650670 "dependencies": {
651− "caniuse-lite": "^1.0.30001370",
652− "electron-to-chromium": "^1.4.202",
671+ "caniuse-lite": "^1.0.30001400",
672+ "electron-to-chromium": "^1.4.251",
653673 "node-releases": "^2.0.6",
654− "update-browserslist-db": "^1.0.5"
674+ "update-browserslist-db": "^1.0.9"
655675 },
656676 "bin": {
657677 "browserslist": "cli.js"
@@ -692,9 +712,9 @@
692712 }
693713 },
694714 "node_modules/caniuse-lite": {
695− "version": "1.0.30001382",
696− "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz",
697− "integrity": "sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==",
715+ "version": "1.0.30001431",
716+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz",
717+ "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==",
698718 "funding": [
699719 {
700720 "type": "opencollective",
@@ -707,13 +727,13 @@
707727 ]
708728 },
709729 "node_modules/canvas": {
710− "version": "2.9.3",
711− "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz",
712− "integrity": "sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw==",
730+ "version": "2.10.2",
731+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.10.2.tgz",
732+ "integrity": "sha512-FSmlsip0nZ0U4Zcfht0qBJqDhlfGuevTZKE8h+dBOYrJjGvY3iqMGSzzbvkaFhvMXiVxfcMaPHS/kge++T5SKg==",
713733 "hasInstallScript": true,
714734 "dependencies": {
715735 "@mapbox/node-pre-gyp": "^1.0.0",
716− "nan": "^2.15.0",
736+ "nan": "^2.17.0",
717737 "simple-get": "^3.0.3"
718738 },
719739 "engines": {
@@ -779,9 +799,9 @@
779799 }
780800 },
781801 "node_modules/classnames": {
782− "version": "2.3.1",
783− "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
784− "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
802+ "version": "2.3.2",
803+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
804+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
785805 },
786806 "node_modules/color": {
787807 "version": "4.2.3",
@@ -844,9 +864,9 @@
844864 "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
845865 },
846866 "node_modules/core-js": {
847− "version": "3.24.1",
848− "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
849− "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==",
867+ "version": "3.26.1",
868+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
869+ "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==",
850870 "hasInstallScript": true,
851871 "funding": {
852872 "type": "opencollective",
@@ -937,9 +957,12 @@
937957 }
938958 },
939959 "node_modules/defined": {
940− "version": "1.0.0",
941− "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
942− "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ=="
960+ "version": "1.0.1",
961+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
962+ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
963+ "funding": {
964+ "url": "https://github.com/sponsors/ljharb"
965+ }
943966 },
944967 "node_modules/delegates": {
945968 "version": "1.0.0",
@@ -1040,9 +1063,9 @@
10401063 }
10411064 },
10421065 "node_modules/downshift": {
1043− "version": "6.1.9",
1044− "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.9.tgz",
1045− "integrity": "sha512-mzvk61WOX4MEsYHMKCXEVwuz/zM84x/WrCbaCQw71hyNN0fmWXvV673uOQy2idgIA+yqDsjtkV5KPfAFWuQylg==",
1066+ "version": "6.1.12",
1067+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.12.tgz",
1068+ "integrity": "sha512-7XB/iaSJVS4T8wGFT3WRXmSF1UlBHAA40DshZtkrIscIN+VC+Lh363skLxFTvJwtNgHxAMDGEHT4xsyQFWL+UA==",
10461069 "dependencies": {
10471070 "@babel/runtime": "^7.14.8",
10481071 "compute-scroll-into-view": "^1.0.17",
@@ -1055,9 +1078,9 @@
10551078 }
10561079 },
10571080 "node_modules/electron-to-chromium": {
1058− "version": "1.4.228",
1059− "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.228.tgz",
1060− "integrity": "sha512-XfDHCvou7CsDMlFwb0WZ1tWmW48e7Sn7VBRyPfZsZZila9esRsJl1trO+OqDNV97GggFSt0ISbWslKXfQkG//g=="
1081+ "version": "1.4.284",
1082+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
1083+ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
10611084 },
10621085 "node_modules/emoji-regex": {
10631086 "version": "8.0.0",
@@ -1144,9 +1167,9 @@
11441167 }
11451168 },
11461169 "node_modules/fast-glob": {
1147− "version": "3.2.11",
1148− "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
1149− "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
1170+ "version": "3.2.12",
1171+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
1172+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
11501173 "dependencies": {
11511174 "@nodelib/fs.stat": "^2.0.2",
11521175 "@nodelib/fs.walk": "^1.2.3",
@@ -1213,9 +1236,9 @@
12131236 }
12141237 },
12151238 "node_modules/follow-redirects": {
1216− "version": "1.15.1",
1217− "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
1218− "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
1239+ "version": "1.15.2",
1240+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
1241+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
12191242 "funding": [
12201243 {
12211244 "type": "individual",
@@ -1559,9 +1582,9 @@
15591582 "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
15601583 },
15611584 "node_modules/is-core-module": {
1562− "version": "2.10.0",
1563− "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
1564− "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
1585+ "version": "2.11.0",
1586+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
1587+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
15651588 "dependencies": {
15661589 "has": "^1.0.3"
15671590 },
@@ -1845,9 +1868,12 @@
18451868 }
18461869 },
18471870 "node_modules/minimist": {
1848− "version": "1.2.6",
1849− "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
1850− "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
1871+ "version": "1.2.7",
1872+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
1873+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
1874+ "funding": {
1875+ "url": "https://github.com/sponsors/ljharb"
1876+ }
18511877 },
18521878 "node_modules/minipass": {
18531879 "version": "3.3.4",
@@ -1914,9 +1940,9 @@
19141940 }
19151941 },
19161942 "node_modules/nan": {
1917− "version": "2.16.0",
1918− "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
1919− "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
1943+ "version": "2.17.0",
1944+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
1945+ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
19201946 },
19211947 "node_modules/nanoid": {
19221948 "version": "3.3.4",
@@ -1930,15 +1956,15 @@
19301956 }
19311957 },
19321958 "node_modules/next": {
1933− "version": "12.2.5",
1934− "resolved": "https://registry.npmjs.org/next/-/next-12.2.5.tgz",
1935− "integrity": "sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==",
1959+ "version": "12.3.3",
1960+ "resolved": "https://registry.npmjs.org/next/-/next-12.3.3.tgz",
1961+ "integrity": "sha512-Rx2Y6Wl5R8E77NOfBupp/B9OPCklqfqD0yN2+rDivhMjd6hjVFH5n0WTDI4PWwDmZsdNcYt6NV85kJ3PLR+eNQ==",
19361962 "dependencies": {
1937− "@next/env": "12.2.5",
1938− "@swc/helpers": "0.4.3",
1939− "caniuse-lite": "^1.0.30001332",
1963+ "@next/env": "12.3.3",
1964+ "@swc/helpers": "0.4.11",
1965+ "caniuse-lite": "^1.0.30001406",
19401966 "postcss": "8.4.14",
1941− "styled-jsx": "5.0.4",
1967+ "styled-jsx": "5.0.7",
19421968 "use-sync-external-store": "1.2.0"
19431969 },
19441970 "bin": {
@@ -1948,19 +1974,19 @@
19481974 "node": ">=12.22.0"
19491975 },
19501976 "optionalDependencies": {
1951− "@next/swc-android-arm-eabi": "12.2.5",
1952− "@next/swc-android-arm64": "12.2.5",
1953− "@next/swc-darwin-arm64": "12.2.5",
1954− "@next/swc-darwin-x64": "12.2.5",
1955− "@next/swc-freebsd-x64": "12.2.5",
1956− "@next/swc-linux-arm-gnueabihf": "12.2.5",
1957− "@next/swc-linux-arm64-gnu": "12.2.5",
1958− "@next/swc-linux-arm64-musl": "12.2.5",
1959− "@next/swc-linux-x64-gnu": "12.2.5",
1960− "@next/swc-linux-x64-musl": "12.2.5",
1961− "@next/swc-win32-arm64-msvc": "12.2.5",
1962− "@next/swc-win32-ia32-msvc": "12.2.5",
1963− "@next/swc-win32-x64-msvc": "12.2.5"
1977+ "@next/swc-android-arm-eabi": "12.3.3",
1978+ "@next/swc-android-arm64": "12.3.3",
1979+ "@next/swc-darwin-arm64": "12.3.3",
1980+ "@next/swc-darwin-x64": "12.3.3",
1981+ "@next/swc-freebsd-x64": "12.3.3",
1982+ "@next/swc-linux-arm-gnueabihf": "12.3.3",
1983+ "@next/swc-linux-arm64-gnu": "12.3.3",
1984+ "@next/swc-linux-arm64-musl": "12.3.3",
1985+ "@next/swc-linux-x64-gnu": "12.3.3",
1986+ "@next/swc-linux-x64-musl": "12.3.3",
1987+ "@next/swc-win32-arm64-msvc": "12.3.3",
1988+ "@next/swc-win32-ia32-msvc": "12.3.3",
1989+ "@next/swc-win32-x64-msvc": "12.3.3"
19641990 },
19651991 "peerDependencies": {
19661992 "fibers": ">= 3.1.0",
@@ -2229,9 +2255,9 @@
22292255 }
22302256 },
22312257 "node_modules/postcss": {
2232− "version": "8.4.16",
2233− "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
2234− "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
2258+ "version": "8.4.19",
2259+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
2260+ "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
22352261 "funding": [
22362262 {
22372263 "type": "opencollective",
@@ -2314,11 +2340,11 @@
23142340 }
23152341 },
23162342 "node_modules/postcss-nested": {
2317− "version": "5.0.6",
2318− "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz",
2319− "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==",
2343+ "version": "6.0.0",
2344+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
2345+ "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
23202346 "dependencies": {
2321− "postcss-selector-parser": "^6.0.6"
2347+ "postcss-selector-parser": "^6.0.10"
23222348 },
23232349 "engines": {
23242350 "node": ">=12.0"
@@ -2560,9 +2586,9 @@
25602586 }
25612587 },
25622588 "node_modules/regenerator-runtime": {
2563− "version": "0.13.9",
2564− "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
2565− "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
2589+ "version": "0.13.10",
2590+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
2591+ "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
25662592 },
25672593 "node_modules/rename-keys": {
25682594 "version": "1.2.0",
@@ -2679,9 +2705,9 @@
26792705 }
26802706 },
26812707 "node_modules/semver": {
2682− "version": "7.3.7",
2683− "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
2684− "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
2708+ "version": "7.3.8",
2709+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
2710+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
26852711 "dependencies": {
26862712 "lru-cache": "^6.0.0"
26872713 },
@@ -2848,9 +2874,9 @@
28482874 }
28492875 },
28502876 "node_modules/styled-jsx": {
2851− "version": "5.0.4",
2852− "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.4.tgz",
2853− "integrity": "sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==",
2877+ "version": "5.0.7",
2878+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
2879+ "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
28542880 "engines": {
28552881 "node": ">= 12.0.0"
28562882 },
@@ -2900,9 +2926,9 @@
29002926 }
29012927 },
29022928 "node_modules/tailwindcss": {
2903− "version": "3.1.8",
2904− "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz",
2905− "integrity": "sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==",
2929+ "version": "3.2.4",
2930+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
2931+ "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==",
29062932 "dependencies": {
29072933 "arg": "^5.0.2",
29082934 "chokidar": "^3.5.3",
@@ -2910,18 +2936,19 @@
29102936 "detective": "^5.2.1",
29112937 "didyoumean": "^1.2.2",
29122938 "dlv": "^1.1.3",
2913− "fast-glob": "^3.2.11",
2939+ "fast-glob": "^3.2.12",
29142940 "glob-parent": "^6.0.2",
29152941 "is-glob": "^4.0.3",
29162942 "lilconfig": "^2.0.6",
2943+ "micromatch": "^4.0.5",
29172944 "normalize-path": "^3.0.0",
29182945 "object-hash": "^3.0.0",
29192946 "picocolors": "^1.0.0",
2920− "postcss": "^8.4.14",
2947+ "postcss": "^8.4.18",
29212948 "postcss-import": "^14.1.0",
29222949 "postcss-js": "^4.0.0",
29232950 "postcss-load-config": "^3.1.4",
2924− "postcss-nested": "5.0.6",
2951+ "postcss-nested": "6.0.0",
29252952 "postcss-selector-parser": "^6.0.10",
29262953 "postcss-value-parser": "^4.2.0",
29272954 "quick-lru": "^5.1.1",
@@ -2949,9 +2976,9 @@
29492976 }
29502977 },
29512978 "node_modules/tar": {
2952− "version": "6.1.11",
2953− "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
2954− "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
2979+ "version": "6.1.12",
2980+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz",
2981+ "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==",
29552982 "dependencies": {
29562983 "chownr": "^2.0.0",
29572984 "fs-minipass": "^2.0.0",
@@ -2961,7 +2988,7 @@
29612988 "yallist": "^4.0.0"
29622989 },
29632990 "engines": {
2964− "node": ">= 10"
2991+ "node": ">=10"
29652992 }
29662993 },
29672994 "node_modules/to-regex-range": {
@@ -2986,9 +3013,9 @@
29863013 "integrity": "sha512-74MoNHhwLVuzwaPDcAecFjSkOA9vwWqyOdkeB0Be8Jc/IWSS5SNZKapFllqzkTliqZptkvqX5CZnVeDvfhN8cw=="
29873014 },
29883015 "node_modules/tslib": {
2989− "version": "2.4.0",
2990− "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
2991− "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
3016+ "version": "2.4.1",
3017+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
3018+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
29923019 },
29933020 "node_modules/unset-value": {
29943021 "version": "0.1.2",
@@ -3003,9 +3030,9 @@
30033030 }
30043031 },
30053032 "node_modules/update-browserslist-db": {
3006− "version": "1.0.5",
3007− "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
3008− "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
3033+ "version": "1.0.10",
3034+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
3035+ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
30093036 "funding": [
30103037 {
30113038 "type": "opencollective",
@@ -3144,11 +3171,11 @@
31443171 },
31453172 "dependencies": {
31463173 "@babel/runtime": {
3147− "version": "7.18.9",
3148− "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
3149− "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
3174+ "version": "7.20.1",
3175+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz",
3176+ "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==",
31503177 "requires": {
3151− "regenerator-runtime": "^0.13.4"
3178+ "regenerator-runtime": "^0.13.10"
31523179 }
31533180 },
31543181 "@iarna/toml": {
@@ -3157,9 +3184,9 @@
31573184 "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
31583185 },
31593186 "@mapbox/node-pre-gyp": {
3160− "version": "1.0.9",
3161− "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
3162− "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
3187+ "version": "1.0.10",
3188+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz",
3189+ "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==",
31633190 "requires": {
31643191 "detect-libc": "^2.0.0",
31653192 "https-proxy-agent": "^5.0.0",
@@ -3173,86 +3200,86 @@
31733200 }
31743201 },
31753202 "@next/env": {
3176− "version": "12.2.5",
3177− "resolved": "https://registry.npmjs.org/@next/env/-/env-12.2.5.tgz",
3178− "integrity": "sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw=="
3203+ "version": "12.3.3",
3204+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.3.tgz",
3205+ "integrity": "sha512-H2pKuOasV9RgvVaWosB2rGSNeQShQpiDaF4EEjLyagIc3HwqdOw2/VAG/8Lq+adOwPv2P73O1hulTNad3k5MDw=="
31793206 },
31803207 "@next/swc-android-arm-eabi": {
3181− "version": "12.2.5",
3182− "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz",
3183− "integrity": "sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==",
3208+ "version": "12.3.3",
3209+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.3.tgz",
3210+ "integrity": "sha512-5O/ZIX6hlIRGMy1R2f/8WiCZ4Hp4WTC0FcTuz8ycQ28j/mzDnmzjVoayVVr+ZmfEKQayFrRu+vxHjFyY0JGQlQ==",
31843211 "optional": true
31853212 },
31863213 "@next/swc-android-arm64": {
3187− "version": "12.2.5",
3188− "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz",
3189− "integrity": "sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==",
3214+ "version": "12.3.3",
3215+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.3.tgz",
3216+ "integrity": "sha512-2QWreRmlxYRDtnLYn+BI8oukHwcP7W0zGIY5R2mEXRjI4ARqCLdu8RmcT9Vemw7RfeAVKA/4cv/9PY0pCcQpNA==",
31903217 "optional": true
31913218 },
31923219 "@next/swc-darwin-arm64": {
3193− "version": "12.2.5",
3194− "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz",
3195− "integrity": "sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==",
3220+ "version": "12.3.3",
3221+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.3.tgz",
3222+ "integrity": "sha512-GtZdDLerM+VToCMFp+W+WhnT6sxHePQH4xZZiYD/Y8KFiwHbDRcJr2FPG0bAJnGNiSvv/QQnBq74wjZ9+7vhcQ==",
31963223 "optional": true
31973224 },
31983225 "@next/swc-darwin-x64": {
3199− "version": "12.2.5",
3200− "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz",
3201− "integrity": "sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==",
3226+ "version": "12.3.3",
3227+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.3.tgz",
3228+ "integrity": "sha512-gRYvTKrRYynjFQUDJ+upHMcBiNz0ii0m7zGgmUTlTSmrBWqVSzx79EHYT7Nn4GWHM+a/W+2VXfu+lqHcJeQ9gQ==",
32023229 "optional": true
32033230 },
32043231 "@next/swc-freebsd-x64": {
3205− "version": "12.2.5",
3206− "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz",
3207− "integrity": "sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==",
3232+ "version": "12.3.3",
3233+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.3.tgz",
3234+ "integrity": "sha512-r+GLATzCjjQI82bgrIPXWEYBwZonSO64OThk5wU6HduZlDYTEDxZsFNoNoesCDWCgRrgg+OXj7WLNy1WlvfX7w==",
32083235 "optional": true
32093236 },
32103237 "@next/swc-linux-arm-gnueabihf": {
3211− "version": "12.2.5",
3212− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz",
3213− "integrity": "sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==",
3238+ "version": "12.3.3",
3239+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.3.tgz",
3240+ "integrity": "sha512-juvRj1QX9jmQScL4nV0rROtYUFgWP76zfdn1fdfZ2BhvwUugIAq8x+jLVGlnXKUhDrP9+RrAufqXjjVkK+uBxA==",
32143241 "optional": true
32153242 },
32163243 "@next/swc-linux-arm64-gnu": {
3217− "version": "12.2.5",
3218− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz",
3219− "integrity": "sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==",
3244+ "version": "12.3.3",
3245+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.3.tgz",
3246+ "integrity": "sha512-hzinybStPB+SzS68hR5rzOngOH7Yd/jFuWGeg9qS5WifYXHpqwGH2BQeKpjVV0iJuyO9r309JKrRWMrbfhnuBA==",
32203247 "optional": true
32213248 },
32223249 "@next/swc-linux-arm64-musl": {
3223− "version": "12.2.5",
3224− "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz",
3225− "integrity": "sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==",
3250+ "version": "12.3.3",
3251+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.3.tgz",
3252+ "integrity": "sha512-oyfQYljCwf+9zUu1YkTZbRbyxmcHzvJPMGOxC3kJOReh3kCUoGcmvAxUPMtFD6FSYjJ+eaog4+2IFHtYuAw/bQ==",
32263253 "optional": true
32273254 },
32283255 "@next/swc-linux-x64-gnu": {
3229− "version": "12.2.5",
3230− "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz",
3231− "integrity": "sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==",
3256+ "version": "12.3.3",
3257+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.3.tgz",
3258+ "integrity": "sha512-epv4FMazj/XG70KTTnrZ0H1VtL6DeWOvyHLHYy7f5PdgDpBXpDTFjVqhP8NFNH8HmaDDdeL1NvQD07AXhyvUKA==",
32323259 "optional": true
32333260 },
32343261 "@next/swc-linux-x64-musl": {
3235− "version": "12.2.5",
3236− "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz",
3237− "integrity": "sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==",
3262+ "version": "12.3.3",
3263+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.3.tgz",
3264+ "integrity": "sha512-bG5QODFy59XnSFTiPyIAt+rbPdphtvQMibtOVvyjwIwsBUw7swJ6k+6PSPVYEYpi6SHzi3qYBsro39ayGJKQJg==",
32383265 "optional": true
32393266 },
32403267 "@next/swc-win32-arm64-msvc": {
3241− "version": "12.2.5",
3242− "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz",
3243− "integrity": "sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==",
3268+ "version": "12.3.3",
3269+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.3.tgz",
3270+ "integrity": "sha512-FbnT3reJ3MbTJ5W0hvlCCGGVDSpburzT5XGC9ljBJ4kr+85iNTLjv7+vrPeDdwHEqtGmdZgnabkLVCI4yFyCag==",
32443271 "optional": true
32453272 },
32463273 "@next/swc-win32-ia32-msvc": {
3247− "version": "12.2.5",
3248− "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz",
3249− "integrity": "sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==",
3274+ "version": "12.3.3",
3275+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.3.tgz",
3276+ "integrity": "sha512-M/fKZC2tMGWA6eTsIniNEBpx2prdR8lIxvSO3gv5P6ymZOGVWCvEMksnTkPAjHnU6d8r8eCiuGKm3UNo7zCTpQ==",
32503277 "optional": true
32513278 },
32523279 "@next/swc-win32-x64-msvc": {
3253− "version": "12.2.5",
3254− "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz",
3255− "integrity": "sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==",
3280+ "version": "12.3.3",
3281+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.3.tgz",
3282+ "integrity": "sha512-Ku9mfGwmNtk44o4B/jEWUxBAT4tJ3S7QbBMLJdL1GmtRZ05LGL36OqWjLvBPr8dFiHOQQbYoAmYfQw7zeGypYA==",
32563283 "optional": true
32573284 },
32583285 "@nodelib/fs.scandir": {
@@ -3285,17 +3312,17 @@
32853312 "requires": {}
32863313 },
32873314 "@swc/helpers": {
3288− "version": "0.4.3",
3289− "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.3.tgz",
3290− "integrity": "sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==",
3315+ "version": "0.4.11",
3316+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
3317+ "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
32913318 "requires": {
32923319 "tslib": "^2.4.0"
32933320 }
32943321 },
32953322 "@tailwindcss/aspect-ratio": {
3296− "version": "0.4.0",
3297− "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.0.tgz",
3298− "integrity": "sha512-WJu0I4PpqNPuutpaA9zDUq2JXR+lorZ7PbLcKNLmb6GL9/HLfC7w3CRsMhJF4BbYd/lkY6CfXOvkYpuGnZfkpQ==",
3323+ "version": "0.4.2",
3324+ "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz",
3325+ "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==",
32993326 "requires": {}
33003327 },
33013328 "@tlon/sigil-js": {
@@ -3315,22 +3342,39 @@
33153342 "dev": true
33163343 },
33173344 "@urbit/foundation-design-system": {
3318− "version": "0.4.1",
3319− "resolved": "https://registry.npmjs.org/@urbit/foundation-design-system/-/foundation-design-system-0.4.1.tgz",
3320− "integrity": "sha512-EFGtqABqIlJYQhaCJ7p/GlS0Wq2MrtF1H0vXC5p1l+na+aV5CGT0oXIR5dDt4hUgCD1gh9rX0QI9qnu2YKpAeA==",
3345+ "version": "0.7.3",
3346+ "resolved": "https://registry.npmjs.org/@urbit/foundation-design-system/-/foundation-design-system-0.7.3.tgz",
3347+ "integrity": "sha512-txg6G2Gv7thd04YqStVilX2CJrkkwrLrWEZx7DaclB+tq1q7Eh9Uud51J2QIytIE/SvWak/innapLL0bUNZI0Q==",
33213348 "requires": {
33223349 "@iarna/toml": "^2.2.5",
3350+ "@tlon/sigil-js": "^1.4.5",
33233351 "core-js": "^3.23.1",
3352+ "downshift": "^7.0.1",
33243353 "gray-matter": "^4.0.3",
33253354 "html-react-parser": "^1.4.14",
3355+ "lodash.debounce": "^4.0.8",
33263356 "luxon": "^3.0.1",
3327− "prism-react-renderer": "^1.3.3"
3357+ "prism-react-renderer": "^1.3.3",
3358+ "react-swipeable": "^6.2.1",
3359+ "urbit-ob": "^5.0.1"
33283360 },
33293361 "dependencies": {
3362+ "downshift": {
3363+ "version": "7.0.1",
3364+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-7.0.1.tgz",
3365+ "integrity": "sha512-AdFU8qJjUg9WZaLKzh7xAPfEwAB0dSqDGb7/Gnx/teldUXcNlaZrxhymOWedzDV+62xphMVustttAngmG33pXw==",
3366+ "requires": {
3367+ "@babel/runtime": "^7.14.8",
3368+ "compute-scroll-into-view": "^1.0.17",
3369+ "prop-types": "^15.7.2",
3370+ "react-is": "^17.0.2",
3371+ "tslib": "^2.3.0"
3372+ }
3373+ },
33303374 "luxon": {
3331− "version": "3.0.1",
3332− "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.0.1.tgz",
3333− "integrity": "sha512-hF3kv0e5gwHQZKz4wtm4c+inDtyc7elkanAsBq+fundaCdUBNJB1dHEGUZIM6SfSBUlbVFduPwEtNjFK8wLtcw=="
3375+ "version": "3.1.0",
3376+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.1.0.tgz",
3377+ "integrity": "sha512-7w6hmKC0/aoWnEsmPCu5Br54BmbmUp5GfcqBxQngRcXJ+q5fdfjEzn7dxmJh2YdDhgW8PccYtlWKSv4tQkrTQg=="
33343378 }
33353379 }
33363380 },
@@ -3441,12 +3485,12 @@
34413485 "dev": true
34423486 },
34433487 "autoprefixer": {
3444− "version": "10.4.8",
3445− "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz",
3446− "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==",
3488+ "version": "10.4.13",
3489+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
3490+ "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
34473491 "requires": {
3448− "browserslist": "^4.21.3",
3449− "caniuse-lite": "^1.0.30001373",
3492+ "browserslist": "^4.21.4",
3493+ "caniuse-lite": "^1.0.30001426",
34503494 "fraction.js": "^4.2.0",
34513495 "normalize-range": "^0.1.2",
34523496 "picocolors": "^1.0.0",
@@ -3499,14 +3543,14 @@
34993543 }
35003544 },
35013545 "browserslist": {
3502− "version": "4.21.3",
3503− "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
3504− "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
3546+ "version": "4.21.4",
3547+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
3548+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
35053549 "requires": {
3506− "caniuse-lite": "^1.0.30001370",
3507− "electron-to-chromium": "^1.4.202",
3550+ "caniuse-lite": "^1.0.30001400",
3551+ "electron-to-chromium": "^1.4.251",
35083552 "node-releases": "^2.0.6",
3509− "update-browserslist-db": "^1.0.5"
3553+ "update-browserslist-db": "^1.0.9"
35103554 }
35113555 },
35123556 "buffer": {
@@ -3524,17 +3568,17 @@
35243568 "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
35253569 },
35263570 "caniuse-lite": {
3527− "version": "1.0.30001382",
3528− "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz",
3529− "integrity": "sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg=="
3571+ "version": "1.0.30001431",
3572+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz",
3573+ "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ=="
35303574 },
35313575 "canvas": {
3532− "version": "2.9.3",
3533− "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz",
3534− "integrity": "sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw==",
3576+ "version": "2.10.2",
3577+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.10.2.tgz",
3578+ "integrity": "sha512-FSmlsip0nZ0U4Zcfht0qBJqDhlfGuevTZKE8h+dBOYrJjGvY3iqMGSzzbvkaFhvMXiVxfcMaPHS/kge++T5SKg==",
35353579 "requires": {
35363580 "@mapbox/node-pre-gyp": "^1.0.0",
3537− "nan": "^2.15.0",
3581+ "nan": "^2.17.0",
35383582 "simple-get": "^3.0.3"
35393583 }
35403584 },
@@ -3579,9 +3623,9 @@
35793623 "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
35803624 },
35813625 "classnames": {
3582− "version": "2.3.1",
3583− "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
3584− "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
3626+ "version": "2.3.2",
3627+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
3628+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
35853629 },
35863630 "color": {
35873631 "version": "4.2.3",
@@ -3635,9 +3679,9 @@
36353679 "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
36363680 },
36373681 "core-js": {
3638− "version": "3.24.1",
3639− "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
3640− "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg=="
3682+ "version": "3.26.1",
3683+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
3684+ "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA=="
36413685 },
36423686 "cross-spawn": {
36433687 "version": "7.0.3",
@@ -3696,9 +3740,9 @@
36963740 "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
36973741 },
36983742 "defined": {
3699− "version": "1.0.0",
3700− "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
3701− "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ=="
3743+ "version": "1.0.1",
3744+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
3745+ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q=="
37023746 },
37033747 "delegates": {
37043748 "version": "1.0.0",
@@ -3771,9 +3815,9 @@
37713815 }
37723816 },
37733817 "downshift": {
3774− "version": "6.1.9",
3775− "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.9.tgz",
3776− "integrity": "sha512-mzvk61WOX4MEsYHMKCXEVwuz/zM84x/WrCbaCQw71hyNN0fmWXvV673uOQy2idgIA+yqDsjtkV5KPfAFWuQylg==",
3818+ "version": "6.1.12",
3819+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.12.tgz",
3820+ "integrity": "sha512-7XB/iaSJVS4T8wGFT3WRXmSF1UlBHAA40DshZtkrIscIN+VC+Lh363skLxFTvJwtNgHxAMDGEHT4xsyQFWL+UA==",
37773821 "requires": {
37783822 "@babel/runtime": "^7.14.8",
37793823 "compute-scroll-into-view": "^1.0.17",
@@ -3783,9 +3827,9 @@
37833827 }
37843828 },
37853829 "electron-to-chromium": {
3786− "version": "1.4.228",
3787− "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.228.tgz",
3788− "integrity": "sha512-XfDHCvou7CsDMlFwb0WZ1tWmW48e7Sn7VBRyPfZsZZila9esRsJl1trO+OqDNV97GggFSt0ISbWslKXfQkG//g=="
3830+ "version": "1.4.284",
3831+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
3832+ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
37893833 },
37903834 "emoji-regex": {
37913835 "version": "8.0.0",
@@ -3847,9 +3891,9 @@
38473891 }
38483892 },
38493893 "fast-glob": {
3850− "version": "3.2.11",
3851− "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
3852− "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
3894+ "version": "3.2.12",
3895+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
3896+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
38533897 "requires": {
38543898 "@nodelib/fs.stat": "^2.0.2",
38553899 "@nodelib/fs.walk": "^1.2.3",
@@ -3903,9 +3947,9 @@
39033947 }
39043948 },
39053949 "follow-redirects": {
3906− "version": "1.15.1",
3907− "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
3908− "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
3950+ "version": "1.15.2",
3951+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
3952+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
39093953 },
39103954 "fraction.js": {
39113955 "version": "4.2.0",
@@ -4145,9 +4189,9 @@
41454189 "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
41464190 },
41474191 "is-core-module": {
4148− "version": "2.10.0",
4149− "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
4150− "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
4192+ "version": "2.11.0",
4193+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
4194+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
41514195 "requires": {
41524196 "has": "^1.0.3"
41534197 }
@@ -4352,9 +4396,9 @@
43524396 }
43534397 },
43544398 "minimist": {
4355− "version": "1.2.6",
4356− "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
4357− "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
4399+ "version": "1.2.7",
4400+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
4401+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
43584402 },
43594403 "minipass": {
43604404 "version": "3.3.4",
@@ -4403,9 +4447,9 @@
44034447 }
44044448 },
44054449 "nan": {
4406− "version": "2.16.0",
4407− "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
4408− "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
4450+ "version": "2.17.0",
4451+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
4452+ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
44094453 },
44104454 "nanoid": {
44114455 "version": "3.3.4",
@@ -4413,28 +4457,28 @@
44134457 "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
44144458 },
44154459 "next": {
4416− "version": "12.2.5",
4417− "resolved": "https://registry.npmjs.org/next/-/next-12.2.5.tgz",
4418− "integrity": "sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==",
4460+ "version": "12.3.3",
4461+ "resolved": "https://registry.npmjs.org/next/-/next-12.3.3.tgz",
4462+ "integrity": "sha512-Rx2Y6Wl5R8E77NOfBupp/B9OPCklqfqD0yN2+rDivhMjd6hjVFH5n0WTDI4PWwDmZsdNcYt6NV85kJ3PLR+eNQ==",
44194463 "requires": {
4420− "@next/env": "12.2.5",
4421− "@next/swc-android-arm-eabi": "12.2.5",
4422− "@next/swc-android-arm64": "12.2.5",
4423− "@next/swc-darwin-arm64": "12.2.5",
4424− "@next/swc-darwin-x64": "12.2.5",
4425− "@next/swc-freebsd-x64": "12.2.5",
4426− "@next/swc-linux-arm-gnueabihf": "12.2.5",
4427− "@next/swc-linux-arm64-gnu": "12.2.5",
4428− "@next/swc-linux-arm64-musl": "12.2.5",
4429− "@next/swc-linux-x64-gnu": "12.2.5",
4430− "@next/swc-linux-x64-musl": "12.2.5",
4431− "@next/swc-win32-arm64-msvc": "12.2.5",
4432− "@next/swc-win32-ia32-msvc": "12.2.5",
4433− "@next/swc-win32-x64-msvc": "12.2.5",
4434− "@swc/helpers": "0.4.3",
4435− "caniuse-lite": "^1.0.30001332",
4464+ "@next/env": "12.3.3",
4465+ "@next/swc-android-arm-eabi": "12.3.3",
4466+ "@next/swc-android-arm64": "12.3.3",
4467+ "@next/swc-darwin-arm64": "12.3.3",
4468+ "@next/swc-darwin-x64": "12.3.3",
4469+ "@next/swc-freebsd-x64": "12.3.3",
4470+ "@next/swc-linux-arm-gnueabihf": "12.3.3",
4471+ "@next/swc-linux-arm64-gnu": "12.3.3",
4472+ "@next/swc-linux-arm64-musl": "12.3.3",
4473+ "@next/swc-linux-x64-gnu": "12.3.3",
4474+ "@next/swc-linux-x64-musl": "12.3.3",
4475+ "@next/swc-win32-arm64-msvc": "12.3.3",
4476+ "@next/swc-win32-ia32-msvc": "12.3.3",
4477+ "@next/swc-win32-x64-msvc": "12.3.3",
4478+ "@swc/helpers": "0.4.11",
4479+ "caniuse-lite": "^1.0.30001406",
44364480 "postcss": "8.4.14",
4437− "styled-jsx": "5.0.4",
4481+ "styled-jsx": "5.0.7",
44384482 "use-sync-external-store": "1.2.0"
44394483 },
44404484 "dependencies": {
@@ -4604,9 +4648,9 @@
46044648 "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="
46054649 },
46064650 "postcss": {
4607− "version": "8.4.16",
4608− "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
4609− "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
4651+ "version": "8.4.19",
4652+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
4653+ "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
46104654 "requires": {
46114655 "nanoid": "^3.3.4",
46124656 "picocolors": "^1.0.0",
@@ -4641,11 +4685,11 @@
46414685 }
46424686 },
46434687 "postcss-nested": {
4644− "version": "5.0.6",
4645− "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz",
4646− "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==",
4688+ "version": "6.0.0",
4689+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
4690+ "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
46474691 "requires": {
4648− "postcss-selector-parser": "^6.0.6"
4692+ "postcss-selector-parser": "^6.0.10"
46494693 }
46504694 },
46514695 "postcss-selector-parser": {
@@ -4811,9 +4855,9 @@
48114855 }
48124856 },
48134857 "regenerator-runtime": {
4814− "version": "0.13.9",
4815− "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
4816− "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
4858+ "version": "0.13.10",
4859+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
4860+ "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
48174861 },
48184862 "rename-keys": {
48194863 "version": "1.2.0",
@@ -4880,9 +4924,9 @@
48804924 }
48814925 },
48824926 "semver": {
4883− "version": "7.3.7",
4884− "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
4885− "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
4927+ "version": "7.3.8",
4928+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
4929+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
48864930 "requires": {
48874931 "lru-cache": "^6.0.0"
48884932 }
@@ -5008,9 +5052,9 @@
50085052 }
50095053 },
50105054 "styled-jsx": {
5011− "version": "5.0.4",
5012− "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.4.tgz",
5013− "integrity": "sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==",
5055+ "version": "5.0.7",
5056+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
5057+ "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
50145058 "requires": {}
50155059 },
50165060 "supports-color": {
@@ -5038,9 +5082,9 @@
50385082 }
50395083 },
50405084 "tailwindcss": {
5041− "version": "3.1.8",
5042− "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz",
5043− "integrity": "sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==",
5085+ "version": "3.2.4",
5086+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
5087+ "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==",
50445088 "requires": {
50455089 "arg": "^5.0.2",
50465090 "chokidar": "^3.5.3",
@@ -5048,18 +5092,19 @@
50485092 "detective": "^5.2.1",
50495093 "didyoumean": "^1.2.2",
50505094 "dlv": "^1.1.3",
5051− "fast-glob": "^3.2.11",
5095+ "fast-glob": "^3.2.12",
50525096 "glob-parent": "^6.0.2",
50535097 "is-glob": "^4.0.3",
50545098 "lilconfig": "^2.0.6",
5099+ "micromatch": "^4.0.5",
50555100 "normalize-path": "^3.0.0",
50565101 "object-hash": "^3.0.0",
50575102 "picocolors": "^1.0.0",
5058− "postcss": "^8.4.14",
5103+ "postcss": "^8.4.18",
50595104 "postcss-import": "^14.1.0",
50605105 "postcss-js": "^4.0.0",
50615106 "postcss-load-config": "^3.1.4",
5062− "postcss-nested": "5.0.6",
5107+ "postcss-nested": "6.0.0",
50635108 "postcss-selector-parser": "^6.0.10",
50645109 "postcss-value-parser": "^4.2.0",
50655110 "quick-lru": "^5.1.1",
@@ -5077,9 +5122,9 @@
50775122 }
50785123 },
50795124 "tar": {
5080− "version": "6.1.11",
5081− "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
5082− "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
5125+ "version": "6.1.12",
5126+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz",
5127+ "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==",
50835128 "requires": {
50845129 "chownr": "^2.0.0",
50855130 "fs-minipass": "^2.0.0",
@@ -5108,9 +5153,9 @@
51085153 "integrity": "sha512-74MoNHhwLVuzwaPDcAecFjSkOA9vwWqyOdkeB0Be8Jc/IWSS5SNZKapFllqzkTliqZptkvqX5CZnVeDvfhN8cw=="
51095154 },
51105155 "tslib": {
5111− "version": "2.4.0",
5112− "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
5113− "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
5156+ "version": "2.4.1",
5157+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
5158+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
51145159 },
51155160 "unset-value": {
51165161 "version": "0.1.2",
@@ -5122,9 +5167,9 @@
51225167 }
51235168 },
51245169 "update-browserslist-db": {
5125− "version": "1.0.5",
5126− "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
5127− "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
5170+ "version": "1.0.10",
5171+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
5172+ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
51285173 "requires": {
51295174 "escalade": "^3.1.1",
51305175 "picocolors": "^1.0.0"
package.json+4−3
@@ -7,11 +7,12 @@
77 "build": "next build",
88 "export": "npm run prebuild && next build && next export",
99 "start": "next start",
10− "prebuild": "npm run cache-posts && npm run rss && npm run community-tree && npm run getting-started-tree && npm run overview-tree",
11− "community-tree": "node lib/buildPageTree community weight",
10+ "prebuild": "npm run cache-posts && npm run rss && npm run glossary && npm run getting-started-tree && npm run overview-tree && npm run campus-tree",
1211 "getting-started-tree": "node lib/buildPageTree getting-started weight",
1312 "overview-tree": "node lib/buildPageTree overview weight",
13+ "campus-tree": "node lib/buildPageTree campus weight",
1414 "cache-posts": "node lib/cache.js",
15+ "glossary": "node lib/buildGlossary.js",
1516 "rss": "node lib/rss.js",
1617 "vercel-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/ && npm run build"
1718 },
@@ -20,7 +21,7 @@
2021 "@socialgouv/matomo-next": "^1.3.0",
2122 "@tailwindcss/aspect-ratio": "^0.4.0",
2223 "@tlon/sigil-js": "^1.4.5",
23− "@urbit/foundation-design-system": "^0.4.1",
24+ "@urbit/foundation-design-system": "0.7.3",
2425 "@urbit/markdoc": "^0.1.4",
2526 "axios": "^0.26.1",
2627 "buffer": "^6.0.3",
pages/404.js+1−1
@@ -21,7 +21,7 @@ export default function NotFound(props) {
2121 </Head>
2222 <IntraNav ourSite="https://urbit.org" search={props.search} />
2323 <SingleColumn>
24− <Header />
24+ <Header search={props.search} />
2525 <Section className="pt-48">
2626 <h1>404</h1>
2727 <p className="mt-12">It looks like nothing is here.</p>
pages/[slug].js+1−1
@@ -31,7 +31,7 @@ export async function getStaticProps({ params }) {
3131}
3232
3333export async function getStaticPaths() {
34− const posts = getPostSlugs("/");
34+ const posts = getPostSlugs("/").filter((e) => e !== 'bitcoin.md');
3535
3636 const slugs = posts.map((e) => e.slice(0, -3));
3737
pages/_app.js+6−2
@@ -1,10 +1,11 @@
11import { useState, useEffect } from "react";
22import { configure, GlobalHotKeys } from "react-hotkeys";
33import { init } from "@socialgouv/matomo-next";
4−import Search from "../components/Search";
4+import { Search } from "@urbit/foundation-design-system";
55import "@urbit/foundation-design-system/styles/globals.css";
66import "@urbit/foundation-design-system/styles/markdown.css";
77import "@urbit/foundation-design-system/styles/prism.css";
8+import Head from "next/head";
89
910const MATOMO_URL = process?.env?.NEXT_PUBLIC_MATOMO_URL || "";
1011const MATOMO_SITE_ID = process?.env?.NEXT_PUBLIC_MATOMO_SITE_ID || "";
@@ -54,17 +55,20 @@ function MyApp({ Component, pageProps }) {
5455 configure({
5556 // ignoreTags: [],
5657 ignoreTags: ["input", "select", "textarea"],
57− ignoreEventsCondition: function () {},
58+ ignoreEventsCondition: function () { },
5859 });
5960
6061 return (
6162 <>
63+
6264 <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
6365 <Search
6466 showSearch={showSearch}
6567 toggleSearch={toggleSearch}
6668 closeSearch={closeSearch}
6769 openSearch={openSearch}
70+ order={["org", "dev", "ops", "roadmap"]}
71+ ourSite="https://urbit.org"
6872 />
6973 <Component
7074 {...pageProps}
pages/api/dev-search.js+1−1
@@ -1,6 +1,6 @@
11export default async (req, res) => {
22 const results = await fetch(
3− `https://developers.urbit.org/api/search?q=${req.query.q}`
3+ `https://developers.urbit.org/api/search?q=${encodeURIComponent(req.query.q)}`
44 ).then((res) => res.json());
55 res.statusCode = 200;
66 res.setHeader("Content-Type", "application/json");
pages/api/glossary.jsdeleted−10
@@ -1,10 +0,0 @@
1−export default async (req, res) => {
2− const results = await fetch(
3− `https://developers.urbit.org/api/glossary?q=${encodeURIComponent(
4− req.query.q
5− )}`
6− ).then((res) => res.json());
7− res.statusCode = 200;
8− res.setHeader("Content-Type", "application/json");
9− res.end(JSON.stringify(results));
10−};
pages/api/roadmap-search.jsnew file+8
@@ -0,0 +1,8 @@
1+export default async (req, res) => {
2+ const results = await fetch(
3+ `https://roadmap.urbit.org/api/search?q=${req.query.q}`
4+ ).then((res) => res.json());
5+ res.statusCode = 200;
6+ res.setHeader("Content-Type", "application/json");
7+ res.end(JSON.stringify(results));
8+};
pages/api/search.js+10−1
@@ -1,4 +1,5 @@
11import { index } from "../../cache/data";
2+import { glossary } from "../../cache/glossary";
23const levenSort = require("leven-sort");
34
45export default (req, res) => {
@@ -9,6 +10,13 @@ export default (req, res) => {
910 e?.parent.toLowerCase().includes(req.query.q.toLowerCase())
1011 );
1112
13+ const entries = glossary.filter((entry) => {
14+ return (
15+ entry.name.includes(req.query.q.toLowerCase()) ||
16+ entry.symbol.includes(req.query.q)
17+ );
18+ });
19+
1220 results.push(
1321 ...index
1422 .filter((e) => !results.includes(e))
@@ -30,7 +38,8 @@ export default (req, res) => {
3038 "parent",
3139 "headings",
3240 ]);
41+ const sortedEntries = levenSort(entries, req.query.q, ["symbol"]);
3342 res.statusCode = 200;
3443 res.setHeader("Content-Type", "application/json");
35− res.end(JSON.stringify({ results: sorted }));
44+ res.end(JSON.stringify({ results: sorted, glossary: sortedEntries }));
3645};
pages/api/urbit-org-search.jsnew file+45
@@ -0,0 +1,45 @@
1+import { index } from "../../cache/data";
2+import { glossary } from "../../cache/glossary";
3+const levenSort = require("leven-sort");
4+
5+export default (req, res) => {
6+ const results = index.filter(
7+ (e) =>
8+ e.title?.toLowerCase().includes(req.query.q.toLowerCase()) ||
9+ e?.slug.includes(req.query.q.toLowerCase()) ||
10+ e?.parent.toLowerCase().includes(req.query.q.toLowerCase())
11+ );
12+
13+ const entries = glossary.filter((entry) => {
14+ return (
15+ entry.name.includes(req.query.q.toLowerCase()) ||
16+ entry.symbol.includes(req.query.q)
17+ );
18+ });
19+
20+ results.push(
21+ ...index
22+ .filter((e) => !results.includes(e))
23+ .filter((e) => {
24+ let found = false;
25+ e.headings.forEach((heading) => {
26+ if (heading.toLowerCase().includes(req.query.q.toLowerCase())) {
27+ found = true;
28+ }
29+ });
30+ return found;
31+ })
32+ .map((e) => ({ ...e, foundOnPage: true }))
33+ );
34+
35+ const sorted = levenSort(results, req.q, [
36+ "title",
37+ "slug",
38+ "parent",
39+ "headings",
40+ ]);
41+ const sortedEntries = levenSort(entries, req.query.q, ["symbol"]);
42+ res.statusCode = 200;
43+ res.setHeader("Content-Type", "application/json");
44+ res.end(JSON.stringify({ results: sorted, glossary: sortedEntries }));
45+};
pages/applications/[[...application]].js+16−5
@@ -19,8 +19,10 @@ import Gateway404 from "../../components/gateway/Gateway404";
1919import MetadataBlock from "../../components/gateway/MetadataBlock";
2020import MetadataLink from "../../components/gateway/MetadataLink";
2121import Description from "../../components/gateway/Description";
22+import { getGrantsByShortcode } from "../../lib/lib";
23+import GrantPreview from "../../components/GrantPreview";
2224
23−const ApplicationPage = ({ data, markdown, organisation, search, params }) => {
25+const ApplicationPage = ({ data, markdown, organisation, matchedGrants, search, params }) => {
2426 const { application } = params;
2527 if (!ob.isValidPatp(application[0])) {
2628 return <Gateway404 type="application" />;
@@ -83,7 +85,7 @@ const ApplicationPage = ({ data, markdown, organisation, search, params }) => {
8385 item="Application"
8486 />
8587
86− <div className="flex flex-wrap md:flex-nowrap justify-between">
88+ <div className="flex flex-wrap justify-between">
8789 <MetadataBlock
8890 title="License"
8991 content={data.license ? data.license : "Unknown"}
@@ -103,14 +105,18 @@ const ApplicationPage = ({ data, markdown, organisation, search, params }) => {
103105 content={data.shortcode ? data.shortcode : data.title}
104106 />
105107 </div>
106−
107108 <Description
108109 description={data.description}
109110 fallback="An application on Urbit."
110111 markdown={markdown}
111112 />
112−
113− <hr className="text-white" />
113+ <hr className="text-wall-200" />
114+ {matchedGrants.length > 0 && <div className="basis-full flex flex-col space-y-2">
115+ <p className="font-semibold text-wall-400">Related Grants</p>
116+ {matchedGrants.map((grant) => {
117+ return <GrantPreview grant={grant} />
118+ })}
119+ </div>}
114120
115121 <div class="bg-wall-100 py-4 px-6 border-2 border-wall-200 rounded-xl">
116122 <p class="text-sm text-wall-400">
@@ -175,6 +181,10 @@ export const getServerSideProps = async ({ params, res }) => {
175181 ? JSON.stringify(Markdown.parse({ post: { content } }))
176182 : null;
177183
184+ const matchedGrants = getGrantsByShortcode(params.application)
185+ .filter((e) => !e.extra.canceled)
186+ .sort((a, b) => new Date(b.date) - new Date(a.date))
187+
178188 if (!data.title) {
179189 data = {
180190 title: params.application?.join("/"),
@@ -187,6 +197,7 @@ export const getServerSideProps = async ({ params, res }) => {
187197 data,
188198 markdown,
189199 organisation,
200+ matchedGrants,
190201 params,
191202 },
192203 };
pages/articles/[slug].jsnew file+84
@@ -0,0 +1,84 @@
1+import BasicPage from "../../components/ecosystem/BasicPage";
2+import {
3+ Markdown,
4+ getAllPosts,
5+ getPostBySlug,
6+ getPostSlugs,
7+} from "@urbit/foundation-design-system";
8+import Link from "next/link";
9+
10+export default function Article({
11+ post,
12+ markdown,
13+ search,
14+ index,
15+ spotlights = [],
16+}) {
17+ return (
18+ <BasicPage
19+ section="Article"
20+ post={post}
21+ markdown={markdown}
22+ search={search}
23+ index={index}
24+ >
25+ {spotlights.length > 0 && (
26+ <p>
27+ Featured in{" "}
28+ {spotlights.map((e, i) => (
29+ <>
30+ {i ? ", " : ""}
31+ <Link href={`/ecosystem/spotlight/${e.slug}`}>{e.title}</Link>
32+ </>
33+ ))}
34+ </p>
35+ )}
36+ </BasicPage>
37+ );
38+}
39+
40+export async function getStaticProps({ params }) {
41+ const post = getPostBySlug(
42+ params.slug,
43+ ["title", "slug", "URL", "publication", "author", "date", "image", "content"],
44+ "articles"
45+ );
46+
47+ const spotlights = getAllPosts(
48+ ["title", "slug", "featured-1", "featured-2", "featured-3"],
49+ "ecosystem/spotlight"
50+ ).filter(
51+ (e) =>
52+ e?.["featured-1"]?.title === post.title ||
53+ e?.["featured-2"]?.title === post.title ||
54+ e?.["featured-3"]?.title === post.title
55+ );
56+
57+ let { index } = post?.extra || { index: null };
58+
59+ if (index === undefined) {
60+ index = null;
61+ }
62+
63+ const markdown = JSON.stringify(Markdown.parse({ post }));
64+ return {
65+ props: { post, markdown, spotlights, index },
66+ };
67+}
68+
69+export async function getStaticPaths() {
70+ const posts = getPostSlugs("articles");
71+
72+ const slugs = posts.map((e) => e.slice(0, -3));
73+
74+ return {
75+ paths: slugs.map((post) => {
76+ return {
77+ params: {
78+ slug: post,
79+ },
80+ };
81+ }),
82+ fallback: false,
83+ };
84+}
pages/bitcoin.jsnew file+98
@@ -0,0 +1,98 @@
1+import { Container, SingleColumn, Section, IntraNav, TableOfContents, getAllPosts, getPage, TwoUp, Markdown } from "@urbit/foundation-design-system";
2+import Head from "next/head";
3+import Link from "next/link";
4+import Meta from "../components/Meta";
5+import Header from "../components/Header";
6+import Footer from "../components/Footer";
7+import PostPreview from "../components/PostPreview"
8+import { join } from 'path';
9+import EventPreview from "../components/EventPreview";
10+import { getAllEvents } from "../lib/lib";
11+
12+import { eventKeys } from "../lib/constants";
13+
14+
15+export default function Bitcoin({ search, posts, data, markdown, events }) {
16+ const post = {
17+ title: "Bitcoin on Urbit: The Sovereign Stack",
18+ description: "Sound digital money and sound computing need each other to achieve a free and prosperous future, and Urbit and Bitcoin's common paradigm of long-termism and self-sovereignty will get us there."
19+ }
20+
21+ return (
22+ <Container>
23+ <Head>
24+ <title>Bitcoin on Urbit: The Sovereign Stack • urbit.org</title>
25+ {Meta(post)}
26+ </Head>
27+ <IntraNav ourSite="https://urbit.org" search={search} />
28+ <SingleColumn>
29+ <Header search={search} />
30+ <Section>
31+ <h1>{post.title}</h1>
32+ </Section>
33+ <Section className="flex space-x-12">
34+ <div className="min-w-0">
35+ <div>
36+ <p>Sound digital money and sound computing need each other to achieve a free and prosperous future, and Urbit and Bitcoin's common paradigm of long-termism and self-sovereignty will get us there. Check out the resources on this page to learn about current Lightning Network development on Urbit and join the Urbitcoiner community.</p>
37+ </div>
38+ <div className="mt-32">
39+ <h2 className="mb-8" id="title">{data.title}</h2>
40+ <div className="markdown">
41+ <Markdown.render content={JSON.parse(markdown)} />
42+ </div>
43+ </div>
44+ <div className="mt-32">
45+ <h2 className="mb-8" id="blog">Blog Posts</h2>
46+ <TwoUp>
47+ <PostPreview post={posts[0]} key={posts[0].slug} />
48+ {posts[1] ? <PostPreview post={posts[1]} key={posts[1].slug} /> : <div />}
49+ </TwoUp>
50+ <Link href="/blog?tag=bitcoin">
51+ <a className="bg-green-400 text-white button-lg w-fit">
52+ View All
53+ </a>
54+ </Link>
55+ </div>
56+ <div className="mt-32">
57+ <h2 className="mb-8" id="events">Events</h2>
58+ <TwoUp>
59+ <EventPreview event={events[0]} className="mb-8" />
60+ {events[1] ? <EventPreview event={events[1]} className="mb-8" /> : <div />}
61+ </TwoUp>
62+ <Link href="/events?tag=bitcoin">
63+ <a className="bg-wall-600 text-white button-lg w-fit">
64+ View All
65+ </a>
66+ </Link>
67+ </div>
68+ </div>
69+ <TableOfContents markdown={false} />
70+ </Section>
71+ </SingleColumn>
72+ <Footer />
73+ </Container>
74+ )
75+}
76+
77+export async function getStaticProps() {
78+ // Latest blog posts
79+ const posts = getAllPosts(
80+ ["title", "slug", "date", "description", "tags", "extra"],
81+ "blog",
82+ "date"
83+ ).filter((e) => e.tags?.includes("bitcoin"));
84+
85+ const events = getAllEvents(eventKeys, "events").filter((e) => e?.tags?.includes("bitcoin"));
86+
87+ const { data, content } = getPage(join(process.cwd(), 'content', 'bitcoin'));
88+
89+ const markdown = JSON.stringify(Markdown.parse({ post: { content } }));
90+ return {
91+ props: {
92+ posts,
93+ data,
94+ markdown,
95+ events
96+ }
97+ }
98+}
pages/blog.js+27−14
@@ -14,8 +14,14 @@ import Footer from "../components/Footer";
1414import Header from "../components/Header";
1515import BackgroundImage from "../components/BackgroundImage";
1616import { contact } from "../lib/constants";
17+import { useRouter } from "next/router";
1718
1819export default function Blog({ posts, search }) {
20+ const router = useRouter();
21+ const { tag } = router.query;
22+
23+ const filteredPosts = tag ? posts.filter((e) => e?.tags?.includes(tag)) : posts;
24+
1925 const post = {
2026 title: "Blog",
2127 description:
@@ -29,22 +35,29 @@ export default function Blog({ posts, search }) {
2935 </Head>
3036 <IntraNav ourSite="https://urbit.org" search={search} />
3137 <SingleColumn>
32− <Header />
38+ <Header search={search} />
3339 <Section>
34− <h1 className="pb-16">Blog</h1>
35− <div className="md:columns-2 gap-x-8">
36− <p className="pb-6 md:pb-0">
37− Stories from the broader Urbit community, the Urbit Foundation,
38− and the many people contributing to Urbit.
39− </p>
40− <p>
41− <a href={contact.newsletter}>Subscribe</a> to the Urbit Newsletter
42− for regular updates, including new blog posts and events.
43− </p>
44− </div>
40+ {tag ?
41+ <><h1 className="pb-16">{filteredPosts.length} posts tagged "{tag}"</h1>
42+ <p>
43+ For more posts, return to the <Link href="/blog">blog index</Link>.
44+ </p>
45+ </>
46+ : <><h1 className="pb-16">Blog</h1>
47+ <div className="md:columns-2 gap-x-8">
48+ <p className="pb-6 md:pb-0">
49+ Stories from the broader Urbit community, the Urbit Foundation,
50+ and the many people contributing to Urbit.
51+ </p>
52+ <p>
53+ <a href={contact.newsletter}>Subscribe</a> to the Urbit Newsletter
54+ for regular updates, including new blog posts and events.
55+ </p>
56+ </div>
57+ </>}
4558 </Section>
4659 <Section>
47− {posts.map((post) => {
60+ {filteredPosts.map((post) => {
4861 const date = generateDisplayDate(post.date);
4962 return (
5063 <div key={post.slug} className="mb-20 cursor-pointer">
@@ -107,7 +120,7 @@ export default function Blog({ posts, search }) {
107120
108121export async function getStaticProps() {
109122 const posts = getAllPosts(
110− ["title", "slug", "date", "description", "extra"],
123+ ["title", "slug", "date", "description", "tags", "extra"],
111124 "blog",
112125 "date"
113126 );
pages/blog/[slug].js+1−1
@@ -41,7 +41,7 @@ export default function Post({
4141 </Head>
4242 <IntraNav ourSite="https://urbit.org" search={search} />
4343 <SingleColumn>
44− <Header />
44+ <Header search={search} />
4545 <Section narrow className="pb-10">
4646 <h1>{post.title}</h1>
4747 <h3 className=" mt-6">{post.description}</h3>
pages/campus/[[...slug]].jsnew file+312
@@ -0,0 +1,312 @@
1+import Head from "next/head";
2+import Link from "next/link";
3+import { useRouter } from "next/router";
4+import classnames from "classnames";
5+import React from "react";
6+import { DateTime } from "luxon";
7+import {
8+ Container,
9+ Section,
10+ SingleColumn,
11+ TwoUp,
12+ IntraNav,
13+ getAllPosts,
14+ generateRealtimeDate,
15+ getPage,
16+ Markdown,
17+ getPreviousPost,
18+ getNextPost,
19+} from "@urbit/foundation-design-system";
20+import { getAllEvents } from "../../lib/lib";
21+import { join } from 'path';
22+import Header from "../../components/Header";
23+import Footer from "../../components/Footer";
24+import Contact from "../../components/Contact";
25+import PostPreview from "../../components/PostPreview";
26+import EventPreview from "../../components/EventPreview";
27+import Sidebar from "../../components/Sidebar";
28+import { eventKeys } from "../../lib/constants";
29+import IndexCard from "../../components/ecosystem/IndexCard";
30+import HighlightCard from "../../components/HighlightCard";
31+import fs from "fs";
32+import path from "path";
33+import Meta from "../../components/Meta";
34+import campusTree from "../../cache/campus.json";
35+import { matchEcosystemPost } from "../../lib/lib";
36+
37+export default function Home({
38+ posts,
39+ highlights,
40+ ecosystem,
41+ events,
42+ grantNumbers,
43+ search,
44+ data,
45+ markdown,
46+}) {
47+ const post = {
48+ title: "Urbit",
49+ description: "A clean-slate OS and network for the 21st century.",
50+ image: "https://storage.googleapis.com/media.urbit.org/site/opengraph/urbit.png"
51+ };
52+ return (
53+ <Container>
54+ <Head>
55+ <title>Urbit</title>
56+ {Meta(post, false, true)}
57+ </Head>
58+ <IntraNav ourSite="https://urbit.org" search={search} />
59+
60+ <SingleColumn>
61+ <Header search={search} />
62+
63+ {/* Hero statement */}
64+ <Section className="pb-6">
65+ <div className="flex flex-col space-y-4">
66+ <h1 className="max-w-prose">
67+ Campus Outreach Program
68+ </h1>
69+ <h3 className="max-w-prose">
70+ Leave your mark on the future. Build on Urbit.
71+ </h3>
72+ </div>
73+ </Section>
74+
75+
76+
77+ {/* Brief explanatory paragraph */}
78+ <Section className="sm:flex sm:space-x-8 space-y-8 sm:space-y-0">
79+
80+ <div className="space-y-8">
81+ <div className="space-y-4">
82+ <p className="type-ui max-w-prose">
83+ The Urbit Foundation’s Campus Outreach Program aims to find ambitious students interested in reimagining the possibilities of decentralized systems and networked computing.
84+ </p>
85+
86+ <p className="type-ui max-w-prose">
87+ Do you fit that description and want us to come to your university?{" "}
88+ <Link href="/campus#contact" passHref>
89+ <a>Get in touch.</a>
90+ </Link>{" "}
91+ </p>
92+ </div>
93+
94+
95+ <Link href="https://airtable.com/shrmfUVpMskWw145u" passHref>
96+ <a className="button-lg bg-green-400 text-white type-ui max-w-fit">
97+ Get on Urbit
98+ </a>
99+ </Link>
100+
101+
102+ </div>
103+ </Section>
104+
105+ {/*
106+ how to make an in-page link (href to hashtag element id)
107+ <a href="#events"> cheebo </a>
108+ */}
109+
110+
111+
112+ {
113+ //funnel, repurposed from /overview page:
114+ }
115+ <div id="learn"></div>
116+
117+ <Section>
118+
119+ <h2 className="pb-16">Why use Urbit?</h2>
120+
121+ <div className="flex justify-between sidebar md:space-x-8">
122+ <Sidebar search={search}>
123+ {childPages("/campus", posts.pages)}
124+ </Sidebar>
125+ <div className={'markdown max-w-prose ' + data.slug }>
126+
127+ <h2>{ data.title }</h2>
128+ <Markdown.render content={JSON.parse(markdown)} />
129+ </div>
130+ </div>
131+ </Section>
132+
133+
134+
135+ {
136+ //Events
137+ }
138+
139+ <Section className="pb-1">
140+
141+ <br></br>
142+ <div className="mt-6">
143+ <h2 className="mb-8" id="events">Events</h2>
144+ {events.length > 0 ? (
145+ <TwoUp>
146+ <EventPreview event={events[0]} className="mb-8" />
147+ {events[1] ? <EventPreview event={events[1]} className="mb-8" /> : <div />}
148+ </TwoUp>
149+ ) : (
150+ <p className="pb-8">No events yet — check back later.</p>
151+ )}
152+ <Link href="/events?tag=campus">
153+ <a className="bg-wall-600 text-white button-lg w-fit">
154+ View All
155+ </a>
156+ </Link>
157+ </div>
158+ </Section>
159+
160+ <div id="contact"></div>
161+
162+ <Section className="pb-12">
163+
164+ <div className="bg-wall-100 w-full p-4 md:p-8 rounded-3xl flex flex-wrap items-center">
165+
166+ <div className="sm:pl-2 align-middle">
167+ <h2 className=" text-2xl pb-2" >Get in touch</h2 >
168+ <p className="max-w-prose type-ui pb-4">
169+ Not sure how to get started after attending an event? Want to schedule one at your university?
170+ Don't be a stranger. Reach out at the email below, or{" "}
171+ <Link href="https://urbit.org/groups/~tidren-nosryg/campus-outreach" passHref>
172+ <a>find us on Urbit.</a>
173+ </Link>{" "}
174+ </p>
175+ <Link href="mailto:campus@urbit.org">
176+ <a className="button-sm border-2 border-wall-600 text-wall-600 type-sm max-w-fit">
177+ campus@urbit.org
178+ </a>
179+ </Link>
180+ </div>
181+ </div>
182+ </Section>
183+
184+
185+
186+
187+ </SingleColumn>
188+
189+
190+
191+ <Footer />
192+ </Container>
193+ );
194+}
195+
196+const childPages = (thisLink, children, level = 0) => {
197+ const router = useRouter();
198+
199+ const isThisPage = router.asPath === thisLink || router.asPath === `${thisLink}#learn`;
200+
201+ const pageItemClasses = classnames({
202+ "text-base type-ui": level === 0,
203+ "text-wall-400": !isThisPage,
204+ "text-black": isThisPage,
205+ });
206+ return (
207+ <ul className="">
208+ <li className="pb-2">
209+ <Link href="/campus#learn">
210+ <a className={`${pageItemClasses} cursor-pointer`}>Software Developers</a>
211+ </Link>
212+ </li>
213+ {children?.map((child) => (
214+ <li className="pb-2">
215+ {pageTree(join(thisLink, child.slug), child, level)}
216+ </li>
217+ ))}
218+ </ul>
219+ );
220+};
221+
222+const pageTree = (thisLink, tree, level = 0) => {
223+ const router = useRouter();
224+
225+
226+ const isThisPage = router.asPath.includes(thisLink);
227+
228+ const pageItemClasses = classnames({
229+ "text-base type-ui": level === 0,
230+ "text-wall-400": !isThisPage,
231+ "text-black": isThisPage,
232+ });
233+
234+ return (
235+ <>
236+ <Link href={thisLink + "#learn"}>
237+ <a className={`${pageItemClasses} cursor-pointer`}>{tree.title}</a>
238+ </Link>
239+ </>
240+ );
241+};
242+
243+export async function getStaticPaths() {
244+ const posts = campusTree;
245+
246+ const slugs = [];
247+
248+ const allHrefs = (thisLink, tree) => {
249+ slugs.push(thisLink, ...tree.pages.map((e) => join(thisLink, e.slug)));
250+ allHrefsChildren(thisLink, tree.children);
251+ };
252+
253+ const allHrefsChildren = (thisLink, children) => {
254+ Object.entries(children).map(([childSlug, child]) => {
255+ allHrefs(join(thisLink, childSlug), child);
256+ });
257+ };
258+
259+ allHrefs("/campus", posts);
260+
261+ return {
262+ paths: slugs,
263+ fallback: false,
264+ };
265+}
266+
267+export async function getStaticProps({ params }) {
268+ const posts = campusTree;
269+
270+ const { data, content } = getPage(
271+ join(process.cwd(), "content/campus", params.slug?.join("/") || "/")
272+ );
273+ const markdown = JSON.stringify(Markdown.parse({ post: { content } }));
274+
275+ const previousPost =
276+ getPreviousPost(
277+ params.slug?.slice(-1).join("") || "campus",
278+ ["title", "slug", "weight"],
279+ join("campus", params.slug?.slice(0, -1).join("/") || "/"),
280+ "weight"
281+ ) || null;
282+
283+ const nextPost =
284+ getNextPost(
285+ params.slug?.slice(-1).join("") || "campus",
286+ ["title", "slug", "weight"],
287+ join("campus", params.slug?.slice(0, -1).join("/") || "/"),
288+ "weight"
289+ ) || null;
290+
291+ const allEvents = getAllEvents(eventKeys, "events");
292+ const events = allEvents.filter((e) => e?.tags?.includes("campus")) || [];
293+
294+ return { props: { posts, data, markdown, params, previousPost, nextPost, events } };
295+}
296+
297+
298+
299+/* export async function getStaticProps() {
300+
301+
302+ const events = getAllEvents(eventKeys, "events").filter((e) => e?.tags?.includes("campus"));
303+
304+ // const { data, content } = getPage(join(process.cwd(), 'content', 'bitcoin'));
305+
306+ return {
307+ props: {
308+ events
309+ }
310+ }
311+}
312+ */
pages/communities/[slug].jsnew file+87
@@ -0,0 +1,87 @@
1+import BasicPage from "../../components/ecosystem/BasicPage";
2+import {
3+ Markdown,
4+ getAllPosts,
5+ getPostBySlug,
6+ getPostSlugs,
7+} from "@urbit/foundation-design-system";
8+import Link from "next/link";
9+
10+export default function Community({
11+ post,
12+ markdown,
13+ search,
14+ index,
15+ spotlights = [],
16+}) {
17+ return (
18+ <BasicPage
19+ section="Community"
20+ post={post}
21+ markdown={markdown}
22+ search={search}
23+ index={index}
24+ >
25+ {spotlights.length > 0 && (
26+ <p>
27+ Featured in{" "}
28+ {spotlights.map((e, i) => (
29+ <>
30+ {i ? ", " : ""}
31+ <Link href={`/ecosystem/spotlight/${e.slug}`}>{e.title}</Link>
32+ </>
33+ ))}
34+ </p>
35+ )}
36+
37+ <p>––</p>
38+ <p>Interested in starting an Urbit meetup? <a href="/grants/community-meetups">Learn more here</a>.</p>
39+ </BasicPage>
40+ );
41+}
42+
43+export async function getStaticProps({ params }) {
44+ const post = getPostBySlug(
45+ params.slug,
46+ ["title", "description", "slug", "image", "content"],
47+ "communities"
48+ );
49+
50+ const spotlights = getAllPosts(
51+ ["title", "slug", "featured-1", "featured-2", "featured-3"],
52+ "ecosystem/spotlight"
53+ ).filter(
54+ (e) =>
55+ e?.["featured-1"]?.title === post.title ||
56+ e?.["featured-2"]?.title === post.title ||
57+ e?.["featured-3"]?.title === post.title
58+ );
59+
60+ let { index } = post?.extra || { index: null };
61+
62+ if (index === undefined) {
63+ index = null;
64+ }
65+
66+ const markdown = JSON.stringify(Markdown.parse({ post }));
67+ return {
68+ props: { post, markdown, spotlights, index },
69+ };
70+}
71+
72+export async function getStaticPaths() {
73+ const posts = getPostSlugs("communities");
74+
75+ const slugs = posts.map((e) => e.slice(0, -3));
76+
77+ return {
78+ paths: slugs.map((post) => {
79+ return {
80+ params: {
81+ slug: post,
82+ },
83+ };
84+ }),
85+ fallback: false,
86+ };
87+}
pages/community/[[...slug]].jsdeleted−121
@@ -1,121 +0,0 @@
1−import Head from "next/head";
2−import Link from "next/link";
3−import { useRouter } from "next/router";
4−import classnames from "classnames";
5−import { join } from "path";
6−import Meta from "../../components/Meta";
7−import { Markdown, getPage } from "@urbit/foundation-design-system";
8−import ContentArea from "../../components/ContentArea";
9−import Sidebar from "../../components/DocsSidebar";
10−import communityTree from "../../cache/community.json";
11−
12−const breadcrumbs = (posts, paths) => {
13− const results = [
14− <Link href="/">Urbit</Link>,
15− <span className="px-1">/</span>,
16− <Link href="/community">Community</Link>,
17− ];
18− let thisLink = "/community";
19− for (const path of paths) {
20− posts = posts.children[path];
21− thisLink = join(thisLink, path);
22− results.push(
23− <span className="px-1">/</span>,
24− <Link href={thisLink}>{posts.title}</Link>
25− );
26− }
27− return results;
28−};
29−
30−const childPages = (thisLink, children, level = 0) => (
31− <ul className="pl-1">
32− {children?.map((child) => (
33− <li>{pageTree(join(thisLink, child.slug), child, level)}</li>
34− ))}
35− </ul>
36−);
37−
38−const pageTree = (thisLink, tree, level = 0) => {
39− const router = useRouter();
40−
41− const isThisPage = router.asPath === thisLink;
42−
43− const pageItemClasses = classnames({
44− "pl-4 text-wall-600 text-base hover:text-green-400": level === 0,
45− "pl-8 text-wall-600 text-base hover:text-green-400": level === 1,
46− "pl-12 text-wall-600 text-base hover:text-green-400": level === 2,
47− "dot relative": isThisPage,
48− "text-green-400": isThisPage,
49− });
50−
51− return (
52− <>
53− <Link href={thisLink}>
54− <a className={`${pageItemClasses} cursor-pointer`}>{tree.title}</a>
55− </Link>
56− </>
57− );
58−};
59−
60−export default function UsingLayout({ posts, data, markdown, params, search }) {
61− return (
62− <>
63− <Head>
64− <title>{data.title} • Community</title>
65− {Meta(data)}
66− </Head>
67− <div className="flex h-screen min-h-screen w-screen sidebar">
68− <Sidebar search={search}>
69− {childPages("/community", posts.pages)}
70− </Sidebar>
71− <ContentArea
72− breadcrumbs={breadcrumbs(posts, params.slug?.slice(0, -1) || "")}
73− title={data.title}
74− search={search}
75− section={"Community"}
76− params={params}
77− >
78− <div className="markdown">
79− <Markdown.render content={JSON.parse(markdown)} />
80− </div>
81− </ContentArea>
82− </div>
83− </>
84− );
85−}
86−
87−export async function getStaticProps({ params }) {
88− const posts = communityTree;
89−
90− const { data, content } = getPage(
91− join(process.cwd(), "content/community", params.slug?.join("/") || "/")
92− );
93−
94− const markdown = JSON.stringify(Markdown.parse({ post: { content } }));
95−
96− return { props: { posts, data, markdown, params } };
97−}
98−
99−export async function getStaticPaths() {
100− const posts = communityTree;
101−
102− const slugs = [];
103−
104− const allHrefs = (thisLink, tree) => {
105− slugs.push(thisLink, ...tree.pages.map((e) => join(thisLink, e.slug)));
106− allHrefsChildren(thisLink, tree.children);
107− };
108−
109− const allHrefsChildren = (thisLink, children) => {
110− Object.entries(children).map(([childSlug, child]) => {
111− allHrefs(join(thisLink, childSlug), child);
112− });
113− };
114−
115− allHrefs("/community", posts);
116−
117− return {
118− paths: slugs,
119− fallback: false,
120− };
121−}
pages/decentralized-discord.js+4−9
@@ -54,7 +54,7 @@ export default function DiscordLanding({ search, featuredGroups }) {
5454 </Head>
5555 <IntraNav ourSite="https://urbit.org" search={search} />
5656 <SingleColumn>
57− <Header />
57+ <Header search={search} />
5858 <Section className="pb-24">
5959 <div className="flex flex-col items-center justify-center space-y-4">
6060 <h3 className="uppercase tracking-widest">Urbit is</h3>
@@ -184,11 +184,11 @@ export default function DiscordLanding({ search, featuredGroups }) {
184184 title="Join a Group"
185185 description={
186186 <p>
187− The easiest way to jump on the network is to download our
188− desktop application and boot up a comet - a Temporary ID.
187+ The easiest way to jump on the network is to download Urbit
188+ and boot up a comet - a Temporary ID.
189189 </p>
190190 }
191− href="https://urbit.org/getting-started/desktop"
191+ href="https://urbit.org/getting-started"
192192 />
193193 </TwoUp>
194194 <div className="flex items-center space-x-4 w-full">
@@ -281,11 +281,6 @@ export async function getStaticProps() {
281281 ["title", "slug", "shortcode", "description", "tile"],
282282 "groups/~tirrel"
283283 ),
284− getPostBySlug(
285− "group-discovery",
286− ["title", "slug", "shortcode", "description", "tile"],
287− "groups/~rondev"
288− ),
289284 getPostBySlug(
290285 "other-life",
291286 ["title", "slug", "shortcode", "description", "tile"],
pages/ecosystem/index.js+215−237
@@ -6,7 +6,6 @@ import {
66 SingleColumn,
77 Section,
88 IntraNav,
9− Markdown,
109 getAllPosts,
1110 generateDisplayDate,
1211 formatDate,
@@ -14,12 +13,15 @@ import {
1413import Header from "../../components/Header";
1514import Footer from "../../components/Footer";
1615import Sidebar from "../../components/Sidebar";
16+import EcosystemSidebar from "../../components/ecosystem/EcosystemSidebar";
17+import SpotlightArchive from "../../components/ecosystem/SpotlightArchive";
1718import Post from "../../components/ecosystem/Post";
1819import classnames from "classnames";
1920import Link from "next/link";
2021import fs from "fs";
2122import path from "path";
2223import Contact from "../../components/Contact";
24+import { matchEcosystemPost } from "../../lib/lib";
2325
2426export default function Ecosystem({
2527 search,
@@ -30,21 +32,34 @@ export default function Ecosystem({
3032 marketplaces,
3133 organizations,
3234 podcasts,
35+ articles,
36+ communities
3337}) {
3438 const router = useRouter();
3539
3640 const { type } = router.query;
3741
42+ // Route ?type=archive to below component;
43+ // otherwise, show directory of ecosystem type
44+ // If no param, we show the spotlight for the month
3845 if (type === "archive") {
3946 return <SpotlightArchive posts={posts} search={search} />;
4047 }
4148
49+ const spotlight = type === undefined;
50+
4251 let title;
4352 if (type) {
4453 switch (type) {
4554 case "applications":
4655 title = "Applications • Ecosystem";
4756 break;
57+ case "communities":
58+ title = "Communities • Ecosystem";
59+ break;
60+ case "applications":
61+ title = "Groups • Ecosystem";
62+ break;
4863 case "marketplaces":
4964 title = "Marketplaces • Ecosystem";
5065 break;
@@ -54,6 +69,9 @@ export default function Ecosystem({
5469 case "organizations":
5570 title = "Organizations • Ecosystem";
5671 break;
72+ case "articles":
73+ title = "Articles • Ecosystem";
74+ break;
5775 default:
5876 title = "Ecosystem Spotlight";
5977 }
@@ -73,7 +91,7 @@ export default function Ecosystem({
7391 </Head>
7492 <IntraNav ourSite="https://urbit.org" search={search} />
7593 <SingleColumn>
76− <Header />
94+ <Header search={search} />
7795 <Section>
7896 <h1>Ecosystem</h1>
7997 </Section>
@@ -84,21 +102,19 @@ export default function Ecosystem({
84102 </Sidebar>
85103 <div
86104 className={classnames("w-full", {
87− "max-w-prose": type === undefined,
105+ "max-w-prose": spotlight,
88106 })}
89107 >
90− {type === undefined && (
91− <h3>{`Ecosystem Spotlight - ${post.title}`}</h3>
92− )}
93− {type === undefined && (
108+ {/* Default layout */}
109+ {spotlight && (
94110 <>
111+ <h3>{`Ecosystem Spotlight - ${post.title}`}</h3>
95112 <Post post={post} />
96113 <Link href="/ecosystem/?type=archive" passHref>
97114 <a className="button-lg bg-wall-600 text-white w-fit">
98115 Spotlight Archive
99116 </a>
100117 </Link>
101−
102118 <div className="pt-36">
103119 <h3 className="pb-2">Urbit Monthly</h3>
104120 <p className="pb-8">
@@ -109,106 +125,38 @@ export default function Ecosystem({
109125 </div>
110126 </>
111127 )}
112−
128+ {/* Ecosystem type layouts */}
113129 <div
114130 className={classnames("grid gap-12 w-full", {
115− "grid-cols-2 md:grid-cols-3": type !== "podcasts",
116− "grid-cols-1": type === "podcasts",
131+ "grid-cols-1": type === "podcasts" || type === "articles",
117132 "grid-cols-1 md:grid-cols-1 lg:grid-cols-1 xl:grid-cols-2":
118− type === "applications" || type === "groups",
119− hidden: type === undefined,
133+ type === "applications" || type === "groups" || type === "communities" || type === "organizations" || type === "marketplaces",
134+ hidden: spotlight,
120135 })}
121136 >
122137 {type === "organizations" &&
123− organizations.map((org) => (
124− <Link href={`/organizations/${org.slug}`}>
125− <div className="flex flex-col space-y-4 items-center cursor-pointer hover:opacity-90">
126− <img className="w-36 rounded-xl" src={org.image} />
127− <p className="text-center font-bold">{org.title}</p>
128− </div>
129− </Link>
130− ))}
138+ <Organizations dir={organizations} />
139+ }
131140
132141 {type === "applications" &&
133− applications.map((app) => (
134− <Link href={`/applications/${app.ship}/${app.slug}`}>
135− <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
136− <div
137− className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
138− style={{
139− backgroundColor: app?.bgColor || "rgba(0,0,0,0)",
140− }}
141− >
142− {app?.image && (
143− <img
144− className="items-center h-36 w-36"
145− src={app.image}
146− />
147− )}
148− </div>
149− <div className="">
150− <p className="text-left font-bold">{app.title}</p>
151− <p className="text-left text-wall-400 font-light">
152− {app.description}
153− </p>
154− </div>
155− </div>
156− </Link>
157− ))}
142+ <Applications dir={applications} />
143+ }
144+ {type === "communities" &&
145+ <Communities dir={communities} />
146+ }
158147 {type === "groups" &&
159− groups.map((group) => (
160− <Link href={`/groups/${group.ship}/${group.slug}`}>
161− <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
162− <div
163− className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
164− style={{
165− backgroundColor: group?.tile?.startsWith("#")
166− ? group?.tile
167− : "rgba(0,0,0,0)",
168− }}
169− >
170− {!group?.tile?.startsWith("#") && (
171− <img
172− className="items-center h-36 w-36"
173− src={group.tile}
174− />
175− )}
176− </div>
177− <div className="">
178− <p className="text-left font-bold">{group.title}</p>
179− <p className="text-left text-wall-400 font-light">
180− {group.description}
181− </p>
182− </div>
183− </div>
184− </Link>
185− ))}
148+ <Groups dir={groups} />
149+ }
186150 {type === "marketplaces" &&
187− marketplaces.map((market) => (
188− <Link href={`/marketplaces/${market.slug}`}>
189− <div className="flex flex-col space-y-4 justify-center items-center cursor-pointer hover:opacity-90">
190− <img className="w-36 rounded-xl" src={market.image} />
191− <p className="text-center font-bold">{market.title}</p>
192− </div>
193− </Link>
194− ))}
151+ <Marketplaces dir={marketplaces} />
152+ }
195153 {type === "podcasts" &&
196− podcasts.map((pod) => (
197− <Link href={`/podcasts/${pod.slug}`}>
198− <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
199− <img className="w-28" src={pod.image} />
200− <div className="flex flex-col space-y-2 min-w-0">
201− <p className="font-bold">{pod.podcast}</p>
202− <p className="min-w-0 min-h-0 leading-5 ">
203− {pod.title}
204− </p>
205− <p className="text-wall-400">
206− {formatDate(generateDisplayDate(pod.date))}
207− </p>
208− </div>
209− </div>
210− </Link>
211− ))}
154+ <Podcasts dir={podcasts} />
155+ }
156+
157+ {type === "articles" &&
158+ <Articles dir={articles} />
159+ }
212160 </div>
213161 </div>
214162 </div>
@@ -219,149 +167,196 @@ export default function Ecosystem({
219167 );
220168}
221169
222−function ActiveLink({ children, href, className, currentPath }) {
223− // special casing this behaviour which overloads one nav
224− const archive = Boolean(
225− currentPath === "/ecosystem?type=archive" && href === "/ecosystem"
226− );
227− const activeClassName = classnames({
228− "text-wall-800": currentPath === href || archive,
229− "text-wall-400": currentPath !== href && !archive,
230− });
231170
232− return (
233− <Link href={href} passHref>
234− <a className={`${className} ${activeClassName}`}>{children}</a>
171+const Applications = ({ dir }) => {
172+ return dir.map((app) => (
173+ <Link href={`/applications/${app.ship}/${app.slug}`}>
174+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
175+ <div
176+ className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
177+ style={{
178+ backgroundColor: app?.bgColor || "rgba(0,0,0,0)",
179+ }}
180+ >
181+ {app?.image && (
182+ <img
183+ className="items-center h-36 w-36"
184+ src={app.image}
185+ />
186+ )}
187+ </div>
188+ <div className="">
189+ <p className="text-left font-bold">{app.title}</p>
190+ <p className="text-left text-wall-400 font-light">
191+ {app.description}
192+ </p>
193+ </div>
194+ </div>
235195 </Link>
236− );
196+ ))
237197}
238198
239−function EcosystemSidebar() {
240− const router = useRouter();
241− let currentPath = router.asPath;
242− return (
243− <div className="flex flex-col space-y-4 pr-24">
244− <ActiveLink
245− currentPath={currentPath}
246− className="type-ui"
247− href="/ecosystem"
248− >
249− Spotlight
250− </ActiveLink>
251− <ActiveLink
252− currentPath={currentPath}
253− className="type-ui"
254− href="/ecosystem?type=organizations"
255− >
256− Organizations
257− </ActiveLink>
258− <ActiveLink
259− currentPath={currentPath}
260− className="type-ui"
261− href="/ecosystem?type=applications"
262− >
263− Applications
264− </ActiveLink>
265− <ActiveLink
266− currentPath={currentPath}
267− className="type-ui"
268− href="/ecosystem?type=groups"
269− >
270− Groups
271− </ActiveLink>
272− <ActiveLink
273− currentPath={currentPath}
274− className="type-ui"
275− href="/ecosystem?type=marketplaces"
276− >
277− Marketplaces
278− </ActiveLink>
279− <ActiveLink
280− currentPath={currentPath}
281− className="mr-5 type-ui"
282− href="/ecosystem?type=podcasts"
283− >
284− Podcasts
285− </ActiveLink>
286− </div>
287− );
199+const Groups = ({ dir }) => {
200+ return dir.map((group) => (
201+ <Link href={`/groups/${group.ship}/${group.slug}`}>
202+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
203+ <div
204+ className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
205+ style={{
206+ backgroundColor: group?.tile?.startsWith("#")
207+ ? group?.tile
208+ : "rgba(0,0,0,0)",
209+ }}
210+ >
211+ {!group?.tile?.startsWith("#") && (
212+ <img
213+ className="items-center h-36 w-36"
214+ src={group.tile}
215+ />
216+ )}
217+ </div>
218+ <div className="">
219+ <p className="text-left font-bold">{group.title}</p>
220+ <p className="text-left text-wall-400 font-light">
221+ {group.description}
222+ </p>
223+ </div>
224+ </div>
225+ </Link>
226+ ))
288227}
289228
290−function SpotlightArchive({ posts, search }) {
291− const post = {
292− title: "Spotlight Archive",
293− description: "The archive of ecosystem spotlights.",
294− };
295− return (
296− <Container>
297− <Head>
298− <title>Archive • Spotlight • Urbit</title>
299− {Meta(post)}
300− </Head>
301− <IntraNav ourSite="https://urbit.org" search={search} />
302− <SingleColumn>
303− <Header />
304− <Section>
305− <div className="measure">
306− <h1>Ecosystem</h1>
307− </div>
308− </Section>
309− <Section className="flex">
310− <Sidebar>
311− <EcosystemSidebar />
312− </Sidebar>
313− <div>
314− <h3 className="mb-12">Spotlight Archive</h3>
315− {posts.map((post) => {
316− return (
317− <div key={post.slug} className="mb-24 cursor-pointer">
318− <Link href={`/ecosystem/spotlight/${post.slug}`}>
319− <div>
320− <h3 className="text-green-400">{post.title}</h3>
321− <div className="type-ui mt-2">
322− {["featured-1", "featured-2", "featured-3"].map(
323− (feat, i) => {
324− if (post?.[feat]) {
325− return (
326− <>
327− {i ? ", " : ""}
328− <span>{post[feat].title}</span>
329− </>
330− );
331− }
332− }
333− )}
334− </div>
335− </div>
336− </Link>
337− </div>
338− );
339− })}
340− </div>
341− </Section>
342− </SingleColumn>
343− <Footer />
344− </Container>
345− );
229+
230+const Podcasts = ({ dir }) => {
231+ return dir.map((pod) => (
232+ <Link href={`/podcasts/${pod.slug}`}>
233+ <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
234+ <img className="w-28" src={pod.image} />
235+ <div className="flex flex-col space-y-2 min-w-0">
236+ <p className="font-bold">{pod.podcast}</p>
237+ <p className="min-w-0 min-h-0 leading-5 ">
238+ {pod.title}
239+ </p>
240+ <p className="text-wall-400">
241+ {formatDate(generateDisplayDate(pod.date))}
242+ </p>
243+ </div>
244+ </div>
245+ </Link>
246+ ))
247+}
248+
249+const Articles = ({ dir }) => {
250+ return dir.map((article) => (
251+ <Link href={`/articles/${article.slug}`}>
252+ <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
253+ <img className="w-28" src={article.image} />
254+ <div className="flex flex-col space-y-2 min-w-0">
255+ <p className="font-bold">{article.publication}</p>
256+ <p className="min-w-0 min-h-0 leading-5 ">
257+ {article.title}
258+ </p>
259+ <p className="text-wall-400">
260+ {formatDate(generateDisplayDate(article.date))}
261+ </p>
262+ </div>
263+ </div>
264+ </Link>
265+ ))
266+}
267+
268+const Communities = ({ dir }) => {
269+ return dir.map((community) => (
270+ <Link href={`/communities/${community.slug}`}>
271+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
272+ <div className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden">
273+ <img
274+ className="items-center h-36 w-36"
275+ src={community.image}
276+ />
277+ </div>
278+ <div className="">
279+ <p className="text-left font-bold">{community.title}</p>
280+ <p className="text-left text-wall-400 font-light">
281+ {community.description}
282+ </p>
283+ </div>
284+ </div>
285+ </Link>
286+ ))
287+}
288+
289+
290+const Marketplaces = ({ dir }) => {
291+ return dir.map((market) => (
292+ <Link href={`/marketplaces/${market.slug}`}>
293+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
294+ <div className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden">
295+ <img
296+ className="items-center h-36 w-36"
297+ src={market.image}
298+ />
299+ </div>
300+ <div className="">
301+ <p className="text-left font-bold">{market.title}</p>
302+ <p className="text-left text-wall-400 font-light">
303+ {market.description}
304+ </p>
305+ </div>
306+ </div>
307+ </Link>
308+ ))
346309}
347310
348−export async function getStaticProps({}) {
311+const Organizations = ({ dir }) => {
312+ return dir.map((org) => (
313+ <Link href={`/organizations/${org.slug}`}>
314+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
315+ <div className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden">
316+ <img
317+ className="items-center h-36 w-36"
318+ src={org.image}
319+ />
320+ </div>
321+ <div className="">
322+ <p className="text-left font-bold">{org.title}</p>
323+ <p className="text-left text-wall-400 font-light">
324+ {org.description}
325+ </p>
326+ </div>
327+ </div>
328+ </Link>
329+ ))
330+}
331+
332+
333+
334+
335+
336+
337+export async function getStaticProps() {
349338 const posts = getAllPosts(
350339 ["title", "date", "slug", "featured-1", "featured-2", "featured-3"],
351340 "ecosystem/spotlight",
352341 "date"
353342 );
354− let post = getAllPosts(
343+ const post = matchEcosystemPost(getAllPosts(
355344 ["title", "date", "featured-1", "featured-2", "featured-3"],
356345 "ecosystem/spotlight",
357346 "date"
358− )[0];
347+ )[0]);
359348 const marketplaces = getAllPosts(["title", "image", "slug"], "marketplaces");
349+ const communities = getAllPosts(["title", "image", "slug", "description"], "communities");
360350 const podcasts = getAllPosts(
361351 ["title", "image", "date", "podcast", "slug"],
362352 "podcasts",
363353 "date"
364354 );
355+ const articles = getAllPosts(
356+ ["title", "image", "date", "publication", "author", "slug"],
357+ "articles",
358+ "date"
359+ );
365360 const organizations = getAllPosts(
366361 ["title", "image", "slug"],
367362 "organizations"
@@ -405,25 +400,6 @@ export async function getStaticProps({}) {
405400 return nameA < nameB ? -1 : 1;
406401 });
407402
408− ["featured-1", "featured-2", "featured-3"].forEach((feat) => {
409− if (post?.[feat]) {
410− const matchedPost = [
411− ...applications.map((e) => ({ ...e, type: "Application" })),
412− ...organizations.map((e) => ({ ...e, type: "Organization" })),
413− ...podcasts.map((e) => ({ ...e, type: "Podcast" })),
414− ...marketplaces.map((e) => ({ ...e, type: "Marketplace" })),
415− ].filter((e) => e.title === post[feat].title)?.[0];
416− post[feat].image = post[feat]?.image || matchedPost?.image || null;
417− post[feat].type = matchedPost?.type || "Podcast";
418− post[feat].matchedPost = matchedPost || null;
419− post[feat].content = JSON.stringify(
420− Markdown.parse({
421− post: { content: post[feat].content },
422− })
423− );
424− }
425− });
426−
427403 return {
428404 props: {
429405 posts,
@@ -433,6 +409,8 @@ export async function getStaticProps({}) {
433409 marketplaces,
434410 podcasts,
435411 organizations,
412+ articles,
413+ communities
436414 },
437415 };
438416}
pages/ecosystem/spotlight/[slug].js+3−53
@@ -6,7 +6,6 @@ import {
66 Container,
77 SingleColumn,
88 Section,
9− Markdown,
109 IntraNav,
1110 getAllPosts,
1211 getPostBySlug,
@@ -14,8 +13,7 @@ import {
1413import Header from "../../../components/Header";
1514import Footer from "../../../components/Footer";
1615import Post from "../../../components/ecosystem/Post";
17−import fs from "fs";
18−import path from "path";
16+import { matchEcosystemPost } from "../../../lib/lib";
1917
2018export default function BasicPage({ post, markdown, search, index = false }) {
2119 const router = useRouter();
@@ -44,59 +42,11 @@ export default function BasicPage({ post, markdown, search, index = false }) {
4442}
4543
4644export async function getStaticProps({ params }) {
47− const post = getPostBySlug(
45+ const post = matchEcosystemPost(getPostBySlug(
4846 params.slug,
4947 ["title", "slug", "date", "featured-1", "featured-2", "featured-3"],
5048 "ecosystem/spotlight"
51− );
52− const marketplaces = getAllPosts(["title", "image", "slug"], "marketplaces");
53− const podcasts = getAllPosts(
54− ["title", "image", "date", "podcast", "slug"],
55− "podcasts",
56− "date"
57− );
58− const organizations = getAllPosts(
59− ["title", "image", "slug"],
60− "organizations"
61− );
62− const applications = fs
63− .readdirSync(path.join(process.cwd(), "content/applications"), {
64− withFileTypes: true,
65− })
66− .filter((f) => f.isDirectory())
67− .map((dir) =>
68− getAllPosts(
69− ["title", "bgColor", "image", "slug", "description"],
70− `applications/${dir.name}`
71− )
72− .map((e) => ({ ...e, ship: dir.name }))
73− .flat()
74− )
75− .flat()
76− .sort((a, b) => {
77− const nameA = a.title.toLowerCase();
78− const nameB = b.title.toLowerCase();
79− return nameA < nameB ? -1 : 1;
80− });
81−
82− ["featured-1", "featured-2", "featured-3"].forEach((feat) => {
83− if (post?.[feat]) {
84− const matchedPost = [
85− ...applications.map((e) => ({ ...e, type: "Application" })),
86− ...organizations.map((e) => ({ ...e, type: "Organization" })),
87− ...podcasts.map((e) => ({ ...e, type: "Podcast" })),
88− ...marketplaces.map((e) => ({ ...e, type: "Marketplace" })),
89− ].filter((e) => e.title === post[feat].title)?.[0];
90− post[feat].image = post[feat]?.image || matchedPost?.image || null;
91− post[feat].type = matchedPost?.type || "Podcast";
92− post[feat].matchedPost = matchedPost || null;
93− post[feat].content = JSON.stringify(
94− Markdown.parse({
95− post: { content: post[feat].content },
96− })
97− );
98− }
99− });
49+ ));
10050
10151 return {
10252 props: { post },
pages/events.js+18−4
@@ -15,11 +15,15 @@ import Footer from "../components/Footer";
1515import Header from "../components/Header";
1616import EventPreview from "../components/EventPreview";
1717import { getAllEvents, pair } from "../lib/lib";
18+import { useRouter } from "next/router";
1819
1920import { eventKeys } from "../lib/constants";
2021
2122export default function Events({ events, search }) {
2223 const [selected, setSelected] = useState("All");
24+ const router = useRouter();
25+ const { tag } = router.query;
26+
2327 const post = {
2428 title: "Events",
2529 description: "In-person, remote, and recorded events about Urbit.",
@@ -27,6 +31,13 @@ export default function Events({ events, search }) {
2731
2832 const now = DateTime.now();
2933
34+ const tagFilter = (event) => {
35+ if (tag) {
36+ return event?.tags?.includes(tag)
37+ } else {
38+ return true;
39+ }
40+ }
3041 const selectionFilter = (event) => {
3142 if (selected === "All") {
3243 return true;
@@ -38,7 +49,7 @@ export default function Events({ events, search }) {
3849 };
3950
4051 const pastEvents = pair(
41− events.filter(selectionFilter).filter((event) => {
52+ events.filter(selectionFilter).filter(tagFilter).filter((event) => {
4253 const ends = generateRealtimeDate(event.ends);
4354 return ends < now;
4455 })
@@ -47,6 +58,7 @@ export default function Events({ events, search }) {
4758 const futureEvents = pair(
4859 events
4960 .filter(selectionFilter)
61+ .filter(tagFilter)
5062 .filter((event) => {
5163 const starts = generateRealtimeDate(event.starts);
5264 return starts > now;
@@ -64,7 +76,7 @@ export default function Events({ events, search }) {
6476 );
6577
6678 const happeningNow = pair(
67− events.filter(selectionFilter).filter((event) => {
79+ events.filter(selectionFilter).filter(tagFilter).filter((event) => {
6880 const starts = generateRealtimeDate(event.starts);
6981 const ends = generateRealtimeDate(event.ends);
7082 return starts < DateTime.now() && ends > now;
@@ -93,10 +105,12 @@ export default function Events({ events, search }) {
93105 </Head>
94106 <IntraNav ourSite="https://urbit.org" search={search} />
95107 <SingleColumn>
96− <Header />
108+ <Header search={search} />
97109 <Section>
98110 <div className="measure">
99− <h1 className="pb-16">Events</h1>
111+ {tag
112+ ? <h1 className="pb-16">{events.filter(tagFilter).length} events tagged "{tag}"</h1>
113+ : <h1 className="pb-16">Events</h1>}
100114 <div className="flex space-x-2">
101115 <SelectedButton selection="All" text="All Events" />
102116 <SelectedButton selection="In-person" text="In-person" />
pages/events/[slug].js+1−1
@@ -49,7 +49,7 @@ export default function Event({
4949 </Head>
5050 <IntraNav ourSite="https://urbit.org" search={search} />
5151 <SingleColumn>
52− <Header />
52+ <Header search={search} />
5353 <Section narrow short>
5454 <h1>{event.title}</h1>
5555 <h3 className="mt-6">{event.description}</h3>
pages/getinvolved.jsnew file+58
@@ -0,0 +1,58 @@
1+import Head from "next/head";
2+import Meta from "../components/Meta";
3+import Link from "next/link";
4+import {
5+ Container,
6+ SingleColumn,
7+ Section,
8+ IntraNav,
9+ getAllPosts,
10+ formatDate,
11+ generateDisplayDate,
12+} from "@urbit/foundation-design-system";
13+import Footer from "../components/Footer";
14+import Header from "../components/Header";
15+import BackgroundImage from "../components/BackgroundImage";
16+import { contact } from "../lib/constants";
17+
18+export default function Blog({ posts, search }) {
19+ const post = {
20+ title: "Getting Started With Urbit",
21+ description:
22+ "Links to get started with Urbit.",
23+ };
24+ return (
25+ <Container>
26+ <Head>
27+ <title>Blog • urbit.org</title>
28+ {Meta(post)}
29+ </Head>
30+ <IntraNav ourSite="https://urbit.org" search={search} />
31+ <SingleColumn>
32+ <Header search={search} />
33+ <Section>
34+ <h1 className="pb-16">Getting Started With Urbit</h1>
35+ <div className="">
36+
37+ <p className="text-md">
38+ • <Link href="https://developers.urbit.org/courses">Take a course on Hoon</Link>
39+ </p>
40+ <p className="text-md">
41+ • <Link href="/grants/proposals">Submit a grant proposal</Link>
42+ </p>
43+ <p className="text-md">
44+ • <Link href="https://urbit.org/grants?type=Bounty#view-grants">Pick up an open bounty</Link>
45+ </p>
46+ <p className="text-md">
47+ • <Link href="https://developers.urbit.org/guides/quickstart/intro">Build an app</Link>
48+ </p>
49+
50+ </div>
51+ </Section>
52+
53+ </SingleColumn>
54+ <Footer />
55+ </Container>
56+ );
57+}
58+
pages/getting-started/[[...slug]].js+181−183
@@ -22,21 +22,29 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
2222 });
2323 };
2424
25− let menu = [{ title: "Overview", slug: "", weight: 0 }],
26− additional = [];
25+ let started = [{ title: "Introduction", slug: "", weight: 0 }],
26+ around = [],
27+ selfhost = [],
28+ hostprov = [];
2729
2830 posts.pages.map((post) => {
29− if (post?.tag === "additional") {
30− additional.push(post);
31− } else {
32− menu.push(post);
31+ if (post?.tag === "around") {
32+ around.push(post);
33+ } else if (post?.tag === "selfhost") {
34+ selfhost.push(post);
35+ } else if (post?.tag === "hostprov") {
36+ hostprov.push(post);
37+ } else if (post?.tag === "started") {
38+ started.push(post);
3339 }
3440 });
3541
36− menu.sort((a, b) => a.weight > b.weight);
37− additional.sort((a, b) => a.weight > b.weight);
42+ started.sort((a, b) => a.weight > b.weight);
43+ selfhost.sort((a, b) => a.weight > b.weight);
44+ hostprov.sort((a, b) => a.weight > b.weight);
45+ around.sort((a, b) => a.weight > b.weight);
3846
39− const rootClasses = "pl-0 font-semibold text-base hover:text-green-400";
47+ const rootClasses = "pl-0 font-semibold antialiased text-base hover:text-green-400";
4048
4149 return (
4250 <>
@@ -46,11 +54,8 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
4654 </Head>
4755 <div className="flex h-screen min-h-screen w-screen sidebar">
4856 <Sidebar search={search}>
49− <p className="uppercase pb-1 font-bold text-xs text-wall-400">
50− Getting Started
51− </p>
5257 <ul>
53− {menu.map((post) => (
58+ {started.map((post) => (
5459 <li>
5560 <Link href={post.slug} passHref>
5661 <a className={`relative ${select(post.slug)} ${rootClasses}`}>
@@ -60,11 +65,39 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
6065 </li>
6166 ))}
6267 </ul>
63− <ul className="mt-8">
64− <p className="uppercase pb-1 font-bold text-xs text-wall-400">
65− Additional Guides
68+ <ul className="mt-6">
69+ <p className="uppercase pb-1 font-bold antialiased text-xs text-wall-400">
70+ Run Yourself
6671 </p>
67− {additional.map((post) => (
72+ {selfhost.map((post) => (
73+ <li>
74+ <Link href={post.slug} passHref>
75+ <a className={`relative ${select(post.slug)} ${rootClasses}`}>
76+ {post.title}
77+ </a>
78+ </Link>
79+ </li>
80+ ))}
81+ </ul>
82+ <ul className="mt-6">
83+ <p className="uppercase pb-1 font-bold antialiased text-xs text-wall-400">
84+ Hosting
85+ </p>
86+ {hostprov.map((post) => (
87+ <li>
88+ <Link href={post.slug} passHref>
89+ <a className={`relative ${select(post.slug)} ${rootClasses}`}>
90+ {post.title}
91+ </a>
92+ </Link>
93+ </li>
94+ ))}
95+ </ul>
96+ <ul className="mt-6">
97+ <p className="uppercase pb-1 font-bold antialiased text-xs text-wall-400">
98+ Getting Around
99+ </p>
100+ {around.map((post) => (
68101 <li>
69102 <Link href={post.slug} passHref>
70103 <a className={`relative ${select(post.slug)} ${rootClasses}`}>
@@ -87,7 +120,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
87120 <div className="markdown">
88121 <Markdown.render content={JSON.parse(markdown)} />
89122 </div>
90− {!params?.slug && <LaunchCards />}
123+ {/* {!params?.slug && <LaunchCards />} */}
91124 </ContentArea>
92125 </div>
93126 </>
@@ -96,9 +129,7 @@ export default function UsingLayout({ posts, data, params, search, markdown }) {
96129
97130const breadcrumbs = (posts, paths) => {
98131 const results = [
99− <Link href="/">Urbit</Link>,
100− <span className="px-1">/</span>,
101− <Link href="/getting-started">Getting Started</Link>,
132+ <Link href="/getting-started">Getting Started</Link>
102133 ];
103134 let thisLink = "/getting-started";
104135 for (const path of paths) {
@@ -112,168 +143,135 @@ const breadcrumbs = (posts, paths) => {
112143 return results;
113144};
114145
115−function LaunchCards() {
116− const info = [
117− {
118− title: "Desktop app",
119− subtitle: "Deploy Urbit on your local system",
120− points: [
121− {
122− title: "Benefits",
123− content: ["Free", "Set up in minutes"],
124− },
125− {
126− title: "Considerations",
127− content: ["Limited functionality with certain applications"],
128− },
129− ],
130− svg: (
131− <svg
132− width="35"
133− height="49"
134− viewBox="0 0 35 49"
135− fill="none"
136− xmlns="http://www.w3.org/2000/svg"
137− >
138− <path
139− d="M7.43609 18.2477H10.856V2.43515C10.8608 1.09 11.9608 1.65662e-05 13.3153 1.65662e-05H21.4235C22.0767 -0.00236832 22.7012 0.252829 23.1623 0.71078C23.6234 1.16632 23.8828 1.7888 23.8828 2.43515V18.2477H27.3123C28.3714 18.2453 29.3393 18.8535 29.7883 19.8075C30.2399 20.7639 30.091 21.8896 29.4089 22.6982L19.4734 34.5206C18.9523 35.1359 18.1837 35.4937 17.3744 35.4937C16.565 35.4937 15.7965 35.136 15.2753 34.5206L5.3325 22.6982C4.64802 21.8896 4.50151 20.7591 4.95304 19.8051C5.40457 18.8511 6.37481 18.2429 7.43635 18.2477H7.43609Z"
140− className="fill-wall-600"
141− />
142− <path
143− d="M0 46.4217V44.5866C0.00657627 43.5411 0.854839 42.6928 1.90369 42.6928H32.8365C33.8853 42.6928 34.7336 43.5411 34.7402 44.5866V46.4217C34.7402 47.4738 33.8886 48.3287 32.8365 48.3352H1.90369C0.851556 48.3286 0 47.4738 0 46.4217Z"
144− className="fill-wall-600"
145− />
146− </svg>
147− ),
148− href: "/getting-started/desktop",
149− },
150− {
151− title: "Hosted urbit",
152− subtitle: "Deploy Urbit on a managed service",
153− points: [
154− {
155− title: "Benefits",
156− content: [
157− "Accessibility from anywhere",
158− "Streamlined setup for ownership and identity",
159− "No technical proficiency required",
160− ],
161− },
162− {
163− title: "Considerations",
164− content: [
165− "Requires monthly subscription",
166− "Requires trust in your service provider",
167− ],
168− },
169− ],
170− svg: (
171− <svg
172− width="50"
173− height="50"
174− viewBox="0 0 50 50"
175− fill="none"
176− xmlns="http://www.w3.org/2000/svg"
177− >
178− <rect width="50" height="23.1481" rx="10" className="fill-wall-600" />
179− <rect
180− y="26.8519"
181− width="50"
182− height="23.1481"
183− rx="10"
184− className="fill-wall-600"
185− />
186− <ellipse
187− cx="40.4167"
188− cy="11.5741"
189− rx="2.91667"
190− ry="3.24074"
191− className="fill-white"
192− />
193− <ellipse
194− cx="40.4167"
195− cy="38.4259"
196− rx="2.91667"
197− ry="3.24074"
198− className="fill-white"
199− />
200− </svg>
201− ),
202− href: "https://operators.urbit.org/manual/running/hosting",
203− },
204− {
205− title: "Command line app",
206− subtitle: "Run Urbit from the terminal",
207− points: [
208− {
209− title: "Benefits",
210− content: ["Greater control", "Reliable", "Smaller footprint"],
211− },
212− {
213− title: "Considerations",
214− content: ["Requires familiarity with the command line"],
215− },
216− ],
217− svg: (
218− <svg
219− width="55"
220− height="55"
221− viewBox="0 0 66 50"
222− fill="none"
223− xmlns="http://www.w3.org/2000/svg"
224− >
225− <path
226− fill-rule="evenodd"
227− clip-rule="evenodd"
228− d="M52.9288 0.03125H3.07125C1.39393 0.03125 0.03125 1.39393 0.03125 3.07125V52.9288C0.03125 53.7333 0.351879 54.5081 0.921894 55.0781C1.49191 55.6481 2.26671 55.9688 3.07125 55.9688H52.9288C53.7333 55.9688 54.5081 55.6481 55.0781 55.0781C55.6481 54.5081 55.9688 53.7333 55.9688 52.9288V3.07125C55.9688 2.26671 55.6481 1.49189 55.0781 0.921894C54.5081 0.351894 53.7333 0.03125 52.9288 0.03125V0.03125ZM12.8 38.7912L20.78 30.7368L12.8 22.7568L17.1314 18.4254L27.2402 28.6079C27.8191 29.1779 28.1456 29.9586 28.1456 30.7721C28.1456 31.5885 27.8191 32.3693 27.2402 32.9393L17.0577 43.0481L12.8 38.7912ZM38.9425 43.1226H27.0113V37.0426H38.8688L38.9425 43.1226Z"
229− className="fill-wall-600"
230− />
231− </svg>
232− ),
233− href: "/getting-started/cli",
234− },
235− ];
236− return (
237− <div className="flex flex-col space-y-8 mt-8">
238− {info.map((e) => {
239− return (
240− <div className="p-8 bg-wall-100 rounded-xl max-w-screen-md flex flex-col">
241− <div className="flex">
242− <div className="pl-4 pr-8 justify-center items-center flex">
243− {e.svg}
244− </div>
245− <div className="flex flex-col">
246− <h4 className="text-2xl">{e.title}</h4>
247− <p className="font-light text-lg">{e.subtitle}</p>
248− </div>
249− </div>
250− <div className="flex mt-8 border-b-neutral-300 pt-2 pb-5 ">
251− {e.points.map((section) => {
252− return (
253− <div className="basis-1/2">
254− <p className="uppercase font-bold text-sm text-black">
255− {section.title}
256− </p>
257− <ul className="mx-8 my-2 list-disc text-sm flex flex-col space-y-2">
258− {section.content.map((point) => (
259− <li>{point}</li>
260− ))}
261− </ul>
262− </div>
263− );
264− })}
265− </div>
266− <Link href={e.href} passHref>
267− <a className="button-lg max-w-fit text-white mt-4 bg-green-400">
268− Get Started
269− </a>
270− </Link>
271− </div>
272− );
273− })}
274− </div>
275− );
276−}
146+// function LaunchCards() {
147+// const info = [
148+// {
149+// title: "Hosted urbit",
150+// subtitle: "Deploy Urbit on a managed service",
151+// points: [
152+// {
153+// title: "Benefits",
154+// content: [
155+// "Accessibility from anywhere",
156+// "Streamlined setup for ownership and identity",
157+// "No technical proficiency required",
158+// ],
159+// },
160+// {
161+// title: "Considerations",
162+// content: [
163+// "Requires monthly subscription",
164+// "Requires trust in your service provider",
165+// ],
166+// },
167+// ],
168+// svg: (
169+// <svg
170+// width="50"
171+// height="50"
172+// viewBox="0 0 50 50"
173+// fill="none"
174+// xmlns="http://www.w3.org/2000/svg"
175+// >
176+// <rect width="50" height="23.1481" rx="10" className="fill-wall-600" />
177+// <rect
178+// y="26.8519"
179+// width="50"
180+// height="23.1481"
181+// rx="10"
182+// className="fill-wall-600"
183+// />
184+// <ellipse
185+// cx="40.4167"
186+// cy="11.5741"
187+// rx="2.91667"
188+// ry="3.24074"
189+// className="fill-white"
190+// />
191+// <ellipse
192+// cx="40.4167"
193+// cy="38.4259"
194+// rx="2.91667"
195+// ry="3.24074"
196+// className="fill-white"
197+// />
198+// </svg>
199+// ),
200+// href: "/getting-started/hosted",
201+// },
202+// {
203+// title: "Command line app",
204+// subtitle: "Run Urbit from the terminal",
205+// points: [
206+// {
207+// title: "Benefits",
208+// content: ["Greater control", "Reliable", "Smaller footprint"],
209+// },
210+// {
211+// title: "Considerations",
212+// content: ["Requires familiarity with the command line"],
213+// },
214+// ],
215+// svg: (
216+// <svg
217+// width="55"
218+// height="55"
219+// viewBox="0 0 66 50"
220+// fill="none"
221+// xmlns="http://www.w3.org/2000/svg"
222+// >
223+// <path
224+// fill-rule="evenodd"
225+// clip-rule="evenodd"
226+// d="M52.9288 0.03125H3.07125C1.39393 0.03125 0.03125 1.39393 0.03125 3.07125V52.9288C0.03125 53.7333 0.351879 54.5081 0.921894 55.0781C1.49191 55.6481 2.26671 55.9688 3.07125 55.9688H52.9288C53.7333 55.9688 54.5081 55.6481 55.0781 55.0781C55.6481 54.5081 55.9688 53.7333 55.9688 52.9288V3.07125C55.9688 2.26671 55.6481 1.49189 55.0781 0.921894C54.5081 0.351894 53.7333 0.03125 52.9288 0.03125V0.03125ZM12.8 38.7912L20.78 30.7368L12.8 22.7568L17.1314 18.4254L27.2402 28.6079C27.8191 29.1779 28.1456 29.9586 28.1456 30.7721C28.1456 31.5885 27.8191 32.3693 27.2402 32.9393L17.0577 43.0481L12.8 38.7912ZM38.9425 43.1226H27.0113V37.0426H38.8688L38.9425 43.1226Z"
227+// className="fill-wall-600"
228+// />
229+// </svg>
230+// ),
231+// href: "/getting-started/cli",
232+// }
233+// ];
234+// return (
235+// <div className="flex flex-col space-y-8 mt-8">
236+// {info.map((e) => {
237+// return (
238+// <div className="p-8 bg-wall-100 rounded-xl max-w-screen-md flex flex-col">
239+// <div className="flex">
240+// <div className="pl-4 pr-8 justify-center items-center flex">
241+// {e.svg}
242+// </div>
243+// <div className="flex flex-col">
244+// <h4 className="text-2xl">{e.title}</h4>
245+// <p className="font-light text-lg">{e.subtitle}</p>
246+// </div>
247+// </div>
248+// <div className="flex mt-8 border-b-neutral-300 pt-2 pb-5 ">
249+// {e.points.map((section) => {
250+// return (
251+// <div className="basis-1/2">
252+// <p className="uppercase font-bold text-sm text-black">
253+// {section.title}
254+// </p>
255+// <ul className="mx-8 my-2 list-disc text-sm flex flex-col space-y-2">
256+// {section.content.map((point) => (
257+// <li>{point}</li>
258+// ))}
259+// </ul>
260+// </div>
261+// );
262+// })}
263+// </div>
264+// <Link href={e.href} passHref>
265+// <a className="button-lg max-w-fit text-white mt-4 bg-green-400">
266+// Get Started
267+// </a>
268+// </Link>
269+// </div>
270+// );
271+// })}
272+// </div>
273+// );
274+// }
277275
278276export async function getStaticProps({ params }) {
279277 let posts = GettingStartedTree;
pages/grants.js+88−67
@@ -15,6 +15,8 @@ import GrantPreview from "../components/GrantPreview";
1515import JoinGroup from "../components/JoinGroup";
1616import omit from "lodash.omit";
1717import { getGrantsCategories, getGrantsTypes } from "../lib/lib";
18+import fs from 'fs';
19+import { join } from 'path';
1820
1921function isArray(arr) {
2022 return Array.isArray(arr);
@@ -31,7 +33,7 @@ export default function Grants({ posts, categories, types, search }) {
3133 const router = useRouter();
3234 let { status, type, category } = router.query;
3335 if (status === undefined) {
34− status = "open";
36+ status = ["open", "wip"];
3537 }
3638
3739 function push(toQuery) {
@@ -80,8 +82,8 @@ export default function Grants({ posts, categories, types, search }) {
8082 const byStatus = (post) => {
8183 return (
8284 (isOrIsIn("open", status) ? post.status === "open" : false) ||
83− (isOrIsIn("complete", status) ? post.status === "completed" : false) ||
84− (isOrIsIn("wip", status) ? post.status === "wip" : false)
85+ (isOrIsIn("complete", status) ? post.status === "completed" : false) ||
86+ (isOrIsIn("wip", status) ? post.status === "wip" : false)
8587 );
8688 };
8789
@@ -89,10 +91,10 @@ export default function Grants({ posts, categories, types, search }) {
8991
9092 const filteredPosts = postsByStatus.filter((post) => {
9193 const hasCategory = category
92− ? isArray(category)
93− ? post.taxonomies.grant_category.some((cat) => category.includes(cat))
94− : post.taxonomies.grant_category.includes(category)
95− : true;
94+ ? isArray(category)
95+ ? post.taxonomies.grant_category.some((cat) => category.includes(cat))
96+ : post.taxonomies.grant_category.includes(category)
97+ : true;
9698
9799 const notCanceled = !post.extra.canceled;
98100 const hasType = type ? post.taxonomies.grant_type.includes(type) : true;
@@ -105,6 +107,9 @@ export default function Grants({ posts, categories, types, search }) {
105107 Bounty: postsByStatus.filter((post) =>
106108 post.taxonomies.grant_type.includes("Bounty")
107109 ).length,
110+ RFP: postsByStatus.filter((post) =>
111+ post.taxonomies.grant_type.includes("RFP")
112+ ).length,
108113 Apprenticeship: postsByStatus.filter((post) =>
109114 post.taxonomies.grant_type.includes("Apprenticeship")
110115 ).length,
@@ -120,12 +125,12 @@ export default function Grants({ posts, categories, types, search }) {
120125 {Meta({
121126 title: "Grants",
122127 description:
123− "Contribute to the Urbit project while earning address space.",
128+ "Contribute to the Urbit project while earning address space.",
124129 })}
125130 </Head>
126131 <IntraNav ourSite="https://urbit.org" search={search} />
127132 <SingleColumn>
128− <Header />
133+ <Header search={search} />
129134 {
130135 // Heading and Introduction
131136 }
@@ -155,11 +160,18 @@ export default function Grants({ posts, categories, types, search }) {
155160 fund all kinds projects, not strictly technical ones, so don't
156161 hesitate to pitch your idea!
157162 </p>
158− <Link href="/grants/proposals" passHref>
159− <a className="button-sm bg-blue-400 text-white mb-8 max-w-fit">
160− Submit a Proposal
161− </a>
162− </Link>
163+ <div className="flex flex-wrap mb-8">
164+ <Link href="/grants/proposals" passHref>
165+ <a className="button-sm bg-blue-400 text-white mb-8 max-w-fit mr-2">
166+ Submit a Proposal
167+ </a>
168+ </Link>
169+ <Link href="/grants?program=rfps&type=RFP#view-grants" passHref>
170+ <a className="button-sm bg-purple text-white mb-8 max-w-fit">
171+ Get Ideas
172+ </a>
173+ </Link>
174+ </div>
163175
164176 {/* Apprenticeships */}
165177 <h3>Apprenticeships</h3>
@@ -183,7 +195,7 @@ export default function Grants({ posts, categories, types, search }) {
183195 Bounties are contracts for work provided by either the Urbit
184196 Foundation or from trusted partners in our ecosystem.
185197 </p>
186− <div className="flex flex-wrap">
198+ <div className="flex flex-wrap mb-8">
187199 <Link href="/grants/bounties#post-a-bounty" passHref>
188200 <a className="button-sm bg-yellow-300 text-black mr-2 max-w-fit">
189201 Post a Bounty
@@ -225,6 +237,12 @@ export default function Grants({ posts, categories, types, search }) {
225237 by those that post them.
226238 </p>
227239 </li>
240+ <li className="mb-2">
241+ <p>
242+ <Link href="/grants/rfps">RFPs</Link>{" "}
243+ are suitable for people experienced with hoon development but who need some ideas on what to work on.
244+ </p>
245+ </li>
228246 <li className="mb-2">
229247 <p>
230248 <Link href="/grants/apprenticeships">Apprenticeships</Link>{" "}
@@ -238,19 +256,15 @@ export default function Grants({ posts, categories, types, search }) {
238256 <div className="md:basis-1/2">
239257 <p className="mb-8">
240258 Whether you're gearing up to submit your proposal or just
241− thinking about it, the best way to get started is to join the
242− Foundation group on Urbit:
259+ thinking about it, the best way to get started is to join the <Link href="/groups/~halbex-palheb/uf-public">Urbit Foundation</Link> group, ask questions there or come find our grants office hours in the group.
243260 </p>
244−
245− <JoinGroup
246− emphasize
247− className="mb-8"
248− groupName="~wolref-podlex/foundation"
249− />
250−
251− <p>
252− If you're not on the network, check out our{" "}
253− <Link href="/getting-started">Getting Started</Link> guide.
261+ <p className="mb-8">
262+ Feel free to contact <a href="/ids/~poldec-tonteg">~poldec-tonteg</a> with general questions or <a href="/ids/~marfun-pacpet">~marfun-pacpet</a> regarding administrative matters.
263+ </p>
264+ <p className="mb-8">
265+ <h4>Approval</h4>
266+ </p>
267+ <p className="mb-8">Grant applications and proposals are approved on a bi-weekly basis on the second and fourth Wednesday of the month.
254268 </p>
255269 </div>
256270 </div>
@@ -264,9 +278,8 @@ export default function Grants({ posts, categories, types, search }) {
264278 <h5 className="text-wall-600 font-semibold my-2">Programs</h5>
265279 <div className="flex flex-wrap items-center pb-2">
266280 <a
267− className={`badge-lg mr-2 ${
268− !type ? "bg-black text-white" : "bg-wall-100 text-wall-500"
269− }`}
281+ className={`badge-lg mr-2 ${!type ? "bg-black text-white" : "bg-wall-100 text-wall-500"
282+ }`}
270283 onClick={() => push((({ type, ...obj }) => obj)(router.query))}
271284 >
272285 All <div className="opacity-50 ml-2">{allCount}</div>
@@ -274,25 +287,27 @@ export default function Grants({ posts, categories, types, search }) {
274287 {types.map((each) => {
275288 let activeBg;
276289 switch (each) {
277− case "Proposal":
278− activeBg = "bg-blue-400 text-white";
279− break;
280− case "Bounty":
281− activeBg = "bg-yellow-300 text-white";
282− break;
283− case "Apprenticeship":
284− activeBg = "bg-green-400 text-white";
285− break;
286− default:
287− activeBg = "bg-black";
290+ case "Proposal":
291+ activeBg = "bg-blue-400 text-white";
292+ break;
293+ case "Bounty":
294+ activeBg = "bg-yellow-300 text-white";
295+ break;
296+ case "RFP":
297+ activeBg = "bg-purple-400 text-white";
298+ break;
299+ case "Apprenticeship":
300+ activeBg = "bg-green-400 text-white";
301+ break;
302+ default:
303+ activeBg = "bg-black";
288304 }
289305 return (
290306 <a
291− className={`badge-lg mr-2 ${
292− isOrIsIn(each, type)
293− ? activeBg
294− : "bg-wall-100 text-wall-500"
295− }`}
307+ className={`badge-lg mr-2 ${isOrIsIn(each, type)
308+ ? activeBg
309+ : "bg-wall-100 text-wall-500"
310+ }`}
296311 onClick={() => push({ ...router.query, type: each })}
297312 >
298313 {each}
@@ -305,8 +320,8 @@ export default function Grants({ posts, categories, types, search }) {
305320 <div className="flex flex-wrap mb-12">
306321 {categories.map((each) => {
307322 const active = isOrIsIn(each, category)
308− ? "bg-green-400 text-white"
309− : "bg-wall-100 text-wall-500";
323+ ? "bg-green-400 text-white"
324+ : "bg-wall-100 text-wall-500";
310325 const categoryQuery = pushOrDropQuery("category", category, each);
311326 return (
312327 <button
@@ -322,20 +337,20 @@ export default function Grants({ posts, categories, types, search }) {
322337 {["open", "complete", "wip"].map((each) => {
323338 let title;
324339 switch (each) {
325− case "open":
326− title = isOrIsIn(each, status)
327− ? "Exclude Open"
328− : "Include Open";
329− break;
330− case "complete":
331− title = isOrIsIn(each, status)
332− ? "Exclude Completed"
333− : "Include Completed";
334− break;
335− case "wip":
336− title = isOrIsIn(each, status)
337− ? "Exclude In Progress"
338− : "Include In Progress";
340+ case "open":
341+ title = isOrIsIn(each, status)
342+ ? "Exclude Open"
343+ : "Include Open";
344+ break;
345+ case "complete":
346+ title = isOrIsIn(each, status)
347+ ? "Exclude Completed"
348+ : "Include Completed";
349+ break;
350+ case "wip":
351+ title = isOrIsIn(each, status)
352+ ? "Exclude In Progress"
353+ : "Include In Progress";
339354 }
340355 const statusQuery = pushOrDropQuery("status", status, each);
341356 return (
@@ -365,11 +380,17 @@ export default function Grants({ posts, categories, types, search }) {
365380export async function getStaticProps() {
366381 const categories = getGrantsCategories();
367382 const types = getGrantsTypes();
368− const posts = getAllPosts(
369− ["title", "slug", "date", "description", "extra", "taxonomies"],
370− "grants",
371− "date"
372− );
383+ const basePath = join(process.cwd(), 'content/grants')
384+ const years = fs.readdirSync(basePath, { 'withFileTypes': true }).filter((f) => f.isDirectory());
385+ const posts = years.map((year) => {
386+ return getAllPosts(
387+ ["title", "slug", "date", "description", "extra", "taxonomies"],
388+ `grants/${year.name}`,
389+ "date"
390+ )
391+ }).flat()
392+ .sort((a, b) => new Date(b.date) - new Date(a.date));
393+
373394 return {
374395 props: {
375396 posts: posts,
pages/grants/[slug].js+168−64
@@ -11,15 +11,21 @@ import {
1111 Section,
1212 IntraNav,
1313 getPostBySlug,
14− getAllPosts,
14+ getPage,
1515 formatDate,
1616} from "@urbit/foundation-design-system";
1717import Header from "../../components/Header";
1818import Footer from "../../components/Footer";
19+import MetadataBlock from "../../components/ecosystem/MetadataBlock";
20+import ResourceCard from "../../components/gateway/ResourceCard";
21+import JoinGroup from "../../components/JoinGroup";
1922import ob from "urbit-ob";
2023import { DateTime } from "luxon";
24+import fs from 'fs';
25+import path, { join } from 'path';
26+import { getGrantYear } from "../../lib/lib";
2127
22−export default function Grant({ post, markdown, search }) {
28+export default function Grant({ post, markdown, match, search }) {
2329 const router = useRouter();
2430 if (!router.isFallback && !post?.slug) {
2531 return <ErrorPage />;
@@ -29,33 +35,89 @@ export default function Grant({ post, markdown, search }) {
2935 const assignee = post?.extra?.assignee;
3036 const mentor = post.extra.mentor || post.extra.champion;
3137 const assigneeLink =
32− assignee &&
33− assignee.map((each, index) => {
34− return ob.isValidPatp(each) ? (
35− <>
36− {index ? ", " : ""}
37− <Link href={`/ids/${each}`} passHref>
38− <a className="text-green-400">{each}</a>
39− </Link>
40− </>
41− ) : (
42− <>
43− {index ? ", " : ""}
44− {each}
45− </>
46− );
47− });
38+ assignee &&
39+ assignee.map((each, index) => {
40+ return ob.isValidPatp(each) ? (
41+ <>
42+ {index ? ", " : ""}
43+ <Link href={`/ids/${each}`} passHref>
44+ <a className="text-green-400">{each}</a>
45+ </Link>
46+ </>
47+ ) : (
48+ <>
49+ {index ? ", " : ""}
50+ {each}
51+ </>
52+ );
53+ });
4854 const mentorLink =
49− mentor && ob.isValidPatp(mentor) ? (
50− <Link href={`/ids/${mentor}`} passHref>
51− <a className="text-green-400">{mentor}</a>
52− </Link>
53− ) : (
54− mentor
55− );
55+ mentor &&
56+ mentor.map((each, index) => {
57+ return ob.isValidPatp(each) ? (
58+ <>
59+ {index ? ", " : ""}
60+ <Link href={`/ids/${each}`} passHref>
61+ <a className="text-green-400">{each}</a>
62+ </Link>
63+ </>
64+ ) : (
65+ <>
66+ {index ? ", " : ""}
67+ {each}
68+ </>
69+ );
70+ });
71+
72+ let status = "";
73+ if (isOpen) {
74+ status = "Open"
75+ } else if (post?.extra?.completed) {
76+ status = "Completed"
77+ } else if (post?.extra?.canceled) {
78+ status = "Canceled"
79+ } else {
80+ status = "In Progress"
81+ }
82+ const statusBadge = <div className={
83+ classnames("badge-sm mr-1 my-1", {
84+ "bg-red": status === "Canceled",
85+ "bg-green-400 text-white": status === "Completed" || status === "Open",
86+ "bg-wall-300": status === "In Progress",
87+ })}>
88+ {status}
89+ </div>;
90+
91+ let deliverable = null;
92+ if (post.extra.deliverable) {
93+ if (match) {
94+ deliverable = <ResourceCard
95+ title={match.data.title}
96+ image={match.data.image}
97+ color={match.data.bgColor || "#000000"}
98+ description={match.data?.description || ""}
99+ type="application"
100+ shortcode={post.extra.deliverable}
101+ full
102+/>
103+ }
104+ else if (post.extra.deliverable.startsWith("~")) {
105+ deliverable = <JoinGroup emphasize groupName={post.extra.deliverable} />
106+ } else {
107+ deliverable = <a className="font-medium text-green-400" href={post.extra.deliverable}>{post.extra.deliverable}</a>
108+ }
109+ }
110+
56111 const metaPost = Object.assign({}, post);
57112 metaPost.title = `${post.title} - Grant`;
58113
114+ const isRFP = post.taxonomies.grant_type.filter((category) => {
115+ return category === "RFP";
116+ }).length > 0;
117+
118+ const hasChampion = post.extra.champion && post.extra.champion[0] !== "";
119+ const hasAssignee = post.extra.assignee && post.extra.assignee[0] !== "";
120+
59121 return (
60122 <Container>
61123 <Head>
@@ -64,43 +126,14 @@ export default function Grant({ post, markdown, search }) {
64126 </Head>
65127 <IntraNav ourSite="https://urbit.org" search={search} />
66128 <SingleColumn>
67− <Header />
129+ <Header search={search} />
68130 <Section narrow short>
69131 <h1>{post.title}</h1>
70− {post.extra.assignee ? (
71− <div className="type-ui text-wall-500 mt-4">
72− Grantee(s): {assigneeLink}
73− </div>
74− ) : null}
75− {post.extra.mentor ? (
76− <div className="type-ui text-wall-500 mt-4">
77− Mentor: {mentorLink}
78− </div>
79− ) : null}
80− {post.extra.champion ? (
81− <div className="type-ui text-wall-500 mt-4">
82− Champion: {mentorLink}
83− </div>
84− ) : null}
85− {post.extra.ship ? (
86− <Link href={`/ids/${post.extra.ship}`} passHref>
87− <a className="type-sub-bold text-wall-500 font-mono">
88− {post.extra.ship}
89− </a>
90− </Link>
91− ) : null}
92− <div className="type-ui text-wall-500 mt-4 md:mt-8 lg:mt-10 flex items-center space-x-1">
93− {formatDate(DateTime.fromISO(post.date))}
94− {post?.extra?.grant_id ? (
95− <>
96− <p className="ml-1 text-wall-500 type-ui">• ID:</p>
97− <p className="font-mono type-ui"> {post.extra.grant_id}</p>
98− </>
99− ) : null}
100− </div>
101− <div className="flex items-center flex-wrap mt-4 md:mt-8 lg:mt-10">
132+ <div className="flex items-center flex-wrap my-4">
133+ {statusBadge}
102134 {post.taxonomies.grant_type.map((category) => {
103135 const className = classnames({
136+ "bg-purple-400 text-white": category === "RFP",
104137 "bg-blue-400 text-white": category === "Proposal",
105138 "bg-green-400 text-white": category === "Apprenticeship",
106139 "bg-yellow-300": category === "Bounty",
@@ -117,10 +150,59 @@ export default function Grant({ post, markdown, search }) {
117150 </div>
118151 ))}
119152 </div>
153+ <div className="flex flex-wrap justify-between">
154+ {post?.extra?.grant_id ? (
155+ <>
156+ <MetadataBlock
157+ title="ID"
158+ content={post.extra.grant_id}
159+ />
160+ </>
161+ ) : null}
162+ <MetadataBlock
163+ title="Date"
164+ content={formatDate(DateTime.fromISO(post.date))}
165+ />
166+ {post.extra.mentor ? (
167+ <MetadataBlock
168+ title="Mentor"
169+ content={mentorLink}
170+ />
171+ ) : null}
172+ {hasChampion ? (
173+ <MetadataBlock
174+ title="Champion"
175+ content={mentorLink}
176+ />
177+ ) : null}
178+ {hasAssignee ? (
179+ <MetadataBlock
180+ title="Grantee(s)"
181+ content={assigneeLink}
182+ />
183+ ) : null}
184+ </div>
185+ {post?.extra?.link?.startsWith("~") && <div className="flex flex-col my-4 space-y-2">
186+ <p className="text-wall-400 font-semibold">Group</p>
187+ <JoinGroup emphasize groupName={post.extra.link} />
188+ </div>}
189+ {deliverable && <div className="flex flex-col my-4 space-y-2">
190+ <p className="text-wall-400 font-semibold">Deliverable</p>
191+ {deliverable}
192+ </div>}
120193 </Section>
121194 <Section narrow className="markdown">
122195 <Markdown.render content={JSON.parse(markdown)} />
123196 </Section>
197+ {isRFP && (
198+ <a
199+ className="bg-green-400 text-white button-lg"
200+ href="/grants/rfps"
201+ target="_blank"
202+ >
203+ Learn More
204+ </a>
205+ )}
124206 {canApply && (
125207 <a
126208 className="bg-green-400 text-white button-lg"
@@ -136,28 +218,50 @@ export default function Grant({ post, markdown, search }) {
136218 );
137219}
138220
139−//
140221export async function getStaticProps({ params }) {
222+ // Gets post in any year folder sharing the slug name in the param
223+ const dir = getGrantYear(params.slug);
141224 const post = getPostBySlug(
142225 params.slug,
143226 ["title", "slug", "date", "description", "content", "extra", "taxonomies"],
144− "grants"
145− );
227+ `grants/${dir.name}`
228+ )
146229
147230 const markdown = JSON.stringify(Markdown.parse({ post }));
231+
232+ // Matches deliverable to page
233+ let match = null;
234+ if (post?.extra?.deliverable?.startsWith("~")) {
235+ const ship = post.extra.deliverable.split("/")[0];
236+ const application = post.extra.deliverable.split("/")[1];
237+ const fileExists = fs.existsSync(path.join(process.cwd(), "content/applications", ship, `${application}.md`));
238+ match = fileExists ? getPage(
239+ join(
240+ process.cwd(),
241+ "content/applications",
242+ post.extra.deliverable
243+ )
244+ ) : null
245+ }
148246 return {
149− props: { post, markdown },
247+ props: { post, markdown, match },
150248 };
151249}
152250
153251export async function getStaticPaths() {
154− const posts = getAllPosts(["slug", "date"], "grants", "date");
252+ // Flatten all year subfolders into a flat array of slugs
253+ const basePath = join(process.cwd(), 'content/grants')
254+ const years = fs.readdirSync(basePath, { 'withFileTypes': true });
255+ const posts = years.filter((year) => year.isDirectory()).map((year) => {
256+ const yearDir = fs.readdirSync(join(basePath, year.name), { 'withFileTypes': true });
257+ return yearDir.filter((entry) => entry.isFile()).map((entry) => entry.name.replace(/\.md$/, ""))
258+ }).flat()
155259
156260 return {
157261 paths: posts.map((post) => {
158262 return {
159263 params: {
160− slug: post.slug,
264+ slug: post,
161265 },
162266 };
163267 }),
pages/grants/apprenticeships.js+1−1
@@ -8,7 +8,7 @@ export default function Post({ post, markdown, search }) {
88 post={post}
99 markdown={markdown}
1010 search={search}
11− actionText="View Apprenticeships"
11+ actionText="View Requests"
1212 actionLink="/grants?program=apprenticeship&completed=true#view-grants"
1313 />
1414 );
pages/grants/rfps.jsnew file+29
@@ -0,0 +1,29 @@
1+import GrantProgramOverview from "../../components/GrantProgramOverview";
2+import { Markdown, getPostBySlug } from "@urbit/foundation-design-system";
3+
4+export default function Post({ post, markdown, search }) {
5+ return (
6+ <GrantProgramOverview
7+ program="rfps"
8+ post={post}
9+ markdown={markdown}
10+ search={search}
11+ actionText="View RFPs"
12+ actionLink="/grants?program=rfps#view-grants"
13+ />
14+ );
15+}
16+
17+export async function getStaticProps() {
18+ const post = getPostBySlug(
19+ "/rfps",
20+ ["title", "date", "slug", "content"],
21+ "/"
22+ );
23+
24+ const markdown = JSON.stringify(Markdown.parse({ post }));
25+
26+ return {
27+ props: { post, markdown },
28+ };
29+}
pages/groups/[[...group]].js+1−1
@@ -84,7 +84,7 @@ const GroupPage = ({ data, markdown, params, search }) => {
8484 Urbit is a clean-slate, peer-to-peer operating system and network.
8585 </h3>
8686 <div className="flex flex-col space-y-4">
87− <Link href="/guides/joining-groups" passHref>
87+ <Link href="/getting-started/joining-groups" passHref>
8888 <a className="button-lg max-w-xs bg-green-400 text-white">
8989 How to Join an Urbit Group
9090 </a>
pages/ids/[id].js+1−1
@@ -140,7 +140,7 @@ const IdPage = ({ data, markdown, applications, groups, network, params }) => {
140140 Urbit is a clean-slate, peer-to-peer operating system and network.
141141 </h3>
142142 <div className="flex flex-col space-y-4">
143− <Link href="/guides/getting-an-urbit-id">
143+ <Link href="/getting-started/get-id">
144144 <button className="button-lg max-w-xs bg-green-400 text-white">
145145 Learn how to get an Urbit ID
146146 </button>
pages/ids/submit.js+3−3
@@ -3,10 +3,10 @@ import {
33 Container,
44 SingleColumn,
55 Section,
6+ Sigil
67} from "@urbit/foundation-design-system";
78import { useInputChange } from "../../lib/hooks";
89import ob from "urbit-ob";
9−import Sigil from "../../components/Sigil";
1010import Head from "next/head";
1111import Meta from "../../components/Meta";
1212
@@ -56,8 +56,8 @@ ${form?.description || ""}`
5656 </p>
5757 <p>
5858 Then, to validate that you own that ID, send a DM to{" "}
59− <Link href="/ids/~haddef-sigwen" passHref>
60− <a>~haddef-sigwen</a>
59+ <Link href="/ids/~battus-datsun" passHref>
60+ <a>~battus-datsun</a>
6161 </Link>{" "}
6262 from your <code>@p</code> with a link to the pull request on
6363 GitHub. We’ll approve the pull request and your page will be
pages/index.js+142−132
@@ -19,12 +19,15 @@ import PostPreview from "../components/PostPreview";
1919import EventPreview from "../components/EventPreview";
2020import { eventKeys } from "../lib/constants";
2121import IndexCard from "../components/ecosystem/IndexCard";
22+import HighlightCard from "../components/HighlightCard";
2223import fs from "fs";
2324import path from "path";
2425import Meta from "../components/Meta";
26+import { matchEcosystemPost } from "../lib/lib";
2527
2628export default function Home({
2729 posts,
30+ highlights,
2831 ecosystem,
2932 events,
3033 grantNumbers,
@@ -33,74 +36,79 @@ export default function Home({
3336 const post = {
3437 title: "Urbit",
3538 description: "A clean-slate OS and network for the 21st century.",
39+ image: "https://storage.googleapis.com/media.urbit.org/site/opengraph/urbit.png"
3640 };
3741 return (
3842 <Container>
3943 <Head>
4044 <title>Urbit</title>
41− {Meta(post)}
45+ {Meta(post, false, true)}
4246 </Head>
4347 <IntraNav ourSite="https://urbit.org" search={search} />
4448 <SingleColumn>
45− <Header />
49+ <Header search={search} />
4650 {
4751 // Hero Statement
4852 }
4953 <Section className="pb-36">
50− <div>
54+ <div className="space-y-8">
5155 <h1>A clean-slate OS and network for the 21st&nbsp;century.</h1>
56+ <Link href="/getting-started" passHref><a className="bg-green-400 text-white button-lg max-w-fit">Get Started</a></Link>
5257 </div>
5358 </Section>
5459 {
5560 // Hero
5661 }
57− <Section>
58− <div className="bg-yellow-100 dark:bg-[#5C5037] w-full p-8 md:p-12 rounded-3xl flex flex-col md:flex-row">
59− <div className="md:w-10/12 w-full md:mr-6">
60− <h2 className="m-0 p-0 mr-4 pb-6">Assembly 2022</h2>
6162
62− <p>
63− Assembly 2022 is the second ever Urbit conference coming to you
64− this year from Miami Beach. Grab a towel and get ready.
63+ {
64+ // Highlights
65+ }
66+ <Section className="pb-12">
67+ <div className="flex flex-col space-y-4 md:space-y-0 md:flex-row md:space-x-4">
68+ <HighlightCard highlight={highlights[0]} key={highlights[0].slug} />
69+ <HighlightCard highlight={highlights[1]} key={highlights[1].slug} />
70+ <HighlightCard highlight={highlights[2]} key={highlights[2].slug} />
71+ </div>
72+ </Section>
73+
74+
75+
76+
77+ <Section narrow className="space-y-8">
78+
79+ <div className="w-full space-y-8 max-w-prose">
80+
81+ <h2 className="font-normal leading-tight">
82+ Urbit is a <span className="font-bold">new kind of computer</span>{" "}
83+ that you can <span className="font-bold">own completely</span> in
84+ ways that matter:{" "}
85+ <span className="font-bold">networking, identity, &amp; data</span>.
86+ </h2>
87+
88+ <div className="space-y-4">
89+ <p className="">
90+ We realized that in order to fix the internet, we had to build a new
91+ computer from scratch. Good thing we started over a decade ago.
6592 </p>
66− <p className="pt-4 font-bold pb-8">
67− September 22nd–25th • Miami Beach, Florida
93+ <p className="pb-4">
94+ Today, Urbit is a real system with thousands of users that are
95+ building all kinds of communities, software, DAOs, and more. And
96+ it’s getting better every day.{" "}
6897 </p>
69− <Link href="https://assembly.urbit.org" passHref>
70− <a className="button-lg max-w-fit bg-green-400 text-white">
71− Learn More
98+ <Link href="/overview" passHref>
99+ <a className="button-lg bg-green-400 text-white type-ui max-w-fit">
100+ Read the Overview
72101 </a>
73102 </Link>
74103 </div>
104+
75105 </div>
76106 </Section>
77− <Section narrow className="space-y-8">
78− <h2 className="font-normal">
79− Urbit is a <span className="font-bold">new kind of computer</span>{" "}
80− that you can <span className="font-bold">own completely</span> in
81− ways that matter:{" "}
82− <span className="font-bold">networking, identity, and data</span>.
83− </h2>
84− <p className="max-w-prose">
85− We realized that in order to fix the internet, we had to build a new
86− computer from scratch. Good thing we started over a decade ago.
87− </p>
88− <p className="max-w-prose">
89− Today, Urbit is a real system with thousands of users that are
90− building all kinds of communities, software, DAOs, and more. And
91− it’s getting better every day.{" "}
92− </p>
93− <Link href="/overview" passHref>
94− <a className="button-lg bg-green-400 text-white type-ui max-w-fit">
95− Read the Overview
96− </a>
97− </Link>
98− </Section>
99107 {/* Ecosystem */}
100108 <Section>
101109 <div className="flex flex-col space-y-8 pb-12">
102110 <h2 className="m-0 p-0 mr-4">Ecosystem</h2>
103− <p>
111+ <p className="max-w-prose">
104112 The Urbit ecosystem is comprised of a wide variety of individuals
105113 and organizations, including developers, DAOs, podcasters, and
106114 more.
@@ -126,6 +134,53 @@ export default function Home({
126134 </Link>
127135 </div>
128136 </Section>
137+
138+ {
139+ // Build on Urbit Developer CTA
140+ }
141+ <Section narrow>
142+ <h2 className="pb-8">Build on Urbit</h2>
143+ <h4 className="pb-6">
144+ Urbit is a personal OS designed from scratch to run peer-to-peer
145+ applications.
146+ </h4>
147+ <p className="pb-6">
148+ It solves the hard problems of implementing a peer-to-peer network
149+ (including identity, NAT traversal, and exactly-once delivery) in
150+ the kernel so app developers can focus on business logic.
151+ </p>
152+ <p className="pb-6">
153+ The entire OS is a{" "}
154+ <Link href="https://urbit.org/docs/nock/definition/" passHref>
155+ <a>single pure function</a>
156+ </Link>{" "}
157+ that provides application developers with strong guarantees:
158+ automated persistence and memory management, repeatable builds, and
159+ support for hot code reloading.
160+ </p>
161+ <p className="pb-10">
162+ You can get started learning how to{" "}
163+ <Link href="https://urbit.org/docs/development/develop/" passHref>
164+ <a>contribute to the project</a>
165+ </Link>
166+ , or view a variety of{" "}
167+ <Link
168+ href="https://github.com/urbit/awesome-urbit#http-apis-airlock"
169+ passHref
170+ >
171+ <a>libraries</a>
172+ </Link>{" "}
173+ for building on Urbit using the languages you already know.
174+ </p>
175+ <Link href="https://developers.urbit.org" passHref>
176+ <a className="button-lg type-ui text-white bg-green-400 max-w-fit">
177+ Visit Urbit Developers
178+ </a>
179+ </Link>
180+ </Section>
181+
182+
183+
129184 {
130185 // Grants
131186 }
@@ -162,7 +217,7 @@ export default function Home({
162217 </p>
163218 <div className="flex flex-wrap">
164219 <Link href="/grants" passHref>
165− <a className="button-lg bg-blue-400 text-white mr-2 mb-8">
220+ <a className="button-lg bg-blue-400 text-white mr-3 mb-8">
166221 Learn More
167222 </a>
168223 </Link>
@@ -175,49 +230,6 @@ export default function Home({
175230 </div>
176231 </Section>
177232
178− {
179− // Build on Urbit Developer CTA
180− }
181− <Section narrow>
182− <h2 className="pb-8">Build on Urbit</h2>
183− <h4 className="pb-6">
184− Urbit is a personal OS designed from scratch to run peer-to-peer
185− applications.
186− </h4>
187− <p className="pb-6">
188− It solves the hard problems of implementing a peer-to-peer network
189− (including identity, NAT traversal, and exactly-once delivery) in
190− the kernel so app developers can focus on business logic.
191− </p>
192− <p className="pb-6">
193− The entire OS is a{" "}
194− <Link href="https://urbit.org/docs/nock/definition/" passHref>
195− <a>single pure function</a>
196− </Link>{" "}
197− that provides application developers with strong guarantees:
198− automated persistence and memory management, repeatable builds, and
199− support for hot code reloading.
200− </p>
201− <p className="pb-10">
202− You can get started learning how to{" "}
203− <Link href="https://urbit.org/docs/development/develop/" passHref>
204− <a>contribute to the project</a>
205− </Link>
206− , or view a variety of{" "}
207− <Link
208− href="https://github.com/urbit/awesome-urbit#http-apis-airlock"
209− passHref
210− >
211− <a>libraries</a>
212− </Link>{" "}
213− for building on Urbit using the languages you already know.
214− </p>
215− <Link href="https://developers.urbit.org" passHref>
216− <a className="button-lg type-ui text-white bg-green-400 max-w-fit">
217− Visit Urbit Developers
218− </a>
219− </Link>
220− </Section>
221233
222234 {
223235 // Blog Posts
@@ -259,6 +271,26 @@ export default function Home({
259271 </Link>
260272 </Section>
261273
274+ <Section className="pb-12">
275+ <div className="bg-wall-100 w-full p-4 md:p-8 rounded-3xl flex flex-wrap items-center">
276+
277+ <div className="basis-full sm:basis-1/3 pb-4 sm:pb-0">
278+ <img className="rounded-xl w-72" src="https://storage.googleapis.com/media.urbit.org/assembly/assembly-thumb2.jpg" />
279+ </div>
280+ <div className="sm:basis-2/3 sm:pl-6 align-middle">
281+ <h2 className="text-2xl pb-2">Assembly 2022</h2 >
282+ <p className="max-w-prose pb-4">
283+ Watch talks and panels from last year's confluence in Miami.
284+ </p>
285+ <Link href="https://assembly.urbit.org" passHref>
286+ <a className="button-sm border-2 border-wall-600 text-wall-600 type-sm max-w-fit">
287+ Watch Now
288+ </a>
289+ </Link>
290+ </div>
291+ </div>
292+ </Section>
293+
262294 <Section narrow>
263295 <h2 className="pb-2">Urbit Monthly</h2>
264296 <p className="pb-8">Get monthly email updates on all things Urbit.</p>
@@ -266,6 +298,9 @@ export default function Home({
266298 <Contact emphasize />
267299 </Section>
268300
301+
302+
303+
269304 <Section narrow>
270305 <h2 className="pb-8">Social Media</h2>
271306 <p className="pb-2">
@@ -297,6 +332,8 @@ export default function Home({
297332 );
298333}
299334
335+
336+
300337export async function getStaticProps() {
301338 // Latest blog posts
302339 const posts = getAllPosts(
@@ -305,60 +342,31 @@ export async function getStaticProps() {
305342 "date"
306343 );
307344
308− // Pull all latest ecosystem information
309− const ecosystem = getAllPosts(
310− ["featured-1", "featured-2", "featured-3"],
311− "ecosystem/spotlight",
312− "date"
313− )[0];
314345
315− const marketplaces = getAllPosts(["title", "image", "slug"], "marketplaces");
316− const podcasts = getAllPosts(
317− ["title", "image", "date", "podcast", "slug"],
318− "podcasts",
319− "date"
320− );
321− const organizations = getAllPosts(
322− ["title", "image", "slug"],
323− "organizations"
346+ // Highlights
347+ const highlights = getAllPosts(
348+ ["title", "slug", "image", "url", "description"],
349+ "highlights"
324350 );
325− const applications = fs
326− .readdirSync(path.join(process.cwd(), "content/applications"), {
327− withFileTypes: true,
328− })
329− .filter((f) => f.isDirectory())
330− .map((dir) =>
331− getAllPosts(
332− ["title", "bgColor", "image", "slug", "description"],
333− `applications/${dir.name}`
334− )
335− .map((e) => ({ ...e, ship: dir.name }))
336− .flat()
337− )
338− .flat()
339− .sort((a, b) => {
340− const nameA = a.title.toLowerCase();
341− const nameB = b.title.toLowerCase();
342− return nameA < nameB ? -1 : 1;
343− });
344351
345− ["featured-1", "featured-2", "featured-3"].forEach((feat) => {
346− if (ecosystem?.[feat]) {
347− const matchedPost = [
348− ...applications.map((e) => ({ ...e, type: "Application" })),
349− ...organizations.map((e) => ({ ...e, type: "Organization" })),
350− ...podcasts.map((e) => ({ ...e, type: "Podcast" })),
351− ...marketplaces.map((e) => ({ ...e, type: "Marketplace" })),
352− ].filter((e) => e.title === ecosystem[feat].title)?.[0];
353− ecosystem[feat].image =
354− ecosystem[feat].image || matchedPost?.image || null;
355− ecosystem[feat].type = matchedPost?.type || "Podcast";
356− ecosystem[feat].matchedPost = matchedPost || null;
357− }
358− });
352+
353+ // Latest ecosystem report with matched post metadata
354+ const ecosystem = matchEcosystemPost(getAllPosts(
355+ ["date", "featured-1", "featured-2", "featured-3"],
356+ "ecosystem/spotlight",
357+ "date"
358+ )[0]);
359359
360360 // Latest grants
361− const grants = getAllPosts(["extra", "taxonomies"], "grants", "date");
361+ const basePath = path.join(process.cwd(), 'content/grants')
362+ const years = fs.readdirSync(basePath, { 'withFileTypes': true }).filter((f) => f.isDirectory());
363+ const grants = years.map((year) => {
364+ return getAllPosts(
365+ ["title", "slug", "date", "description", "extra", "taxonomies"],
366+ `grants/${year.name}`,
367+ "date"
368+ )
369+ }).flat();
362370
363371 const grantNumbers = {
364372 starsAwarded: Math.floor(
@@ -368,7 +376,8 @@ export async function getStaticProps() {
368376 0
369377 )
370378 ),
371− contributors: [...new Set(...[grants.map((e) => e.extra.assignee)])].length,
379+ contributors: [...new Set(...[grants.map((e) => e.extra.assignee).flat()])]
380+ .length,
372381 active: grants.filter(
373382 (e) =>
374383 !e.extra.canceled &&
@@ -412,6 +421,7 @@ export async function getStaticProps() {
412421 return {
413422 props: {
414423 posts,
424+ highlights,
415425 ecosystem,
416426 grantNumbers,
417427 events: happeningNow.concat(futureEvents).concat(pastEvents),
pages/organizations/[slug].js+4−3
@@ -40,7 +40,7 @@ export default function Organization({
4040 {applications.length > 0 && (
4141 <>
4242 <h3>Applications</h3>
43− <div className="grid grid-cols-2 md:grid-cols-4 gap-8 h-full w-full">
43+ <div className="grid grid-cols-2 md:grid-cols-4 gap-8 w-full">
4444 {applications.map((app) => (
4545 <Link href={`/applications/${app.ship}/${app.slug}`}>
4646 <div className="flex flex-col h-full w-full space-y-4 cursor-pointer">
@@ -52,7 +52,7 @@ export default function Organization({
5252 }}
5353 >
5454 {app.image && (
55− <img src={app.image} className="h-full w-full" />
55+ <img src={app.image} className="h-full w-full" style={{ aspectRatio: "1" }} />
5656 )}
5757 </div>
5858 <p className="text-center font-bold font-xl">{app.title}</p>
@@ -103,6 +103,7 @@ export async function getStaticProps({ params }) {
103103 "slug",
104104 "description",
105105 "URL",
106+ "twitter",
106107 "image",
107108 "ships",
108109 "group",
@@ -112,7 +113,7 @@ export async function getStaticProps({ params }) {
112113 );
113114
114115 const spotlights = getAllPosts(
115− ["title", "slug", "featured-1", "featured-2", "featured-3"],
116+ ["title", "heading", "slug", "featured-1", "featured-2", "featured-3"],
116117 "ecosystem/spotlight"
117118 ).filter(
118119 (e) =>
pages/overview/[[...slug]].js+1−1
@@ -28,7 +28,7 @@ export default function Overview({ posts, data, markdown, search }) {
2828 </Head>
2929 <IntraNav ourSite="https://urbit.org" search={search} />
3030 <SingleColumn>
31− <Header />
31+ <Header search={search} />
3232 <Section>
3333 <h1>Overview</h1>
3434 </Section>
pages/trial-over.jsnew file+35
@@ -0,0 +1,35 @@
1+import Head from "next/head";
2+import Link from "next/link";
3+import Meta from "../components/Meta";
4+import {
5+ Container,
6+ SingleColumn,
7+ Section,
8+ IntraNav,
9+} from "@urbit/foundation-design-system";
10+import Header from "../components/Header";
11+import Footer from "../components/Footer";
12+
13+export default function TrialOver(props) {
14+ const post = {
15+ title: "Trial Over",
16+ };
17+
18+
19+ return (
20+ <Container>
21+ <Head>
22+ <title>Trial Over • urbit.org</title>
23+ {Meta(post)}
24+ </Head>
25+ <IntraNav ourSite="https://urbit.org" search={props.search} />
26+ <div className="h-full w-full grow flex items-center justify-center flex-col px-8 md:px-0">
27+ <div className="w-fit">
28+ <h2>Your one day moon trial has concluded.</h2>
29+ <p className="my-12 max-w-prose">To keep using Urbit, we recommend getting a planet and setting up Urbit yourself or using a hosting provider.
30+ <Link href="/getting-started"><a className="button-lg bg-green-400 text-white max-w-fit my-12">Get Started</a></Link></p>
31+ </div>
32+ </div>
33+ </Container>
34+ );
35+}
pages/trial.jsnew file+129
@@ -0,0 +1,129 @@
1+import { useState, useEffect } from 'react';
2+import Head from "next/head";
3+import Link from 'next/link';
4+import Meta from "../components/Meta";
5+import {
6+ Container,
7+ SingleColumn,
8+ Section,
9+ IntraNav,
10+} from "@urbit/foundation-design-system";
11+import Header from "../components/Header";
12+import Footer from "../components/Footer";
13+import cn from 'classnames';
14+
15+const postReq = (path, params, method = 'post') => {
16+ const form = document.createElement('form');
17+ form.method = method;
18+ form.action = path;
19+
20+ for (const key in params) {
21+ if (params.hasOwnProperty(key)) {
22+ const hiddenField = document.createElement('input');
23+ hiddenField.type = 'hidden';
24+ hiddenField.name = key;
25+ hiddenField.value = params[key];
26+
27+ form.appendChild(hiddenField);
28+ }
29+ }
30+
31+ document.body.appendChild(form);
32+ form.submit();
33+}
34+
35+
36+
37+export default function Trial(props) {
38+ const post = {
39+ title: "Explore the Network",
40+ description: "Get one day of a complimentary hosted moon: a temporary Urbit ID."
41+ };
42+
43+ const [count, setCount] = useState(0)
44+
45+ useEffect(() => {
46+ fetch('https://api.shore.arvo.network/count', {
47+ method: 'GET',
48+ headers: { 'Content-Type': 'application/json' }
49+ })
50+ .then(res => res.json())
51+ .then(data => {
52+ setCount(data.count);
53+ });
54+ }, []);
55+
56+ const available = count > 0;
57+
58+ return (
59+ <Container>
60+ <Head>
61+ <title>{post.title} • urbit.org</title>
62+ {Meta(post)}
63+ </Head>
64+ <IntraNav ourSite="https://urbit.org" search={props.search} />
65+ <SingleColumn>
66+ <Header />
67+ <Section className="space-y-12">
68+ <h1>{post.title}</h1>
69+ {/* Flex between image and blurb, collapse to col on mobile */}
70+ <div className="flex flex-col items-center space-y-4 xl:space-y-0 xl:flex-row xl:space-x-4">
71+ <video className="max-w-md w-full min-w-0" autoPlay muted loop playsInline>
72+ <source
73+ src="https://storage.googleapis.com/media.urbit.org/site/explorethenetwork.webm"
74+ type="video/webm"
75+ />
76+ <source
77+ src="https://storage.googleapis.com/media.urbit.org/site/explorethenetwork.mp4"
78+ type="video/mp4"
79+ />
80+ </video>
81+ {/* Blurb is flexed to space button and copy */}
82+ <div className="flex-col flex space-y-4">
83+ <p>No downloads, no signup.</p>
84+ <p>Get <span className="font-bold">one day</span> of a complimentary hosted moon: a temporary Urbit ID.</p>
85+ {/* Button is flexed to space potential "try again later" copy */}
86+ <div className="xl:space-x-4 space-y-4 xl:space-y-0 self-center xl:self-start w-full flex-col xl:flex-row flex items-center">
87+ <a className={cn("p-8 button-lg text-white max-w-fit shrink-0", {
88+ "bg-green-400": available,
89+ "bg-wall-300 cursor-not-allowed": !available,
90+ })}
91+ onClick={(e) => {
92+ e.stopPropagation();
93+
94+ if (!available) {
95+ return
96+ }
97+
98+ fetch('https://api.shore.arvo.network/enter', {
99+ method: 'GET',
100+ headers: { 'Content-Type': 'application/json' }
101+ })
102+ .then(res => {
103+ if (!res.ok) {
104+ throw 'Error response from shore api.';
105+ }
106+ return res.json();
107+ })
108+ .then(data => {
109+ postReq(data.url + '/~/login', { password: data.code, redirect: '/' });
110+ })
111+ .catch(e => setCount(0));
112+ }}
113+ >
114+ {available ? 'Launch Moon' : 'No Moons Available'}
115+ </a>
116+ {!available && <p>Check back later!</p>}
117+ </div>
118+ </div>
119+ </div>
120+ <div className="max-w-prose flex flex-col space-y-4">
121+ <p>Moons are great for checking things out, but some groups may require a planet – a permanent Urbit ID.</p>
122+ <p>Learn more about <Link href="/getting-started/get-planet"><a>getting a planet</a></Link>.</p>
123+ </div>
124+ </Section>
125+ </SingleColumn>
126+ <Footer />
127+ </Container>
128+ );
129+}
pages/updates.js+1−1
@@ -26,7 +26,7 @@ export default function Updates({ posts, search }) {
2626 </Head>
2727 <IntraNav ourSite="https://urbit.org" search={search} />
2828 <SingleColumn>
29− <Header />
29+ <Header search={search} />
3030 <Section narrow>
3131 <div className="measure">
3232 <h1 className="pb-16">Updates</h1>
pages/updates/[slug].js+1−1
@@ -32,7 +32,7 @@ export default function Post({ post, markdown, search }) {
3232 </Head>
3333 <IntraNav ourSite="https://urbit.org" search={search} />
3434 <SingleColumn>
35− <Header />
35+ <Header search={search} />
3636 <Section short narrow>
3737 <h1>{post.title}</h1>
3838 {post.author ? (
public/images/android-chrome-192x192.pngnew file

Binary file not shown.

public/images/android-chrome-512x512.pngnew file

Binary file not shown.

public/images/apple-touch-icon.pngnew file

Binary file not shown.

public/images/developers-guide-logo.pngdeleted

Binary file not shown.

public/images/favicon-16x16.pngnew file

Binary file not shown.

public/images/favicon-32x32.pngnew file

Binary file not shown.

public/images/favicon.ico

Binary file not shown.

public/images/network-explorer-logo.pngdeleted

Binary file not shown.

public/images/operators-guide-logo.pngdeleted

Binary file not shown.

public/images/star-market-logo.pngdeleted

Binary file not shown.

tailwind.config.js+3−4
@@ -1,5 +1,5 @@
1+const { Markdown } = require("@urbit/foundation-design-system");
12const markdoc = require("@urbit/markdoc");
2−
33module.exports = {
44 presets: [require("@urbit/foundation-design-system/tailwind.config")],
55 content: {
@@ -11,9 +11,8 @@ module.exports = {
1111 ],
1212 transform: {
1313 md: (content) => {
14− const parsed = markdoc.parse(content);
15− const transform = markdoc.transform(parsed);
16− return markdoc.renderers.html(transform);
14+ const parsed = Markdown.parse({ post: { content } });
15+ return markdoc.renderers.html(parsed);
1716 },
1817 },
1918 },
vercel.json+56−13
@@ -4,16 +4,45 @@
44 },
55 "redirects": [
66 {
7− "source": "/getting-started/server",
8− "destination": "/getting-started/cli"
7+ "source": "/sponsordeck",
8+ "destination": "https://tinyurl.com/urbitsponsordeck",
9+ "permanent": true
10+ },
11+ {
12+ "source": "/uf-public",
13+ "destination": "https://tlon.network/lure/~halbex-palheb/uf-public",
14+ "permanent": false
15+ },
16+ {
17+ "source": "/groups/~wolref-podlex/foundation",
18+ "destination": "/groups/~halbex-palheb/uf-public"
19+ },
20+ {
21+ "source": "/getting-around",
22+ "destination": "/getting-started/getting-around"
23+ },
24+ {"source": "/getting-started/get-planet",
25+ "destination": "/getting-started/get-id"
26+ },
27+ {
28+ "source": "/docs/getting-started",
29+ "destination": "/getting-started"
30+ },
31+ {
32+ "source": "/getinvolved",
33+ "destination": "https://developers.urbit.org/blog/get-involved"
34+ },
35+ {
36+ "source": "/getting-started/server",
37+ "destination": "/getting-started/cli"
938 },
1039 {
11− "source": "/applications",
12− "destination": "/ecosystem?type=applications"
40+ "source": "/applications",
41+ "destination": "/ecosystem?type=applications"
1342 },
1443 {
15− "source": "/understanding-urbit/:path*",
16− "destination": "/overview/:path*"
44+ "source": "/understanding-urbit/:path*",
45+ "destination": "/overview/:path*"
1746 },
1847 {
1948 "source": "/blog/layer-2-guides",
@@ -23,9 +52,13 @@
2352 "source": "/grants/Faux",
2453 "destination": "/grants/faux"
2554 },
55+ {
56+ "source": "/using/id/layer-2-for-planets",
57+ "destination": "https://operators.urbit.org/manual/id/layer-2-for-planets"
58+ },
2659 {
2760 "source": "/getting-started/layer-2-for-planets",
28− "destination": "/using/id/layer-2-for-planets"
61+ "destination": "https://operators.urbit.org/manual/id/layer-2-for-planets"
2962 },
3063 {
3164 "source": "/guides/getting-an-urbit-id",
@@ -74,24 +107,34 @@
74107 "destination": "/getting-started",
75108 "permanent": true
76109 },
110+ {
111+ "source": "/using/install",
112+ "destination": "/getting-started/cli",
113+ "permanent": true
114+ },
77115 {
78116 "source": "/using/:path*",
79117 "destination": "https://operators.urbit.org/manual/:path",
80118 "permanent": true
81119 },
82120 {
83− "source": "/install/mac/latest",
84− "destination": "https://github.com/urbit/urbit/releases/latest/download/darwin.tgz",
121+ "source": "/install/linux-aarch64/latest",
122+ "destination": "https://github.com/urbit/vere/releases/latest/download/linux-aarch64.tgz",
123+ "permanent": true
124+ },
125+ {
126+ "source": "/install/linux-x86_64/latest",
127+ "destination": "https://github.com/urbit/vere/releases/latest/download/linux-x86_64.tgz",
85128 "permanent": true
86129 },
87130 {
88− "source": "/install/linux64/latest",
89− "destination": "https://github.com/urbit/urbit/releases/latest/download/linux64.tgz",
131+ "source": "/install/macos-aarch64/latest",
132+ "destination": "https://github.com/urbit/vere/releases/latest/download/macos-aarch64.tgz",
90133 "permanent": true
91134 },
92135 {
93− "source": "/install/windows/latest",
94− "destination": "http://github.com/urbit/urbit/releases/latest/download/windows.tgz",
136+ "source": "/install/macos-x86_64/latest",
137+ "destination": "https://github.com/urbit/vere/releases/latest/download/macos-x86_64.tgz",
95138 "permanent": true
96139 },
97140 {