diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ac33f9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+# Hugo artifacts
+.hugo_build.lock
+**/*.hugo/public
+**/_gen
\ No newline at end of file
diff --git a/deploy b/deploy
index e7e6bac..d26136b 100755
--- a/deploy
+++ b/deploy
@@ -1,2 +1,4 @@
#!/bin/bash
-rsync -avz --delete public/ a@trwnh.com:/srv/http/trwnh.com
+rsync -avz --delete public/ a@trwnh.com:/srv/http/trwnh.com \
+--exclude=wiki \
+--exclude=blog
diff --git a/hugo/.gitignore b/hugo/.gitignore
deleted file mode 100644
index fc795e5..0000000
--- a/hugo/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-**/public
-**/_gen
-.hugo_build.lock
\ No newline at end of file
diff --git a/hugo/archetypes/comments.md b/profile.hugo/archetypes/comments.md
similarity index 100%
rename from hugo/archetypes/comments.md
rename to profile.hugo/archetypes/comments.md
diff --git a/hugo/archetypes/notes.md b/profile.hugo/archetypes/notes.md
similarity index 100%
rename from hugo/archetypes/notes.md
rename to profile.hugo/archetypes/notes.md
diff --git a/hugo/assets/scripts/main.js b/profile.hugo/assets/scripts/main.js
similarity index 100%
rename from hugo/assets/scripts/main.js
rename to profile.hugo/assets/scripts/main.js
diff --git a/hugo/assets/scripts/search.js b/profile.hugo/assets/scripts/search.js
similarity index 100%
rename from hugo/assets/scripts/search.js
rename to profile.hugo/assets/scripts/search.js
diff --git a/hugo/assets/styles/common/base.scss b/profile.hugo/assets/styles/common/base.scss
similarity index 100%
rename from hugo/assets/styles/common/base.scss
rename to profile.hugo/assets/styles/common/base.scss
diff --git a/hugo/assets/styles/common/colors.scss b/profile.hugo/assets/styles/common/colors.scss
similarity index 100%
rename from hugo/assets/styles/common/colors.scss
rename to profile.hugo/assets/styles/common/colors.scss
diff --git a/hugo/assets/styles/common/content.scss b/profile.hugo/assets/styles/common/content.scss
similarity index 100%
rename from hugo/assets/styles/common/content.scss
rename to profile.hugo/assets/styles/common/content.scss
diff --git a/hugo/assets/styles/common/reset.scss b/profile.hugo/assets/styles/common/reset.scss
similarity index 100%
rename from hugo/assets/styles/common/reset.scss
rename to profile.hugo/assets/styles/common/reset.scss
diff --git a/hugo/assets/styles/features/headings.scss b/profile.hugo/assets/styles/features/headings.scss
similarity index 100%
rename from hugo/assets/styles/features/headings.scss
rename to profile.hugo/assets/styles/features/headings.scss
diff --git a/hugo/assets/styles/features/links.scss b/profile.hugo/assets/styles/features/links.scss
similarity index 100%
rename from hugo/assets/styles/features/links.scss
rename to profile.hugo/assets/styles/features/links.scss
diff --git a/hugo/assets/styles/features/search.scss b/profile.hugo/assets/styles/features/search.scss
similarity index 100%
rename from hugo/assets/styles/features/search.scss
rename to profile.hugo/assets/styles/features/search.scss
diff --git a/hugo/assets/styles/features/syntax-highlighting.scss b/profile.hugo/assets/styles/features/syntax-highlighting.scss
similarity index 100%
rename from hugo/assets/styles/features/syntax-highlighting.scss
rename to profile.hugo/assets/styles/features/syntax-highlighting.scss
diff --git a/hugo/assets/styles/layouts/index.scss b/profile.hugo/assets/styles/layouts/index.scss
similarity index 100%
rename from hugo/assets/styles/layouts/index.scss
rename to profile.hugo/assets/styles/layouts/index.scss
diff --git a/hugo/assets/styles/mixins/fab-unit.scss b/profile.hugo/assets/styles/mixins/fab-unit.scss
similarity index 100%
rename from hugo/assets/styles/mixins/fab-unit.scss
rename to profile.hugo/assets/styles/mixins/fab-unit.scss
diff --git a/hugo/assets/styles/mixins/shadow.scss b/profile.hugo/assets/styles/mixins/shadow.scss
similarity index 100%
rename from hugo/assets/styles/mixins/shadow.scss
rename to profile.hugo/assets/styles/mixins/shadow.scss
diff --git a/hugo/assets/styles/partials/h-card.scss b/profile.hugo/assets/styles/partials/h-card.scss
similarity index 100%
rename from hugo/assets/styles/partials/h-card.scss
rename to profile.hugo/assets/styles/partials/h-card.scss
diff --git a/hugo/assets/styles/print.scss b/profile.hugo/assets/styles/print.scss
similarity index 100%
rename from hugo/assets/styles/print.scss
rename to profile.hugo/assets/styles/print.scss
diff --git a/hugo/assets/styles/screen.scss b/profile.hugo/assets/styles/screen.scss
similarity index 100%
rename from hugo/assets/styles/screen.scss
rename to profile.hugo/assets/styles/screen.scss
diff --git a/hugo/content/_index.md b/profile.hugo/content/_index.md
similarity index 100%
rename from hugo/content/_index.md
rename to profile.hugo/content/_index.md
diff --git a/hugo/content/comments/_index.md b/profile.hugo/content/comments/_index.md
similarity index 100%
rename from hugo/content/comments/_index.md
rename to profile.hugo/content/comments/_index.md
diff --git a/hugo/content/comments/smartphones-arent-as-exciting-as-they-used-to-be/index.md b/profile.hugo/content/comments/smartphones-arent-as-exciting-as-they-used-to-be/index.md
similarity index 100%
rename from hugo/content/comments/smartphones-arent-as-exciting-as-they-used-to-be/index.md
rename to profile.hugo/content/comments/smartphones-arent-as-exciting-as-they-used-to-be/index.md
diff --git a/hugo/content/comments/status-as-a-service/index.md b/profile.hugo/content/comments/status-as-a-service/index.md
similarity index 100%
rename from hugo/content/comments/status-as-a-service/index.md
rename to profile.hugo/content/comments/status-as-a-service/index.md
diff --git a/hugo/content/notes/100040916509633482/index.md b/profile.hugo/content/notes/100040916509633482/index.md
similarity index 100%
rename from hugo/content/notes/100040916509633482/index.md
rename to profile.hugo/content/notes/100040916509633482/index.md
diff --git a/hugo/content/notes/108588546793521204/image.png b/profile.hugo/content/notes/108588546793521204/image.png
similarity index 100%
rename from hugo/content/notes/108588546793521204/image.png
rename to profile.hugo/content/notes/108588546793521204/image.png
diff --git a/hugo/content/notes/108588546793521204/index.md b/profile.hugo/content/notes/108588546793521204/index.md
similarity index 100%
rename from hugo/content/notes/108588546793521204/index.md
rename to profile.hugo/content/notes/108588546793521204/index.md
diff --git a/hugo/content/notes/99865201213509948/index.md b/profile.hugo/content/notes/99865201213509948/index.md
similarity index 100%
rename from hugo/content/notes/99865201213509948/index.md
rename to profile.hugo/content/notes/99865201213509948/index.md
diff --git a/hugo/content/notes/99918136079992108/index.md b/profile.hugo/content/notes/99918136079992108/index.md
similarity index 100%
rename from hugo/content/notes/99918136079992108/index.md
rename to profile.hugo/content/notes/99918136079992108/index.md
diff --git a/hugo/content/notes/99963583159619719/index.md b/profile.hugo/content/notes/99963583159619719/index.md
similarity index 100%
rename from hugo/content/notes/99963583159619719/index.md
rename to profile.hugo/content/notes/99963583159619719/index.md
diff --git a/hugo/content/notes/99987017261137486/index.md b/profile.hugo/content/notes/99987017261137486/index.md
similarity index 100%
rename from hugo/content/notes/99987017261137486/index.md
rename to profile.hugo/content/notes/99987017261137486/index.md
diff --git a/hugo/content/notes/99999893512052394/index.md b/profile.hugo/content/notes/99999893512052394/index.md
similarity index 100%
rename from hugo/content/notes/99999893512052394/index.md
rename to profile.hugo/content/notes/99999893512052394/index.md
diff --git a/hugo/content/notes/_index.md b/profile.hugo/content/notes/_index.md
similarity index 100%
rename from hugo/content/notes/_index.md
rename to profile.hugo/content/notes/_index.md
diff --git a/hugo/content/shares/99985686693364517/index.md b/profile.hugo/content/shares/99985686693364517/index.md
similarity index 100%
rename from hugo/content/shares/99985686693364517/index.md
rename to profile.hugo/content/shares/99985686693364517/index.md
diff --git a/hugo/hugo.toml b/profile.hugo/hugo.toml
similarity index 100%
rename from hugo/hugo.toml
rename to profile.hugo/hugo.toml
diff --git a/hugo/index.html b/profile.hugo/index.html
similarity index 100%
rename from hugo/index.html
rename to profile.hugo/index.html
diff --git a/hugo/layouts/_default/_markup/render-heading.html b/profile.hugo/layouts/_default/_markup/render-heading.html
similarity index 100%
rename from hugo/layouts/_default/_markup/render-heading.html
rename to profile.hugo/layouts/_default/_markup/render-heading.html
diff --git a/hugo/layouts/_default/baseof.html b/profile.hugo/layouts/_default/baseof.html
similarity index 100%
rename from hugo/layouts/_default/baseof.html
rename to profile.hugo/layouts/_default/baseof.html
diff --git a/hugo/layouts/_default/list.html b/profile.hugo/layouts/_default/list.html
similarity index 100%
rename from hugo/layouts/_default/list.html
rename to profile.hugo/layouts/_default/list.html
diff --git a/hugo/layouts/_default/single.html b/profile.hugo/layouts/_default/single.html
similarity index 100%
rename from hugo/layouts/_default/single.html
rename to profile.hugo/layouts/_default/single.html
diff --git a/hugo/layouts/comments/single.html b/profile.hugo/layouts/comments/single.html
similarity index 100%
rename from hugo/layouts/comments/single.html
rename to profile.hugo/layouts/comments/single.html
diff --git a/hugo/layouts/index.html b/profile.hugo/layouts/index.html
similarity index 100%
rename from hugo/layouts/index.html
rename to profile.hugo/layouts/index.html
diff --git a/hugo/layouts/index.json b/profile.hugo/layouts/index.json
similarity index 100%
rename from hugo/layouts/index.json
rename to profile.hugo/layouts/index.json
diff --git a/hugo/layouts/notes/single.html b/profile.hugo/layouts/notes/single.html
similarity index 100%
rename from hugo/layouts/notes/single.html
rename to profile.hugo/layouts/notes/single.html
diff --git a/hugo/layouts/partials/h-card.html b/profile.hugo/layouts/partials/h-card.html
similarity index 100%
rename from hugo/layouts/partials/h-card.html
rename to profile.hugo/layouts/partials/h-card.html
diff --git a/hugo/layouts/partials/seo.html b/profile.hugo/layouts/partials/seo.html
similarity index 100%
rename from hugo/layouts/partials/seo.html
rename to profile.hugo/layouts/partials/seo.html
diff --git a/hugo/layouts/partials/styles/external-links.html b/profile.hugo/layouts/partials/styles/external-links.html
similarity index 100%
rename from hugo/layouts/partials/styles/external-links.html
rename to profile.hugo/layouts/partials/styles/external-links.html
diff --git a/hugo/layouts/search/list.html b/profile.hugo/layouts/search/list.html
similarity index 100%
rename from hugo/layouts/search/list.html
rename to profile.hugo/layouts/search/list.html
diff --git a/hugo/static/avatar.png b/profile.hugo/static/avatar.png
similarity index 100%
rename from hugo/static/avatar.png
rename to profile.hugo/static/avatar.png
diff --git a/hugo/static/avatar2.png b/profile.hugo/static/avatar2.png
similarity index 100%
rename from hugo/static/avatar2.png
rename to profile.hugo/static/avatar2.png
diff --git a/hugo/static/header.jpg b/profile.hugo/static/header.jpg
similarity index 100%
rename from hugo/static/header.jpg
rename to profile.hugo/static/header.jpg
diff --git a/public/unstable/fedi-vs-web.html b/public/unstable/fedi-vs-web.html
index 8c6284c..db7420a 100644
--- a/public/unstable/fedi-vs-web.html
+++ b/public/unstable/fedi-vs-web.html
@@ -35,9 +35,11 @@
-
+
fedi vs web
+
on the distinction between social network and social web, where activitypub straddles both
+
published around
the disconnect between activitypub and the fediverse
diff --git a/threads.hugo/archetypes/default.md b/threads.hugo/archetypes/default.md
new file mode 100644
index 0000000..00e77bd
--- /dev/null
+++ b/threads.hugo/archetypes/default.md
@@ -0,0 +1,6 @@
+---
+title: "{{ replace .Name "-" " " | title }}"
+date: {{ .Date }}
+draft: true
+---
+
diff --git a/threads.hugo/assets/scripts/main.js b/threads.hugo/assets/scripts/main.js
new file mode 100644
index 0000000..b336f2a
--- /dev/null
+++ b/threads.hugo/assets/scripts/main.js
@@ -0,0 +1,15 @@
+/*
+Use a window's inner dimensions for viewport units.
+This fixes some mobile bugs
+*/
+
+var root = document.documentElement;
+let vh = window.innerHeight * 0.01;
+root.style.setProperty('--vh', `${vh}px`);
+
+// We listen to the resize event
+window.addEventListener('resize', () => {
+ // We execute the same script as before
+ let vh = window.innerHeight * 0.01;
+ root.style.setProperty('--vh', `${vh}px`);
+});
\ No newline at end of file
diff --git a/threads.hugo/assets/scripts/search.js b/threads.hugo/assets/scripts/search.js
new file mode 100644
index 0000000..e8dc3ef
--- /dev/null
+++ b/threads.hugo/assets/scripts/search.js
@@ -0,0 +1,225 @@
+/*
+tutorials used:
+- https://aaronluna.dev/blog/add-search-to-static-site-lunrjs-hugo-vanillajs/#codepen-with-final-code
+- https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/
+*/
+
+let pagesIndex, searchIndex
+const MAX_SUMMARY_LENGTH = 30
+const SENTENCE_BOUNDARY_REGEX = /\b\.\s/gm
+const WORD_REGEX = /\b(\w*)[\W|\s|\b]?/gm
+
+async function initSearch() {
+ try {
+ const response = await fetch("/index.json");
+ pagesIndex = await response.json();
+ searchIndex = lunr(function () {
+ this.field("title");
+ this.field("content");
+ this.ref("href");
+ pagesIndex.forEach((page) => this.add(page));
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ console.log("Search index initialized")
+ // Get the query parameter(s)
+ const params = new URLSearchParams(window.location.search)
+ const query = params.get('query')
+
+ // Perform a search if there is a query
+ if (query) {
+ // Retain the search input in the form when displaying results
+ document.getElementById('search-input').setAttribute('value', query)
+
+ // Update the list with results
+ console.log("search performed")
+ let results = searchSite(query)
+ renderSearchResults(query, results)
+ }
+}
+
+initSearch();
+
+function searchSite(query) {
+ const originalQuery = query;
+ query = getLunrSearchQuery(query);
+ let results = getSearchResults(query);
+ return results.length
+ ? results
+ : query !== originalQuery
+ ? getSearchResults(originalQuery)
+ : [];
+}
+
+function getLunrSearchQuery(query) {
+ const searchTerms = query.split(" ");
+ if (searchTerms.length === 1) {
+ return query;
+ }
+ query = "";
+ for (const term of searchTerms) {
+ query += `+${term} `;
+ }
+ return query.trim();
+}
+
+function getSearchResults(query) {
+ return searchIndex.search(query).flatMap((hit) => {
+ if (hit.ref == "undefined") return [];
+ let pageMatch = pagesIndex.filter((page) => page.href === hit.ref)[0];
+ pageMatch.score = hit.score;
+ return [pageMatch];
+ });
+}
+
+function renderSearchResults(query, results) {
+ clearSearchResults();
+ updateSearchResults(query, results);
+}
+
+function clearSearchResults() {
+ const results = document.querySelector("#search-results");
+ while (results.firstChild) results.removeChild(results.firstChild);
+}
+
+function updateSearchResults(query, results) {
+ document.getElementById("results-query").innerHTML = query;
+ document.querySelector("#search-results").innerHTML = results
+ .map(
+ (hit) => `
+
+ `
+ )
+ .join("");
+ const searchResultListItems = document.querySelectorAll("#search-results li");
+ document.getElementById("results-count").innerHTML = searchResultListItems.length;
+ document.getElementById("results-count-text").innerHTML = searchResultListItems.length === 1 ? "result" : "results";
+ // searchResultListItems.forEach(
+ // (li) => (li.firstElementChild.style.color = getColorForSearchResult(li.dataset.score))
+ // );
+}
+
+function createTitleBlurb(query, title) {
+ const searchQueryRegex = new RegExp(createQueryStringRegex(query), "gmi");
+ return title.replace(
+ searchQueryRegex,
+ "$&"
+ )
+}
+
+function createSearchResultBlurb(query, pageContent) {
+ const searchQueryRegex = new RegExp(createQueryStringRegex(query), "gmi");
+ const searchQueryHits = Array.from(
+ pageContent.matchAll(searchQueryRegex),
+ (m) => m.index
+ );
+ const sentenceBoundaries = Array.from(
+ pageContent.matchAll(SENTENCE_BOUNDARY_REGEX),
+ (m) => m.index
+ );
+ let searchResultText = "";
+ let lastEndOfSentence = 0;
+ for (const hitLocation of searchQueryHits) {
+ if (hitLocation > lastEndOfSentence) {
+ for (let i = 0; i < sentenceBoundaries.length; i++) {
+ if (sentenceBoundaries[i] > hitLocation) {
+ const startOfSentence = i > 0 ? sentenceBoundaries[i - 1] + 1 : 0;
+ const endOfSentence = sentenceBoundaries[i];
+ lastEndOfSentence = endOfSentence;
+ parsedSentence = pageContent.slice(startOfSentence, endOfSentence).trim();
+ searchResultText += `${parsedSentence} ... `;
+ break;
+ }
+ }
+ }
+ const searchResultWords = tokenize(searchResultText);
+ const pageBreakers = searchResultWords.filter((word) => word.length > 50);
+ if (pageBreakers.length > 0) {
+ searchResultText = fixPageBreakers(searchResultText, pageBreakers);
+ }
+ if (searchResultWords.length >= MAX_SUMMARY_LENGTH) break;
+ }
+ return ellipsize(searchResultText, MAX_SUMMARY_LENGTH).replace(
+ searchQueryRegex,
+ "$&"
+ );
+}
+
+function createQueryStringRegex(query) {
+ const searchTerms = query.split(" ");
+ if (searchTerms.length == 1) {
+ return query;
+ }
+ query = "";
+ for (const term of searchTerms) {
+ query += `${term}|`;
+ }
+ query = query.slice(0, -1);
+ return `(${query})`;
+}
+
+function tokenize(input) {
+ const wordMatches = Array.from(input.matchAll(WORD_REGEX), (m) => m);
+ return wordMatches.map((m) => ({
+ word: m[0],
+ start: m.index,
+ end: m.index + m[0].length,
+ length: m[0].length,
+ }));
+}
+
+function fixPageBreakers(input, largeWords) {
+ largeWords.forEach((word) => {
+ const chunked = chunkify(word.word, 20);
+ input = input.replace(word.word, chunked);
+ });
+ return input;
+}
+
+function chunkify(input, chunkSize) {
+ let output = "";
+ let totalChunks = (input.length / chunkSize) | 0;
+ let lastChunkIsUneven = input.length % chunkSize > 0;
+ if (lastChunkIsUneven) {
+ totalChunks += 1;
+ }
+ for (let i = 0; i < totalChunks; i++) {
+ let start = i * chunkSize;
+ let end = start + chunkSize;
+ if (lastChunkIsUneven && i === totalChunks - 1) {
+ end = input.length;
+ }
+ output += input.slice(start, end) + " ";
+ }
+ return output;
+}
+
+function ellipsize(input, maxLength) {
+ const words = tokenize(input);
+ if (words.length <= maxLength) {
+ return input;
+ }
+ return input.slice(0, words[maxLength].end) + "...";
+}
+
+if (!String.prototype.matchAll) {
+ String.prototype.matchAll = function (regex) {
+ "use strict";
+ function ensureFlag(flags, flag) {
+ return flags.includes(flag) ? flags : flags + flag;
+ }
+ function* matchAll(str, regex) {
+ const localCopy = new RegExp(regex, ensureFlag(regex.flags, "g"));
+ let match;
+ while ((match = localCopy.exec(str))) {
+ match.index = localCopy.lastIndex - match[0].length;
+ yield match;
+ }
+ }
+ return matchAll(this, regex);
+ };
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/common.scss b/threads.hugo/assets/styles/common.scss
new file mode 100644
index 0000000..dc1362c
--- /dev/null
+++ b/threads.hugo/assets/styles/common.scss
@@ -0,0 +1,16 @@
+@import 'common/reset.scss';
+@import 'common/variables.scss';
+
+@import 'layouts/_default/baseof.scss';
+@import 'layouts/partials/site-header.scss';
+@import 'layouts/partials/nav-header.scss';
+@import 'layouts/partials/site-footer.scss';
+
+@import 'layouts/index.scss';
+@import 'layouts/_default/list.scss';
+@import 'layouts/partials/paginator.scss';
+
+@import 'layouts/_default/single.scss';
+
+@import 'layouts/search/list.scss';
+@import 'layouts/partials/search/search-form.scss';
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/common/reset.scss b/threads.hugo/assets/styles/common/reset.scss
new file mode 100644
index 0000000..4721693
--- /dev/null
+++ b/threads.hugo/assets/styles/common/reset.scss
@@ -0,0 +1,5 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/common/variables.scss b/threads.hugo/assets/styles/common/variables.scss
new file mode 100644
index 0000000..e69de29
diff --git a/threads.hugo/assets/styles/layouts/_default/baseof.scss b/threads.hugo/assets/styles/layouts/_default/baseof.scss
new file mode 100644
index 0000000..9894048
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/_default/baseof.scss
@@ -0,0 +1,24 @@
+html {
+ font-family: sans-serif;
+ --container-width: 75rem;
+ --pad-x: 1rem;
+ @media (min-width: 30rem) {
+ --pad-x: 2rem;
+ }
+}
+body {
+ min-height: 100vh;
+ display: flex;
+ flex-flow: column;
+}
+main {
+ flex-grow: 1;
+}
+.section {
+ padding-inline: var(--pad-x, 1rem);
+ padding-block: var(--pad-y, 0rem);
+}
+.container {
+ max-width: var(--container-width, 60rem);
+ margin: 0 auto;
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/_default/list.scss b/threads.hugo/assets/styles/layouts/_default/list.scss
new file mode 100644
index 0000000..6bbb71d
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/_default/list.scss
@@ -0,0 +1,15 @@
+main._default-list {
+ display: flex;
+ flex-flow: column;
+ .pages {
+ flex-grow: 1;
+ display: flex;
+ padding-inline: var(--pad-x, 1rem);
+ .container {
+ flex-grow: 1;
+ .paginator {
+ height: 100%;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/_default/single.scss b/threads.hugo/assets/styles/layouts/_default/single.scss
new file mode 100644
index 0000000..6a6e0c7
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/_default/single.scss
@@ -0,0 +1,57 @@
+main._default-single {
+ .container {
+ display: grid;
+ gap: 1em;
+ @media (min-width: 40rem) {
+ grid-template-columns: 1fr minmax(auto, 80ch) 1fr;
+ > * {
+ grid-column: 2;
+ }
+ }
+ }
+ .page {
+ @media (min-width: 40rem) {
+ font-size: 1.25em;
+ }
+ }
+ .page-header {
+ hr {display: none;}
+ padding-block: 2em;
+ }
+ .page-title {
+ font-weight: bold;
+ font-size: 1.953em;
+ line-height: 1;
+ }
+ .page-summary {
+ max-inline-size: 65ch;
+ font-size: 1.25em;
+ line-height: 1.4;
+ font-style: italic;
+ }
+ .page-date {
+ font-size: 1em;
+ line-height: 1;
+ }
+ .page-author {
+ display: none;
+ }
+ .page-content {
+ padding-block: 2em;
+ blockquote {
+ padding-block: 1rem;
+ padding-inline-start: 1rem;
+ border-inline-start: 4px solid black;
+ background: #eee;
+ font-style: italic;
+ }
+ h1 {font-size: 1.953em}
+ h2 {font-size: 1.563em}
+ h3 {font-size: 1.25em}
+ h4 {font-size: 1em}
+ h1, h2, h3, h4 {margin-block-start: 1em}
+ ul, ol {
+ margin-inline-start: 1em;
+ }
+ }
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/index.scss b/threads.hugo/assets/styles/layouts/index.scss
new file mode 100644
index 0000000..4400cae
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/index.scss
@@ -0,0 +1,5 @@
+main.index {
+ .pages {
+ padding-inline: var(--pad-x, 1rem);
+ }
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/partials/nav-header.scss b/threads.hugo/assets/styles/layouts/partials/nav-header.scss
new file mode 100644
index 0000000..e69de29
diff --git a/threads.hugo/assets/styles/layouts/partials/paginator.scss b/threads.hugo/assets/styles/layouts/partials/paginator.scss
new file mode 100644
index 0000000..5bdcf2c
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/partials/paginator.scss
@@ -0,0 +1,74 @@
+.paginator {
+ display: flex;
+ flex-flow: column;
+ .list {
+ flex-grow: 1;
+ padding-block: 1em;
+ display: flex;
+ flex-flow: column;
+ gap: 1em;
+ .page {
+ width: 100%;
+ max-inline-size: 75ch;
+ a {
+ font-weight: bold;
+ }
+ span {
+ font-style: italic;
+ }
+ }
+ }
+ /* _internal/pagination.html */
+ .pagination {
+ list-style: none;
+ display: flex;
+ justify-content: space-between;
+ gap: 1em;
+ inline-size: fit-content;
+ max-inline-size: 100%;
+ }
+ .page-item {
+ &.disabled {
+
+ }
+ &.active {
+ font-weight: bold;
+ }
+ }
+ .page-link {
+ display: grid;
+ place-items: center;
+ font-size: 1em;
+ line-height: 1;
+ width: 3em;
+ height: 3em;
+ border-radius: 100em;
+ background: #eee;
+ text-decoration: none;
+ color: inherit;
+ transition: all 0.2s ease-in-out;
+ &:hover, &:active, &:focus {
+ background: #ace;
+ }
+ &[aria-label="First"],
+ &[aria-label="Previous"],
+ &[aria-label="Next"],
+ &[aria-label="Last"]
+ {
+ background: none;
+ &:hover, &:active, &:focus {
+ background: #ace;
+ }
+ }
+ }
+ .active .page-link {
+ background: #06f;
+ color: white;
+ }
+ .disabled .page-link {
+ background: none;
+ &:hover, &:active, &:focus {
+ background: none;
+ }
+ }
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/partials/search/search-form.scss b/threads.hugo/assets/styles/layouts/partials/search/search-form.scss
new file mode 100644
index 0000000..e69de29
diff --git a/threads.hugo/assets/styles/layouts/partials/site-footer.scss b/threads.hugo/assets/styles/layouts/partials/site-footer.scss
new file mode 100644
index 0000000..abd3879
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/partials/site-footer.scss
@@ -0,0 +1,5 @@
+.site-footer {
+ hr {display: none;}
+ padding-inline: var(--pad-x, 1rem);
+ padding-block: var(--pad-y, 1rem);
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/partials/site-header.scss b/threads.hugo/assets/styles/layouts/partials/site-header.scss
new file mode 100644
index 0000000..8e9ad8e
--- /dev/null
+++ b/threads.hugo/assets/styles/layouts/partials/site-header.scss
@@ -0,0 +1,26 @@
+.site-header {
+ padding-inline: var(--pad-x, 1rem);
+ padding-block: 1rem;
+ .container {
+
+ }
+ .hang-left {
+
+ }
+}
+.site-masthead {
+ text-decoration: none;
+ color: inherit;
+ &__image {
+
+ }
+}
+.site-title {
+
+}
+.scroll-margin {
+
+}
+#top {
+ --header-height: 4rem;
+}
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/layouts/search/list.scss b/threads.hugo/assets/styles/layouts/search/list.scss
new file mode 100644
index 0000000..e69de29
diff --git a/threads.hugo/assets/styles/print.scss b/threads.hugo/assets/styles/print.scss
new file mode 100644
index 0000000..fc8bd5a
--- /dev/null
+++ b/threads.hugo/assets/styles/print.scss
@@ -0,0 +1 @@
+@import 'common.scss';
\ No newline at end of file
diff --git a/threads.hugo/assets/styles/screen.scss b/threads.hugo/assets/styles/screen.scss
new file mode 100644
index 0000000..fc8bd5a
--- /dev/null
+++ b/threads.hugo/assets/styles/screen.scss
@@ -0,0 +1 @@
+@import 'common.scss';
\ No newline at end of file
diff --git a/threads.hugo/content/search/_index.md b/threads.hugo/content/search/_index.md
new file mode 100644
index 0000000..a7f481a
--- /dev/null
+++ b/threads.hugo/content/search/_index.md
@@ -0,0 +1,3 @@
++++
+title = "Search"
++++
\ No newline at end of file
diff --git a/threads.hugo/content/threads/_index.md b/threads.hugo/content/threads/_index.md
new file mode 100644
index 0000000..7fda3a3
--- /dev/null
+++ b/threads.hugo/content/threads/_index.md
@@ -0,0 +1,4 @@
++++
+title = "threads"
+summary = "originally posted as threads on social media"
++++
\ No newline at end of file
diff --git a/threads.hugo/content/threads/art-not-commodity/index.md b/threads.hugo/content/threads/art-not-commodity/index.md
new file mode 100644
index 0000000..b3bb94d
--- /dev/null
+++ b/threads.hugo/content/threads/art-not-commodity/index.md
@@ -0,0 +1,22 @@
++++
+title = "art is not a commodity"
+summary = "the real answer to making sure artists get paid is to actually pay them for the work they do, not to commodify what they produce"
+date = "2023-01-02T21:00:00-06:00"
+source = "https://mastodon.social/@trwnh/109623038871646811"
++++
+
+well opposing copyright isn't thievery, for a start. theft is the act of taking something without returning it, removing the original. digital information can be infinitely and perfectly copied.
+
+copyright enforcement is instead about giving certain parties exclusive monopolies on the spread of information. this gatekeeps culture and stifles free expression. in return for what? trying to sell access?
+
+note also this monopoly is only enforced via the threat of state violence.
+
+tangentially, there's also the fundamental inversion of value that occurs when artists try to fund themselves by selling art as if it were a commodity. the value in art is not necessarily in the final product alone but moreso in the creation of it.
+
+copyright asks us to perform creative labour for free, and hope to recoup our losses via the market (in which you must differentiate yourself from millions of functionally equivalent forms of art and entertainment -- good luck!)
+
+when you recognize this inversion of value, you recognize that the real answer to making sure artists get paid is to actually pay them for the work they do, not to commodify what they produce. things like commissions, patronage, public works funds, etc. all get to the root and heart of the issue.
+
+copyright is in effect more akin to theft -- theft from the public, from the commons, from culture. it benefits no one except those who "own" a lot of art -- the disneys of the world.
+
+in short: if you want artists to get paid, copyright is a really poor and ineffective way to do that. it just leads to big monopolies on art, at the expense of everyone else.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/blocked/index.md b/threads.hugo/content/threads/blocked/index.md
new file mode 100644
index 0000000..4a347b0
--- /dev/null
+++ b/threads.hugo/content/threads/blocked/index.md
@@ -0,0 +1,16 @@
++++
+title = "blocked"
+summary = "it's the finality of such a situation that bothers me the most; the knowledge that no amount of apology will matter, nor will any attempt at reconciliation even be seen"
+date = "2018-02-27T21:23:00-00:00"
+source = "https://mastodon.social/@trwnh/99599426061591957"
++++
+
+i wish i wasn't autistic because i'm really bad at reading social situations and here i am thinking i'm making light banter when instead i'm one post away from being blocked, before i can even apologize for misreading intent. end result is i just feel extremely shitty and like i'm terrible at being a human. i don't know how to vent my frustrations without it seeming personal, apparently
+
+also it's the finality of such a situation that bothers me the most; the knowledge that no amount of apology will matter, nor will any attempt at reconciliation even be seen. i've never been able to properly handle irreversibility. even though a block is technically reversible, it isn't practically. one mistake and it's over. and i *will* make those mistakes, because not only am i not perfect, but i'm hopelessly broken beyond repair, no matter how hard i try to learn how to socialize.
+
+and yet... i've not really been blocked much in my life (bar some democrats on birdsite who refuse to listen to left-poc) so i'm not totally insufferable or an absolute troll or a toxic personality. but of the more "misunderstood" blocks, one particular one comes to mind, because it was the only case where that person actually unblocked me years later. but that was much worse and what i said then was extremely insensitive. i wish i knew why they unblocked me. i'm too afraid to ask.
+
+sometimes i wonder why i care what total strangers think of me, and i don't know if it's better or worse to not care. it's not "shame" or "approval-seeking"; it's more of an intense urge to not be hated or begrudged.
+
+i guess that's a part of life, but it's not a part i'm comfortable with and i don't know if i ever will be.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/boktai-3/index.md b/threads.hugo/content/threads/boktai-3/index.md
new file mode 100644
index 0000000..b09ca22
--- /dev/null
+++ b/threads.hugo/content/threads/boktai-3/index.md
@@ -0,0 +1,10 @@
++++
+title = "boktai deserved better"
+summary = "where do you go to find quirky existentialist video games based on norse mythology and spaghetti westerns in the year of your lord 2018, you ask? you don't ;_;"
+date = "2018-04-15T19:54:00-00:00"
+source = "https://mastodon.social/@trwnh/99865201213509948"
++++
+
+i'm so emo that boktai 3 never launched outside of japan and also that boktai as a series is super dead and konami will never continue it and kojima probably can't/won't either due to copyright and the fact that it's been over 10 years since boktai ds and also kojima doesn't work for konami anymore UGH
+
+where do you go to find quirky existentialist video games based on norse mythology and spaghetti westerns in the year of your lord 2018, you ask? you don't ;_; #boktai
\ No newline at end of file
diff --git a/threads.hugo/content/threads/camera-gear/index.md b/threads.hugo/content/threads/camera-gear/index.md
new file mode 100644
index 0000000..5793393
--- /dev/null
+++ b/threads.hugo/content/threads/camera-gear/index.md
@@ -0,0 +1,23 @@
++++
+title = "don't worry about camera gear"
+summary = "I wouldn't recommend going for ILCs unless you have a dedicated use case [...] Once you've picked a niche, then the gear choices will result naturally."
+date = "2018-04-09T22:28:00-00:00"
+source = "https://mastodon.social/@trwnh/99831836537266861"
++++
+
+> On a less cranky note, I really want to get myself a nice digital camera. Any photographers out there with strong opinions on the matter?
+
+* What type of photos do you want to take?
+* What's your budget?
+* Do you want to deal with carrying multiple lenses / heavy bodies / etc?
+* What's the destination / use case for your photos?
+
+> all kinds. Budget isn't too much of an issue I can just save up longer. Multiple lenses are fun and I'll probably get a couple solid bags so not too put out about weight. Destination unknown.
+
+Well, I'm just going to say that if you don't have any idea at all, then that also means you can't really get a good answer. I wouldn't recommend going for ILCs unless you have a dedicated use case -- a compact or even a smartphone will do fine in most general cases. (I picked up a Sony RX100 M2 used for a few hundred bucks for my general shots.)
+
+Once you've picked a niche, then the gear choices will result naturally. As a general rule, spend more on glass than on bodies. Probably pick two telephoto lenses, one below ~70mm (down to 35mm or 24mm) and one above (up to about 200mm). Get a body with a sensor that's at least APS-C, and at least 12MP. A Sony a6000 or a6300 will be most versatile in the $750-1000 range (body only). You'll be spending an additional $400-$1000 for each quality lens you also pick up.
+
+> fair enough! I'm just doing my research right now so I appreciate the honesty.
+
+you're welcome :) it's really important to know what you're getting yourself into. a lot of people buy in way too early and stick with a kit lens because they didn't budget for lens -- and at that point, you might as well get a 1" compact, maybe even a Micro Four-Thirds like the Fujifilm X100 series if you can afford it.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/crossposters/index.md b/threads.hugo/content/threads/crossposters/index.md
new file mode 100644
index 0000000..b3d4fa1
--- /dev/null
+++ b/threads.hugo/content/threads/crossposters/index.md
@@ -0,0 +1,27 @@
++++
+title = "stop using crossposters"
+summary = "crossposts really don't engender organic engagement. They feel robotic and distant, largely because they're just that"
+date = "2017-11-26T02:20:00-06:00"
+source = [
+ "https://mastodon.social/@trwnh/99069749589979672",
+ "https://mastodon.social/@trwnh/99093644445157168",
+]
++++
+
+Stop using crossposters.
+
+Not to, like, force y'all to do something, but crossposters are self-defeating.
+
+It's far better to commit to a network rather than just make a carbon copy of yourself, because if you're posting exactly the same things, then what even is the point of having two networks?
+
+That's just unnecessarily redundant.
+
+I've been through this kinda rigmarole before when I tried using diaspora*, and the end result was that I completely abandoned it because I wasn't getting any meaningful interactions out of it compared to Twitter. Which was a shame, because I really liked diaspora*.
+
+The problem, of course, is that you will inevitably gravitate to whichever platform nets you more interaction. And crossposts really don't engender organic engagement. They feel robotic and distant, largely because they're just that
+
+## followup
+
+ugh i really hope crossposters don't slowly choke mastodon like they did to diaspora*
+
+if you're just crossposting everything you tweet on birdsite then what even is the point of making a mastodon account? that's glorified spam at worst, and a recipe for abandonment.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/deactivating-twitter/index.md b/threads.hugo/content/threads/deactivating-twitter/index.md
new file mode 100644
index 0000000..267ac3d
--- /dev/null
+++ b/threads.hugo/content/threads/deactivating-twitter/index.md
@@ -0,0 +1,18 @@
++++
+title = "nothing is truly forever"
+summary = "At some point, the final copy of any given data will be deleted. Or it will lose relevance. Or it will slip into obscurity."
+date = "2017-12-20T04:53:00-06:00"
+source = "https://mastodon.social/@trwnh/99206247716252048"
++++
+
+I just deactivated some really old accounts I had on birdsite, ones I'd stopped using years ago, but had left up as a sort of archive... The last relics of a bygone era, of a personality long dead... A mark of my former selves.
+
+Makes me think about the fact that nothing is truly forever, not even the internet and the data we think will last forever. At some point, the final copy of any given data will be deleted. Or it will lose relevance. Or it will slip into obscurity.
+
+Of course, it was already not as I had left it. Accounts I had once conversed with, deleted. Maybe some of those people met the same fate as their accounts. Who knows? A lot changes in three years.
+
+I can't back up the DMs that have been deleted, and the only copy of the replies are in the notification emails sent out to an inbox of a Gmail I'd long forgotten I had.
+
+Kind of a heavy feeling.
+
+The pictures will be gone in 30 days, but I can't help but think of the pictures lost forever from Twitpic or Yfrog or all of those other image hosts we all used before image hosting became a standard part of any web app.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/gun-culture-in-america/index.md b/threads.hugo/content/threads/gun-culture-in-america/index.md
new file mode 100644
index 0000000..24df00c
--- /dev/null
+++ b/threads.hugo/content/threads/gun-culture-in-america/index.md
@@ -0,0 +1,16 @@
++++
+title = "gun culture in america"
+summary = "a reactionary gun culture that perceives any attempt to curb it as an assault on their very identity"
+date = "2018-02-18T01:48:00-00:00"
+source = "https://mastodon.social/@trwnh/99543874314017409"
++++
+
+[...] although in fact, having a permanent standing army is less legally supported than gun ownership. constitutionally, the longest that congress can raise/fund an army is 2 years...
+
+the larger problem is that the culture around violence in america is absolutely toxic. the war of 1812 eroded the resistance to standing armies, the fugitive slave act of 1850 let the army act as a police force (only on the president's orders post-1878), in 1904 then-sec of war decided to station foreign troops, and in 1947 the dept of defense was formed to integrate the army into the govt. so militias aren't really a modern application of civilian defense, since the govt "took over" it.
+
+the biggest strain was actually when the black panthers decided to arm themselves for community self-defense; white supremacists were scared and started to push for gun control. not really the first gun-scare about black people; one of the arguments used during the dred scott case was that freed slaves couldn't be citizens because then they would legally be allowed to have guns.
+
+anyway, the NRA got taken over in the 1970s and converted from a marksmanship club to a political advocacy group. most of the people involved in this takeover decided to try another approach: take a hardline stance against any gun licensing (to better form white militias), and to strip the black community of its guns by criminalizing them, usually in conjunction with something else...that thing was the introduction of drugs and crack into black communities, which was criminalized once people got addicted to it. furthermore, gun possession drastically increased sentencing if convicted for drug offenses.
+
+the end result of all that is a reactionary gun culture that perceives any attempt to curb it as an assault on their very identity. and when you call them out on this, they deflect to something else like "mental illness" instead. in other words, the whole of american gun culture revolves around a false sense of freedom and safety, directly descended from white supremacy and toxic masculinity. people commit shootings out of a desire for fame or notoriety, or out of some perceived slight or grievance, largely based on ideological assumptions or entitlement.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/liberalism-and-trump/index.md b/threads.hugo/content/threads/liberalism-and-trump/index.md
new file mode 100644
index 0000000..fb9f0c8
--- /dev/null
+++ b/threads.hugo/content/threads/liberalism-and-trump/index.md
@@ -0,0 +1,63 @@
++++
+title = "liberalism and the rise of trump"
+summary = "there's some broad historical revisionism going on"
+date = "2018-01-14T10:35:00-00:00"
+source = [
+ "https://mastodon.social/@trwnh/99347736716090638",
+ "https://mastodon.social/@trwnh/99355650165263881",
+ "https://mastodon.social/@trwnh/99359516579847229",
+]
++++
+
+> some vox article about trump and liberalism
+
+eh, the article and its analysis has many issues with it
+
+- liberals aren't leftist
+- "reforms" were gained by strikes and protests, and it was anarchists and communists that led the struggle, not liberals
+- presents japanese internment as a "flaw" and not a great injustice
+- "whether the state has a responsibility to ensure a moral and socially desirable distribution of wealth" is irrelevant; welfare capitalism is still capitalism
+- you can't "correct" inequities by using the institutions that exist to propagate them; they are working as intended
+- "appealing to national pride" is fascist
+- anticommunism and mccarthyism WAS a major reactionary force, not a "purity test" by the left
+- the "strategy" you quoted has mostly been adopted by modern democrats in reaction to the rise of the "religious right" and other ratfucking attempts
+- the left was sabotaged by the fbi/cia
+- academia and technocracy aren't hallmarks of the left, either
+- "the hard work of liberal democratic politics" is, again, fruitless; the real issue is the complete defanging of the left by COINTELPRO and other initiatives; we need more haymarket squares and more may days, not endlessly begging politicians to not murder us
+- in short: yes a revolt is justified because america was founded on a fascist mythos of expansionism and exceptionalism
+
+i guess in conclusion i'd say that the "make america great again" point is really close to being on the money
+
+- the right = "make america great again" by national rebirth (one of the 3 main tenets of fascism)
+
+- the liberals = "america is already great" because we just need a bit of reform (and all horrors are simply aberrations)
+
+- the left = "america was never great" because it was explicitly founded as colonialist/imperialist/white-supremacist
+
+> [...]
+
+no, the extreme right wants a reactionary / openly fascist state that broadly uses violence to liquidate "degenerates" and other "undesirables". the state would be an even stronger force of national supremacy and authority than it already is.
+
+I guess the larger point I'm trying to make is that there's some broad historical revisionism going on, as an attempt to maintain authority. the idea of the nonviolent reformist solution to everything is not how most social revolutions work. this wasn't new to the 1960s; a much longer history of struggle against state violence exists, going back through all of america's colonial history
+
+i.e. as a nation, we've never "reformed" anything. radical abolitionists like john brown and the free soil party did more to end slavery than abraham lincoln ever did. the black panther party's community policing and radical housing and food programs were effective despite the fbi assassinating almost every single one of their leaders. fdr proclaimed to businesses that the new deal would "save capitalism" from the labor insurgency.
+
+the original article kind of glosses over all this in an attempt to paint trump as a new phenomenon and not the natural result of weak reformism utterly failing to uplift anyone. the central thesis is that the left failed because of a lack of bourgeois democracy, not because of pervasive sabotage efforts by the state like cointelpro
+
+> [...]
+
+i can see that. i grew up in alabama, and there's a rich history of communism down here. (Hammer and Hoe is a good book to read about this)
+
+the big switch from dem to GOP was an orchestrated effort to create an "identitarian" base of support. that is, by building up whiteness, by having politicians speak at churches and then funding preachers to spread political messages, etc... political parties hope to become functions of identity
+
+the alt-right is, in fact, the most modern outgrowth of the "identitarian" movement -- their politics are descended directly from the cynical traditionalism employed by the political right for over half a century. the people who grew up with this stuff eventually realized that the GOP was in the same boat as the dems; that military contracts and tax subsidies was their only real aim.
+
+but the real problem was that there was no opposition to this idea -- the fbi destroyed it with cointelpro and by assassinating anyone who became too influential.
+
+in this void, the liberals decided that they would try to minimize racial tensions rather than approach them head-on. the outgrowth of this was the dlc, which argued that the democrats had gone "too far to the left" with the new deal and great society legislation.
+
+if i had to pick a reason why much of the south doesn't like democrats, it would be that they just don't trust them. and their visible options have been restricted to the democrats and republicans, which is barely a choice at all. so some people vote gop because they think it'll trickle down or their taxes will go down. democrats are stuck in this perception that taxes and welfare are the only way forward, which doesn't really net much
+
+but way more people around me are nonpolitical. most people don't vote. they're too busy working at jobs that don't pay enough, and either voting hasn't done anything for them, or they CAN'T vote. the conversation is dominated by republicans who promise lower taxes, and by democrats who insult them. every time alabama comes up in national news it's always derisively, and people notice that stuff.
+
+i very much believe that if were any legitimate opposition to the established order, it would gain supporters in droves... but the state has prevented that from being viable by neutralizing opposition wherever it finds it. the FBI and CIA, as part of the "national security" apparatus, take the view that any subversion is harmful to national security. and i mean, they're kinda right. but that's the whole problem...
\ No newline at end of file
diff --git a/threads.hugo/content/threads/mastodon-as-twitter-do-over/index.md b/threads.hugo/content/threads/mastodon-as-twitter-do-over/index.md
new file mode 100644
index 0000000..2d76cb6
--- /dev/null
+++ b/threads.hugo/content/threads/mastodon-as-twitter-do-over/index.md
@@ -0,0 +1,112 @@
++++
+title = "mastodon as a twitter do-over"
+summary = "it would probably behoove us all to consider what mistakes twitter did and how we can avoid them."
+date = "2018-01-12T06:20:00-06:00"
+source = "https://mastodon.social/@trwnh/99336824877757248"
++++
+
+i wonder if it would be a good idea or a bad idea for mastodon to adopt a way to view popular hashtags
+
+pros: better discovery
+cons: going down the same road twitter did
+
+actually it's kind of interesting to think of mastodon as a twitter do-over, because it would probably behoove us all to consider what mistakes twitter did and how we can avoid them.
+
+## hashtags
+
+we're obviously past the age of posting toots via sms, so let's start with hashtags.
+
+* aug 2007: hashtags proposed by users as irc-channel metaphor
+* july 2009: twitter starts hyperlinking hashtags
+* 2010: twitter starts tracking "trending topics"
+
+but of course the mistakes that twitter did were to attempt to apply an algorithm to trends, meaning words and phrases could trend, and some hashtags could be filtered out or censored.
+
+## external media
+
+i think we're also past the point of external media hosting on twitpic/yfrog/etc, since internal media hosting has become far more widespread.
+
+## replying
+
+so the next thing is to look at replying and boosting statuses. starting with replies, because boosting is a bit more involved in analysis.
+
+* nov 2006: @ reply first used
+* may 2007: @replies adopted by twitter
+
+not much to say here. i guess i'd note that it makes a service more conversation than status-oriented, but that's about it? conversation is good
+
+## boosting
+
+now, about boosts...
+
+* apr 2007: "ReTweet" first used
+* jan 2008: "RT @user" first used
+* nov 2009: twitter adds retweet button
+
+so far so good. no need to clog up feeds with multiples of the same stuff. now here's the problem:
+
+* ~2009: people add comments to manual RTs
+* apr 2015: twitter adds quote tweets
+
+the biggest problems with quotes? they break context, and they lead to dogpiling. mastodon hasn't adopted quote toots, and probably never should.
+
+## conversation vs content
+
+just about the last thing to add at this point is twitter's attempt to transition from a conversational platform to a curated content provider, especially since 2015. that's bad.
+
+---
+
+## further discussion
+
+### replying to boosts
+
+> who replying to boosts mentions (on twitter, the reply tags both the person who retweeted and the person who posted, whereas on masto only the person who posted it gets the reply)
+>
+> the 2nd is more nebulous on how it _should_ work and i go back and forth on it tbh. like there's a lot of confusion on who someone is replying to on twitter
+>
+> but also i have had someone point out that by automatically tagging in the person who boosted it, it takes some responsibility off of the original poster to reply, which helps when you have posts getting more attention than you can handle
+
+when someone boosts a status, and you reply to that boosted status: are you replying to the original poster, or to the person who boosted it? that's the primary consideration there.
+
+twitter steamrolls everyone into the conversation, mastodon doesn't. i like the current behavior. if it's relevant to the person who boosted, i'll manually tag them in, perhaps as a sort of cc.
+
+### replies in home feeds
+
+> how replies to multiple people show up in your feed (generally this has worked by "if you follow one person who is mentioned in the reply it shows up")
+>
+> i think the 1st is annoying as fuck personally since i'm missing pieces of conversations, especially on mastodon with private posts (and this in turn can affect social ettiquette as people go "my friends are talking, i'll join in" without acknowledging the extra party privately posting)
+
+maybe break it down to decide who's relevant to each new status?
+
+if it's two people you both follow, then i guess it's not too bad to show you their conversation. but social etiquette might mean you shouldn't butt in, if it doesn't involve you. so there's a potential argument to be made to NOT show other people's conversations.
+
+on the other hand, it's generally more useful to follow your friend's conversations, because there is a high chance you'll be interested in them. this is what both twitter and mastodon do right now, and it's kind of taken for granted.
+
+when multiple people get involved, it gets a bit more tricky.
+
+possibility 1: only show the conversation if you follow everyone mentioned
+* still shows you friends, and allows friends to join in
+* if an external person joins the convo, the convo will continue in their mentions, but will not reach your timeline? it's debatable whether you would want to see ALL of the posts in the convo, or just the ones with your friends. could lead to abrupt disappearance of convos from your timeline.
+
+twitter's behavior is to show you the conversation if you follow the poster + the *first* mention. the assumption is that the post is targeted primarily at the first person mentioned. this may or may not be actually true, though. for completeness, it's assumed to be true.
+
+the only possible extension is to show ANY post from people you follow that mention ANYONE you also follow, which balloons pretty fast.
+
+i don't really have any thoughts about private accounts, because this isn't really an issue on mastodon. mastodon's idea of a locked account revolves around approving followers, but locked users can still post publicly. it's just impossible to see their followers-only toots without them approving you. so, post-level privacy sidesteps this issue; private accounts can still post publicly. much better than twitter's all-or-nothing approach.
+
+### private posts on mastodon
+
+> where private post issues arise is like:
+A posts privately, B replies, C replies to B
+>
+> I follow B and C so I see C's reply to B in my timeline, despite not being able to see the original context AT ALL because it's private
+
+so does C follow A? I would say that ideally, if the original post is privated to A-followers, then all replies are also privated to A-followers. I'm not entirely sure if this is indeed the case; I assume not, since you're asking about it.
+
+It seems easier to handle this for post-comment systems rather than post-reply systems, though the distinction between the two is rather arbitrary. Privacy in the first is encompassing; the second cascades.
+
+Due to specifics of how post-reply systems are implemented differently than post-comment systems (namely, in treating follow-ups as linked nodes rather than as children), I don't really know how best to propagate privacy attributes. It seems a bit strange, protocol-wise, to say that D's reply to C should be limited to A's followers. Perhaps this meshes back with the "multiple reply" issue above.
+
+So I guess the two-birds-one-stone solution is to only show you toots where you follow EVERYONE mentioned. But this has downsides, again as mentioned above... it stifles expansion of social circles. You'd have to go to someone's profile to see all their toots.
+
+Tweetdeck, before being bought out, used to have an option to show ALL replies from people you followed. Maybe bad for social etiquette to jump in with strangers, but it had a use case.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/misc.md b/threads.hugo/content/threads/misc.md
new file mode 100644
index 0000000..d9890da
--- /dev/null
+++ b/threads.hugo/content/threads/misc.md
@@ -0,0 +1,126 @@
++++
+title = "miscellaneous"
+summary = "stuff that didn't get its own post"
+draft = true
++++
+
+## https://mastodon.social/@trwnh/2264242 [i disagree with my past self somewhat]
+
+the profile model itself is dead [...] streams are the future and also they make way more sense
+
+## https://mastodon.social/@trwnh/99346993416792417
+
+not trying to sell ya, just fawning over how much i'm in love with xfce lol. it's just wild how microsoft decided everything would be 96dpi forever
+
+## https://mastodon.social/@trwnh/99557570047763492
+
+I wish there was a way to search up the title of old children's novels published before 2000 by plot summary or keywords... there are two different books that are on the tip of my mind, but whose titles I've long since forgotten. I doubt they've been digitized or republished, so they may be lost to time forever.
+
+## https://mastodon.social/@trwnh/99793615497112400
+
+hot take: mastodon should be more like email than it already is
+
+## https://mastodon.social/@trwnh/99899695933102322
+
+idk, the thing about e.g. python or ruby is that they focus a lot more on having clean syntax and being easy to understand.
+
+## https://mastodon.social/@trwnh/99937186098244775
+
+> I was under the impression that including "cisgender" in straight was controversial?
+
+I mean... the "controversy" is in how being transgender intersects with heterosexual / heteroromantic. some might argue that "trans people aren't straight" is transphobic because it denies their association with a binary gender. others disagree because being trans is inherently queer and deviates from the "norm" of society.
+
+## https://mastodon.social/@trwnh/99992566429566674
+
+In a way, it's like saying paper should never have been invented, and we should all have continued chiseling stone. That doesn't mean we should forget how to chisel stone; it just means that we shouldn't chisel new stones for *everything* -- paper will do fine in most cases.
+
+## https://mastodon.social/@trwnh/99997039233920487
+
+Hmm... I wouldn't say it's "security by obscurity" in a pejorative way -- there is a very real and very bad habit on Twitter of people "namesearching", or tracking specific terms so that they can jump into conversations.
+
+## https://mastodon.social/@trwnh/100009272925737468
+
+until maybe as late as 2016, twitter thought of itself as a "real time update news network and discussion platform" but now it thinks of itself as "consuming interests and topics"
+
+## https://mastodon.social/@trwnh/100053713095158984
+
+"anarchists are real enemies of marxism" is a self-fulfilling prophecy, fuck. treat someone as an enemy and they become your enemy.
+
+[...]
+
+concept: parody of that old relacore ad ("stress induces cortisol. relacore reduces cortisol.") but replace stress with twitter and relacore with mastodon
+
+## https://mastodon.social/@trwnh/100063071127017012
+
+people aren't always paid to disrupt, they may be doing it for personal reasons, ideology, etc. call them "trolls", it's accurate re: the practice of trolling for attention.
+
+## https://mastodon.social/@trwnh/100072299035734958
+
+it's a false assumption that crypto is trustless
+
+## https://mastodon.social/@trwnh/100085567120616255
+
+hard to say; what makes for a good discourse platform?
+
+## https://mastodon.social/@trwnh/100087757497941062
+
+there's a sort of fetishism around commodity goods from america throughout much of the middle east
+
+## https://mastodon.social/@trwnh/100097247421492501
+
+how to pick a mastodon server
+
+https://mastodon.social/@trwnh/100097303707813337
+
+servers shut down
+
+## https://mastodon.social/@trwnh/100103662264850023
+
+on some level i understand the ignorant desire for change, simply for change's sake [...]
+
+## https://mastodon.social/@trwnh/100105279502219193
+
+by "contradictions" of liberalism I mean things like
+- "job creation" when we have the technology to reduce work
+- "violence is bad" in the face of endless wars
+- "competition is good" when the natural end result is a monopoly
+
+https://mastodon.social/@trwnh/100105523140235220
+
+in general, the liberal/neoliberal split isn't very useful
+
+https://mastodon.social/@trwnh/100109839779411064
+
+"conservative" and "liberal" is a meaningless dichotomy
+
+## https://mastodon.social/@trwnh/100128470703676020
+
+all my friends are cute
+
+## https://mastodon.social/@trwnh/100131913998697452
+
+yeah, idk how i would have gotten off twitter if they hadn't made it extremely easy for me by breaking 3rd-party apps, shadowbanning me being blocked by too many TERFs, and refusing to ban fascists
+
+## https://mastodon.social/@trwnh/100141167073699878
+
+the chronological stuff was like 20% why i left twitter but the other 80% was the "reactionary sensationalist culture" as you put it
+
+## https://mastodon.social/@trwnh/100164745640244312
+
+i don't think it can ever be said that the state is acting in "self-defense". self-preservation? maybe. but self-defense is the domain of the oppressed. at the very least, merely surviving is a radical act. the long-term solution is to defang power and build alternative power.
+
+## some holodomor stuff in 4 subchains
+
+https://mastodon.social/@trwnh/100206391621628088
+https://mastodon.social/@trwnh/100206500940583286
+https://mastodon.social/@trwnh/100206609835191626
+https://mastodon.social/@trwnh/100206657397747867
+
+## https://mastodon.social/@trwnh/100234428636106449
+
+To use Twitter as the perennial example of bad design: say you want to indicate that something is bad. You could previously .@ to make it show up to your followers. Now, you quote tweet it, which exclusively shows it to your followers and not the participants of the old thread. But the third and harder option is to not do a public callout at all.
+
+## actor types idk not rly important
+
+https://mastodon.social/@trwnh/100240521462320522
+https://mastodon.social/@trwnh/100240555863529471
diff --git a/threads.hugo/content/threads/multiple-accounts/index.md b/threads.hugo/content/threads/multiple-accounts/index.md
new file mode 100644
index 0000000..afaaaa0
--- /dev/null
+++ b/threads.hugo/content/threads/multiple-accounts/index.md
@@ -0,0 +1,26 @@
++++
+title = "multiple accounts"
+summary = "why/when do people use multiple accounts, and what features can be implemented to reduce the friction in using just one account?"
+date = "2017-12-17T03:55:00-06:00"
+source = "https://mastodon.social/@trwnh/99189033326279405"
++++
+
+unrelated thought: been trying to hash out a solution to the "multiple accounts" issue with social media. namely: why/when do people use multiple accounts, and what features can be implemented to reduce the friction in using just one account? would appreciate feedback.
+
+off the top of my head:
+
+- private vs public accounts for trusted people (answered by privacy options on toots)
+- multiple interests (not really solved currently; perhaps implementing a tag system and letting people mute certain tags? Diaspora*-style aspects can get complicated)
+- separate identity (unsolvable and would be insecure to attempt with one account)
+
+wrt multiple interests, this really is my biggest pain point with ANY social media (coming from someone who has had like 15 birdsite accounts at once)
+
+perhaps not exactly tags, but having a category system like google+ would be nice and perhaps easiest to manage when considering tootboosts. but this also might complicate the issue? nevertheless, it could be optional (default behavior would be to boost to your profile, no categorization involved)
+
+the tag approach would be easiest for your own toots, but the categories wouldn't be too bad and would also allow for separating different boosts
+
+---
+
+## further discussion
+
+problem with diaspora*'s aspects (and by extension, Google+ circles which aped it) is that it's a bidirectional metaphor for a unidirectional relationship. you're supposed to pick who can see a post, but they might not even follow you. I would understand if instead it functioned and was advertised as a way to split your timeline into multiple timelines. As is, sharing to aspects/circles/etc. is needlessly confusing.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/necromancy/index.md b/threads.hugo/content/threads/necromancy/index.md
new file mode 100644
index 0000000..6451247
--- /dev/null
+++ b/threads.hugo/content/threads/necromancy/index.md
@@ -0,0 +1,14 @@
++++
+title = "necromancy"
+summary = "\"i saw the soul of my grandpa and he told me to keep working hard\" is almost mystic and folkloric, not really like \"i summoned the soul of my grandpa to give me encouragement\" and still one step removed from \"i inserted my grandpa's soul into a corpse / some bones to give him physical form\""
+date = "2018-04-12T07:31:00-00:00"
+source = "https://mastodon.social/@trwnh/99845293118930539"
++++
+
+i always have to stop and realize people don't mean actual necromancy (learning from the dead) and instead they mean some kinda pseudo-resurrection/reanimation thing in pop culture, haha
+
+> honestly, is divination through dead people's spirits any better?
+
+there's not as much stigma against it, compared to the physical. "i saw the soul of my grandpa and he told me to keep working hard" is almost mystic and folkloric, not really like "i summoned the soul of my grandpa to give me encouragement" and still one step removed from "i inserted my grandpa's soul into a corpse / some bones to give him physical form"
+
+it seems like souls are free to either stay in heaven or roam the land of the living, but giving them physical form is like playing god
\ No newline at end of file
diff --git a/threads.hugo/content/threads/neoliberalism/index.md b/threads.hugo/content/threads/neoliberalism/index.md
new file mode 100644
index 0000000..6e86462
--- /dev/null
+++ b/threads.hugo/content/threads/neoliberalism/index.md
@@ -0,0 +1,18 @@
++++
+title = "what is neoliberalism"
+summary = "in short, everything is a market and the experts should decide the best policies to help the market"
+date = "2018-03-14T08:10:00-00:00"
+source = "https://mastodon.social/@trwnh/99681239150233207"
++++
+
+> What is #neoliberalism? Is it a set defined thing or a term just like liberalism that could mean lots of different things to different people?
+
+kinda both? liberalism and neoliberalism have academic meanings, but get used differently by different people
+
+ie neoliberalism is just largely a return to liberalism; the idea that govt's role is to help business, that markets can be used as a force for good https://en.wikipedia.org/wiki/Neoliberalism
+
+maybe best exemplified by thatcher, reagan, greenspan, clinton; the support of "free trade" agreements like NAFTA and TPP or organizations like the IMF or WTO; opposition to people like ralph nader in the 1970s; concepts like "the marketplace of ideas" or "soft power"; in short, everything is a market and the experts should decide the best policies to help the market
+
+> [...]
+
+Neoliberalism seems like a big tent, but that's really only because it's ideologically sparse and lacks substance. Most of the Western world holds a neoliberal economic and domestic policy, and a neoconservative foreign policy.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/net-neutrality-repealed/index.md b/threads.hugo/content/threads/net-neutrality-repealed/index.md
new file mode 100644
index 0000000..fe3e583
--- /dev/null
+++ b/threads.hugo/content/threads/net-neutrality-repealed/index.md
@@ -0,0 +1,37 @@
++++
+title = "the day net neutrality was repealed"
+summary = "The Open Internet Order of 2015 which was just repealed was not too much. It was not enough."
+date = "2017-12-15T01:35:00-00:00"
+source = [
+ "https://mastodon.social/@trwnh/99175742733649566",
+ "https://mastodon.social/@trwnh/99175781630692764",
+]
++++
+
+> [...]
+
+Hey, remember when Comcast filtered P2P traffic including BitTorrent, Skype, and Spotify?
+
+Remember when AT&T blocked FaceTime and Google Voice on their network?
+
+Remember when Verizon throttled all video except mysteriously for their subsidiary go90?
+
+Because I remember.
+
+[Is it] a GOOD thing to have no legal authority to challenge ISPs when they pull the shit they clearly already did?
+
+Because that's literally all that happened in 2015, w/ forbearance
+
+In fact, Wheeler ONLY pursued the clauses of Title II that dealt with nondiscrimination (common carrier status), and didn't apply rate regulation or taxes or last-mile unbundling.
+
+He did this because Verizon successfully sued to prevent the FCC from using S706, and the judge told Wheeler he needed to reclassify as Title II.
+
+It should be obvious that the "free market" will not solve a problem created by the market. This is market failure, plain and simple.
+
+> [...]
+
+Which rules "allow" ISPs to monopolize regions? ISPs collude to not enter markets, renege on coverage expansion contracts, and prevent competition by claiming ownership of the backbone.
+
+In fact, I would support taking it out of the FCC's hands entirely, so that people like Pai can't take us backwards at their whims as the political winds change. The Open Internet Order of 2015 which was just repealed was not too much. It was not enough. There needs to be an act specifically protecting the free and open internet, and repealing the Telecommunications Act of 1996. Among other acts...
+
+So pardon me for thinking the decision today was not great. There's an overwhelming pile of evidence that Pai ignored wholesale in order to push an agenda that benefits the ISPs who simply want to profit more, users be damned.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/physical-bodies/index.md b/threads.hugo/content/threads/physical-bodies/index.md
new file mode 100644
index 0000000..9715b61
--- /dev/null
+++ b/threads.hugo/content/threads/physical-bodies/index.md
@@ -0,0 +1,6 @@
++++
+title = "physical bodies are so encumbering"
+summary = "it would be great to never again have to feel pain from a stomach too empty, or perhaps too full; to never have crusty eyes after sleeping too much, or perhaps too little; to never suffer from physiology that at best will decay, and at worst will actively punish us."
+date = "2018-05-09T14:42:00-00:00"
+source = "https://mastodon.social/@trwnh/99999872996282760"
++++
\ No newline at end of file
diff --git a/threads.hugo/content/threads/product-vs-profit/index.md b/threads.hugo/content/threads/product-vs-profit/index.md
new file mode 100644
index 0000000..d99fe9d
--- /dev/null
+++ b/threads.hugo/content/threads/product-vs-profit/index.md
@@ -0,0 +1,12 @@
++++
+title = "product vs profit"
+summary = "There will inevitably be a point where it is unprofitable to improve a product any further."
+date = "2017-12-22T12:06:00-00:00"
+source = "https://mastodon.social/@trwnh/99217860566004390"
++++
+
+> maybe providing useful products turns a profit hmmm...
+
+Only to a certain extent. There will inevitably be a point where it is unprofitable to improve a product any further.
+
+i.e., if Apple's primary goal was to make useful products, it would make choices that result in a better product even if it was slightly more expensive. But their primary goal is profit, as it is for every corporation under capitalism. Making better stuff is unprofitable.
\ No newline at end of file
diff --git a/threads.hugo/content/threads/reading-theory/index.md b/threads.hugo/content/threads/reading-theory/index.md
new file mode 100644
index 0000000..09a9c67
--- /dev/null
+++ b/threads.hugo/content/threads/reading-theory/index.md
@@ -0,0 +1,10 @@
++++
+title = "reading theory"
+summary = "the point of reading theory is to see what ideas other people already came up with, so you don't have to spend time formulating them yourselves."
+date = "2018-01-27T08:44:00-00:00"
+source = "https://mastodon.social/@trwnh/99420908783601966"
++++
+
+the point of reading theory is to see what ideas other people already came up with, so you don't have to spend time formulating them yourselves. like... you start out with political beliefs and experiences, but they can always be solidified if you have a framework to contextualize them.
+
+and that doesn't really require discussion unless you want to or need more understanding, and it doesn't require organizing if you're not capable of it, and it really doesn't require voting since many people can't vote and many voting systems are designed to minimize choice. it feels wrong to say one *can't* be politically engaged unless one does these things
\ No newline at end of file
diff --git a/threads.hugo/content/threads/responsive-web-design/index.md b/threads.hugo/content/threads/responsive-web-design/index.md
new file mode 100644
index 0000000..6f7ace5
--- /dev/null
+++ b/threads.hugo/content/threads/responsive-web-design/index.md
@@ -0,0 +1,12 @@
++++
+title = "fully responsive web design"
+summary = "my pipe dream is to redesign my website to be fully responsive -- not across mere pixel widths, but by aspect ratio and overall size"
+date = "2018-04-22T15:42:00-00:00"
+source = "https://mastodon.social/@trwnh/99903847448978099"
++++
+
+my pipe dream is to redesign my website to be fully responsive -- not across mere pixel widths, but by aspect ratio and overall size.
+
+does anyone consider what their website looks like when it's fullscreened across one of those samsung 3840x1080 monitors? probably not, and why would you?
+
+but i do
\ No newline at end of file
diff --git a/threads.hugo/content/threads/smartphones-and-capitalism/index.md b/threads.hugo/content/threads/smartphones-and-capitalism/index.md
new file mode 100644
index 0000000..e8a0a0c
--- /dev/null
+++ b/threads.hugo/content/threads/smartphones-and-capitalism/index.md
@@ -0,0 +1,26 @@
++++
+title = "i hate the smartphone market"
+summary = "profit motives means that the entire market has abandoned me"
+date = "2018-05-07T08:13:00-00:00"
+source = "https://mastodon.social/@trwnh/99987017261137486"
++++
+
+tbh like 90% of my day-to-day angst against capitalism is from how shit the smartphone market has become. if capitalism is so great then where the fuck is my <70mm-wide phone with a removable battery? fucking profit motives means that the entire market has abandoned me. I haven't been satisfied with any phone since 2010. hell, I'd buy an updated Nexus One with newer, more efficient internals.
+
+"capitalism brought you your smartphone!" yeah, and that phone /fucking sucks/.
+
+I wish I could build my own phone or have one built to spec, but alas, I do not own a machining and assembly factory, and I don't have the requisite circuitry knowledge... if only I could, I dunno, *cooperate* with some like-minded people, and we had *public ownership of those factories*... :thaenkin:
+
+> do you know about this company? https://www.fairphone.com/en/ . They do their best to source all their components ethically, and work with worker's organisations in the countries they are producing phones in. The fair phone also comes with root access by default, so you can install your own ROM if you want.
+
+yeah; they're well-intentioned but still restricted to operating within the confines of capitalism. and it's still too big of a phone for my liking, personally
+
+like, i'm using a sony xperia x compact right now because it's 4.6" and fits in one hand. the snapdragon 650 means the battery is *decent*, but for how long? i got it lightly used in september, and now it's may and the battery is starting to heat up and degrade after 8 months of heavy usage and all those recharge cycles.
+
+> my fair phone 1 is still working nicely after 3 years or so [...]
+
+I feel like the same could be said about several more devices from 2013 than could be said today. my mom is still using a Nexus 7 2013 tablet just fine. our Nexus 5 could have lasted until now, if she hadn't broken it accidentally in a fit of rage. my htc one m7 is still close to the "ideal" device for me, except its battery has long gone to shit and is a nightmare to replace.
+
+I wish there were like 400 more fairphones, because just 1 is too limited to accomplish much for my case. and part of why there's only 1, I imagine, is because they can't be profiting too much; they still rely on profit, don't they? It's not "sustainable" for companies to provide services at-cost under capitalism.
+
+[...] it's extremely hard to "build it yourself" at sufficient scale to make a difference... and even then, you're bound by the laws of capital. you need to make money to survive, so at-cost operation is not viable without external funding
\ No newline at end of file
diff --git a/threads.hugo/content/threads/syndicalism-is-dead/index.md b/threads.hugo/content/threads/syndicalism-is-dead/index.md
new file mode 100644
index 0000000..1cb87c8
--- /dev/null
+++ b/threads.hugo/content/threads/syndicalism-is-dead/index.md
@@ -0,0 +1,18 @@
++++
+title = "syndicalism in the 21st century"
+summary = "syndicalism is dead because the labor industry is dead. it's been replaced by the service industry today"
+date = "2018-01-03T19:42:00-06:00"
+source = "https://mastodon.social/@trwnh/99289017794408922"
++++
+
+> Is syndicalism relevant in the 21st century?
+
+there's a reason why crimethinc call themselves an "ex"-worker collective. syndicalism is dead because the labor industry is dead. it's been replaced by the service industry today. factories are either on the decline or they're being exported. so i guess in that sense, syndicalism can still live in china, or wherever else production is a significant part of the economy so that a general strike can bring it to its knees
+
+or, alternatively, i suppose all food servers and retail employees could go on strike but the capitalist powers have created an abundance of unemployed people ready to bust that strike
+
+i see it as much more likely that the masses will revolt wholesale, before any trade-unionist path could ever make itself viable again
+
+very likely within the next 20 years, and almost certainly by the end of the century. too many crises are coming to a head "by 2040, 2050, 2080, 2100" etc. natural and anthropogenic conflicts will arise more easily than ever before
+
+to be clear: organizing workers is still the most effective way forward; unionism can help but isn't an effective avenue for change anymore compared to agitation. but there's only so much we can gain by lobbying for labor standards; we need to push for fundamental transformation of the entirety of class relations
\ No newline at end of file
diff --git a/threads.hugo/content/threads/the-web-not-only-for-profit/index.md b/threads.hugo/content/threads/the-web-not-only-for-profit/index.md
new file mode 100644
index 0000000..af3772f
--- /dev/null
+++ b/threads.hugo/content/threads/the-web-not-only-for-profit/index.md
@@ -0,0 +1,15 @@
++++
+title = "the web is not only for profit"
+summary = "i just want to find some inspiration on how to express myself, not market myself"
+date = "2023-01-03T01:58:00-06:00"
+source = "https://mastodon.social/@trwnh/109624210338690804"
++++
+
+it's funny how a lot of help articles can be boiled down to one of
+
+a) it's really easy, just give us money
+b) it's really hard, so give us money
+
+people act like the only worthwhile use case of the web is financial gain. no one has any tips or hints on how to make a personal website, it's always "build your brand" or "showcase your portfolio" or some other transparently profit-motivated initiative. everyone is always talking about the sales funnel or the call to action or whatever. it's just *assumed* you are also like this.
+
+i just want to find some inspiration on how to express myself, not market myself
\ No newline at end of file
diff --git a/threads.hugo/content/threads/ubi/index.md b/threads.hugo/content/threads/ubi/index.md
new file mode 100644
index 0000000..0024f8a
--- /dev/null
+++ b/threads.hugo/content/threads/ubi/index.md
@@ -0,0 +1,10 @@
++++
+title = "the problem with universal basic income"
+summary = "market forces on basic needs need to be abolished"
+date = "2018-03-16T02:00:00-00:00"
+source = "https://mastodon.social/@trwnh/99691112300163044"
++++
+
+my only problem with UBI is if you're going to guarantee a basic income then why not just guarantee the basics and cut down on the bureacracy? also you can't just give everyone a lump sum of money and not expect a market to react to that flood of monetary supply -- market forces on basic needs need to be abolished
+
+tldr UBI is a bandage on capitalism in the same way the New Deal was, but even less accountable
\ No newline at end of file
diff --git a/threads.hugo/content/threads/voluntarism/index.md b/threads.hugo/content/threads/voluntarism/index.md
new file mode 100644
index 0000000..aeb6003
--- /dev/null
+++ b/threads.hugo/content/threads/voluntarism/index.md
@@ -0,0 +1,12 @@
++++
+title = "voluntarism vs socialism"
+summary = "If two people are inequal, then they can never come to a voluntary agreement -- the power of one will coerce the other"
+date = "2018-04-06T23:19:00-00:00"
+source = "https://mastodon.social/@trwnh/99815047195372515"
++++
+
+My point is that pursuing pure voluntarism as an ideology (and not simply an ideal) tends to ignore the realities of power imbalances. If two people are inequal, then they can never come to a voluntary agreement -- the power of one will coerce the other, even if subconsciously.
+
+Consider whether one can "voluntarily" become a slave. Or, more relevant today, consider the wage labor system. Is it truly "voluntary" if your food, shelter, and very survival depends on such a "voluntary" arrangement?
+
+The cold reality is that voluntarism is merely idealism so long as any social class or hierarchy exists. Maybe some prefigurative politics are necessary, but you have to push for progress without 100% support or you'll wait forever.
\ No newline at end of file
diff --git a/threads.hugo/deploy b/threads.hugo/deploy
new file mode 100755
index 0000000..19054ac
--- /dev/null
+++ b/threads.hugo/deploy
@@ -0,0 +1,4 @@
+#!/bin/bash
+rm -r public/
+hugo
+rsync -avz --delete public/ a@trwnh.com:/srv/http/trwnh.com/blog
diff --git a/threads.hugo/hugo.toml b/threads.hugo/hugo.toml
new file mode 100644
index 0000000..f409f7e
--- /dev/null
+++ b/threads.hugo/hugo.toml
@@ -0,0 +1,6 @@
+baseURL = 'https://trwnh.com/blog/'
+languageCode = 'en-us'
+title = 'a blog'
+
+[pagination]
+pagerSize = 100
diff --git a/threads.hugo/layouts/_default/baseof.html b/threads.hugo/layouts/_default/baseof.html
new file mode 100644
index 0000000..70df867
--- /dev/null
+++ b/threads.hugo/layouts/_default/baseof.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+{{- /* print layout */ -}}
+{{- $print := resources.Get "styles/print.scss" | toCSS | minify | fingerprint }}
+
+
+{{- /* web layout */ -}}
+{{- $theme := resources.Get "styles/screen.scss" | toCSS }}
+{{- with resources.Get "styles/custom.scss" }}
+{{- $custom := . | toCSS }}
+{{- $screen := slice $theme $custom | resources.Concat "assets/screen.css" | minify | fingerprint }}
+
+{{- else }}
+{{- $screen := $theme | minify | fingerprint }}
+
+{{- end }}
+
+{{- /* scripts */ -}}
+{{- $theme := resources.Get "scripts/main.js" | js.Build "script.js" | minify | fingerprint }}
+{{ with resources.Get "scripts/custom.js" }}
+{{ $custom := . }}
+{{ $script := slice $theme $custom | resources.Concat "assets/main.js" | js.Build "script.js" | minify | fingerprint}}
+
+{{ else }}
+{{ $script := $theme | js.Build "script.js" | minify | fingerprint}}
+
+{{ end }}
+
+{{ partial "seo.html" . -}}
+{{- block "head" . -}}
+{{ end }}
+
+
+{{ partial "site-header.html" . }}
+{{ block "main" . }}
+{{ end }}
+{{ partial "site-footer.html" . }}
+
+
\ No newline at end of file
diff --git a/threads.hugo/layouts/_default/list.html b/threads.hugo/layouts/_default/list.html
new file mode 100644
index 0000000..9b91749
--- /dev/null
+++ b/threads.hugo/layouts/_default/list.html
@@ -0,0 +1,14 @@
+{{ define "main" }}
+
+
+
, purely for constraining width.
+*/
+.section {
+ padding: 2em 0; /* we apply a vertical padding only to sections */
+ box-sizing: border-box;
+}
+.container {
+ box-sizing: border-box;
+ width: 100%;
+ max-width: var(--site-max-width);
+ margin: 0 auto;
+ padding: 0 1em; /* and we apply a horizontal padding only to containers */
+}
+
+/* Ensure consistent colors for text selection and element focus */
+::selection {
+ background: var(--primary-accent);
+ color: var(--primary-accent-text);
+}
+
+*:focus {
+ border-radius: 2px;
+ text-decoration: none;
+ outline: 1px dashed var(--ui-text);
+ outline-offset: 4px;
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/common/colors.scss b/wiki.hugo/assets/styles/common/colors.scss
new file mode 100644
index 0000000..1b6a213
--- /dev/null
+++ b/wiki.hugo/assets/styles/common/colors.scss
@@ -0,0 +1,35 @@
+:root {
+ --link-color: #3371cf;
+ --link-visited: #594288;
+
+ --primary-accent: rgb(0, 123, 255);
+ --primary-accent-transparent: rgba(0, 123, 255,0.25);
+ --primary-accent-text: #fff;
+
+ --ui-background: #fff;
+ --ui-text: #111;
+ --ui-text-muted: #666;
+ --ui-text-bold: #000;
+
+ --ui-overlay: #ddd;
+ --ui-overlay-text: var(--ui-text);
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --link-color: #8fb1df;
+ --link-visited: #a089d4;
+
+ --primary-accent: rgb(0, 123, 255);
+ --primary-accent-transparent: rgba(64, 156, 255, 0.45);
+ --primary-accent-text: #fff;
+
+ --ui-background: #212121;
+ --ui-text: #eee;
+ --ui-text-muted: #999;
+ --ui-text-bold: #fff;
+
+ --ui-overlay: #333;
+ --ui-overlay-text: var(--ui-text);
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/common/content.scss b/wiki.hugo/assets/styles/common/content.scss
new file mode 100644
index 0000000..55f43f7
--- /dev/null
+++ b/wiki.hugo/assets/styles/common/content.scss
@@ -0,0 +1,207 @@
+.content {
+ /* text */
+ p, li {max-inline-size: 80ch;}
+ h1 {font-size: 1.8em}
+ h2 {font-size: 1.6em}
+ h3 {font-size: 1.423em}
+ h4 {font-size: 1.265em}
+ h5 {font-size: 1.125em}
+ h6 {font-size: 1em}
+ h1, h2, h3, h4, h5, h6 {
+ line-height: 1.2;
+ margin-block-start: 2rem;
+ margin-block-end: 1rem;
+ font-weight: 700;
+ }
+ p {
+ line-height: 2;
+ margin-block-end: 1em;
+ }
+ a {
+ word-wrap: break-word;
+ }
+ /* semantics */
+ em {font-style: italic}
+ strong {font-weight: 700}
+ /* text formatting */
+ --script-size: 0.65em;
+ sup {
+ position: relative;
+ font-size: var(--script-size);
+ inset-block-start: -1em;
+ }
+ sub {
+ position: relative;
+ font-size: var(--script-size);
+ }
+ @supports #{'selector\(:has(kbd))'} {
+ /* style individual keys only (for the innermost element) */
+ kbd kbd,
+ kbd:not(:has(kbd)) {
+ font-family: monospace;
+ padding: 0.25em;
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ }
+ }
+ @supports not #{'selector\(:has(kbd))'} {
+ /* style the entire key sequence */
+ kbd {
+ font-family: monospace;
+ padding: 0.25em;
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ }
+ /* and prevent double-styling for nested keys */
+ kbd kbd {
+ background: none;
+ }
+ }
+ mark {
+ background: var(--primary-accent-transparent);
+ color: var(--ui-text);
+ --pad-x-highlight: 0.125em;
+ padding-inline-start: var(--pad-x-highlight);
+ padding-inline-end: var(--pad-x-highlight);
+ }
+ abbr[title]:after {
+ content: '?';
+ font-size: var(--script-size);
+ color: var(--ui-text-muted);
+ }
+ /* lists */
+ ul, ol {
+ padding-inline-start: 0;
+ margin-block: 1em;
+ position: relative;
+ }
+ ul {list-style: disc;}
+ ol {list-style: decimal;}
+ li {margin-block-end: 1em; line-height: 1.4; margin-inline-start: 1em;}
+ dl {margin-block: 1em; line-height: 1.4;}
+ dt {font-weight: 700;}
+ dd {margin-inline-start: 1em;}
+ /* block elements */
+ img {
+ width: 100%;
+ margin-block-end: 1em;
+ }
+ blockquote {
+ font-style: italic;
+ font-size: 1em;
+ margin: 1em 0;
+ border-inline-start: 0.25rem solid var(--ui-text-bold);
+ padding-inline-start: 0.75em;
+ line-height: 1.4;
+ }
+ pre {
+ font-family: monospace;
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ padding: 1em;
+ line-height: 1.4;
+ overflow-inline: auto;
+ white-space: pre;
+ display: grid;
+ tab-size: 3;
+ margin-block-end: 1em;
+ }
+ code {
+ font-family: monospace;
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ padding: 0.25rem;
+ }
+ :not(.highlight) > pre {
+ line-height: 1.5;
+ background: var(--ui-overlay);
+ padding: 1em;
+ }
+ pre code {
+ background: inherit;
+ padding: 0;
+ }
+ .highlight pre {
+ padding-block: 1em;
+ }
+ /* figures */
+ figure {
+ margin-block-end: 1em;
+ }
+ figure img {
+ width: 100%;
+ margin-block-end: -0.125em;
+ }
+ figcaption {
+ background: #212121;
+ color: white;
+ font-style: italic;
+ padding: 1em;
+ font-size: 0.8em;
+ line-height: 1.2;
+ }
+ /* tables */
+ table {text-align: center;}
+ thead {
+ font-weight: 700;
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ }
+ th, td {
+ border: 1px solid var(--ui-text);
+ padding: 0.5em;
+ }
+ /* {{}} shortcode */
+ .hint, .callout {
+ padding: 1em;
+ line-height: 2;
+ &.info, &.tip
+ {
+ background: rgba(142, 226, 142, 0.2);
+ border-inline-start: 4px solid rgb(142, 226, 142);
+ }
+ &.warning {
+ background: rgba(218, 226, 142, 0.2);
+ border-inline-start: 4px solid rgb(218, 226, 142);
+ }
+ &.danger {
+ background: rgba(226, 142, 142, 0.2);
+ border-inline-start: 4px solid rgb(226, 142, 142);
+ }
+ }
+ /* hugo-specific citation footnote */
+ cite sup {
+ position: inherit;
+ font-size: inherit;
+ a {
+ padding: 0.25em;
+ }
+ &:before {
+ content: ' [';
+ }
+ &:after {
+ content: ']';
+ }
+ }
+ /* the actual footnotes section */
+ .footnotes {
+ hr {
+ display: flex;
+ align-items: center;
+ border: 0;
+ &:before {
+ content: 'Footnotes';
+ color: var(--ui-text);
+ text-transform: uppercase;
+ font-weight: 900;
+ font-size: 0.8em;
+ }
+ &:after {
+ content: '';
+ width: 100%;
+ margin-inline-start: 1rem;
+ border-block-end: 1px solid var(--ui-text-muted);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/common/reset.scss b/wiki.hugo/assets/styles/common/reset.scss
new file mode 100644
index 0000000..9e2f07f
--- /dev/null
+++ b/wiki.hugo/assets/styles/common/reset.scss
@@ -0,0 +1,60 @@
+*, *::before, *::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+}
+
+p, h1, h2, h3, h4, h5, h6 {
+ overflow-wrap: break-word;
+}
+
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+input, button, textarea, select {
+ font: inherit;
+}
+
+ol, ul {
+ list-style: none;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+
+html:focus-within {
+ scroll-behavior: smooth;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ html:focus-within {
+ scroll-behavior: auto;
+ }
+
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/components/breadcrumbs.scss b/wiki.hugo/assets/styles/components/breadcrumbs.scss
new file mode 100644
index 0000000..2eb7645
--- /dev/null
+++ b/wiki.hugo/assets/styles/components/breadcrumbs.scss
@@ -0,0 +1,27 @@
+.breadcrumbs {
+ display: flex;
+ flex-flow: row wrap;
+ padding: 0;
+ li:not(:first-child) {
+ margin-inline-start: 1.5rem;
+ margin-block-end: 1rem;
+ }
+ li::marker {
+ content: "/ ";
+ }
+ li:first-child::marker {
+ content: "";
+ }
+ li:first-child {
+ margin-inline-start: 0;
+ }
+ font-family: monospace;
+}
+.breadcrumb-nav {
+ .title {
+ margin-block-end: 0.5em;
+ color: var(--ui-text-muted);
+ text-transform: uppercase;
+ font-weight: 900;
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/components/site-footer.scss b/wiki.hugo/assets/styles/components/site-footer.scss
new file mode 100644
index 0000000..8e32d8e
--- /dev/null
+++ b/wiki.hugo/assets/styles/components/site-footer.scss
@@ -0,0 +1,41 @@
+.site-footer {
+ display: flex;
+ align-items: center;
+ padding-block: 1em;
+
+ hr {display: none;}
+
+ .container {
+ display: flex;
+ flex-flow: row wrap;
+ gap: 1em;
+ }
+
+ .footer-nav .menu {
+ display: flex;
+ flex-flow: row wrap;
+ gap: 1em;
+ a:after {display: none;}
+ }
+
+ .social-nav {
+ .menu {
+ display: flex;
+ gap: 1rem;
+ a:after {
+ display: none;
+ }
+ }
+ }
+
+ a[href='#top'] {
+ margin-inline-start: auto;
+ }
+
+ .lastmod {
+ .edit-link {
+ margin-inline-start: 1em;
+ }
+ }
+
+}
diff --git a/wiki.hugo/assets/styles/components/site-header.scss b/wiki.hugo/assets/styles/components/site-header.scss
new file mode 100644
index 0000000..cf44217
--- /dev/null
+++ b/wiki.hugo/assets/styles/components/site-header.scss
@@ -0,0 +1,55 @@
+.site-masthead {
+ display: inline-flex;
+ flex-flow: row;
+ align-items: center;
+ gap: 1em;
+ text-decoration: none;
+}
+.site-icon {
+ block-size: 2em;
+}
+.site-title {
+ font-weight: 900;
+ letter-spacing: -0.5px;
+ font-size: 1.25em;
+ margin: 0;
+}
+.site-masthead, .site-masthead:visited {
+ color: inherit
+}
+
+.site-masthead:focus {
+ color: var(--primary-accent-text);
+}
+
+.site-header {padding: 1em 0;}
+
+.site-header a {
+ font-weight: 500;
+}
+.site-header .container {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-between;
+ gap: 1em;
+}
+
+.header-nav {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: center;
+ align-items: center;
+ .menu {
+ display: flex;
+ flex-flow: row wrap;
+ gap: 1em;
+ a {
+ display: flex;
+ align-items: center;
+ gap: 0.5em;
+ &:after {
+ display: none;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/components/table-of-contents.scss b/wiki.hugo/assets/styles/components/table-of-contents.scss
new file mode 100644
index 0000000..010b607
--- /dev/null
+++ b/wiki.hugo/assets/styles/components/table-of-contents.scss
@@ -0,0 +1,30 @@
+.toc-title {
+ margin-block-end: 0.5em;
+ font-weight: 900;
+ text-transform: uppercase;
+ color: var(--ui-text-muted);
+}
+#TableOfContents {
+ ul, ol {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+ li {
+ margin-block: 0.5em;
+ margin-inline: 0;
+ }
+ a {
+ display: inline-block;
+ line-height: 1.5;
+ }
+ li > ul, li > ol { /* indent subheadings */
+ margin-inline-start: 1em;
+ }
+}
+.toc details {
+ max-width: 45ch;
+ background: rgba(0,0,0,0.2);
+ padding: 1em;
+ border-radius: 0.5em;
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/features/headings.scss b/wiki.hugo/assets/styles/features/headings.scss
new file mode 100644
index 0000000..6781a45
--- /dev/null
+++ b/wiki.hugo/assets/styles/features/headings.scss
@@ -0,0 +1,94 @@
+h2.heading {
+ border-block-end: 1px solid var(--ui-text-muted);
+ padding-block-end: 1rem;
+}
+
+/* headings with no numbers */
+
+article:not([autonumbering]) .heading {
+ position: relative;
+ margin-inline-end: 2.5rem;
+ &__anchor-link {
+ display: inline-flex;
+ align-content: center;
+ margin-inline-start: 0.25em;
+ position: absolute;
+ inset-inline-end: -2.5rem;
+ inset-block-start: 3px;
+ font-size: 1rem;
+ }
+}
+
+/* headings with autonumbering support */
+
+body {counter-reset: h2}
+h2 {counter-reset: h3}
+h3 {counter-reset: h4}
+h4 {counter-reset: h5}
+
+article[autonumbering] {
+ h2:before {
+ counter-increment: h2;
+ content: counter(h2) " ";
+ }
+ h3:before {
+ counter-increment: h3;
+ content: counter(h2) "." counter(h3) " ";
+ }
+ h4:before {
+ counter-increment: h4;
+ content: counter(h2) "." counter(h3) "." counter(h4) " ";
+ }
+ h2:before,
+ h3:before,
+ h4:before
+ {
+ margin-inline-end: 1em;
+ font-family: monospace;
+ font-size: 1rem;
+ }
+
+ .heading {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ grid-template-rows: auto auto;
+ grid-gap: 0.5rem;
+ &__text {
+ grid-column: span 2;
+ }
+ &__anchor-link {
+ font-size: 1rem;
+ grid-column: 2;
+ grid-row: 1;
+ justify-self: end;
+ }
+ }
+
+ #TableOfContents :is(ol, ul) {
+ /*
+ each list gets a new counter
+ */
+ counter-reset: item;
+ margin-inline-start: 0;
+ }
+ #TableOfContents li:before {
+ /*
+ the counter is added as a pseudo-element,
+ and nested counters are joined by a dot
+ */
+ content: counters(item, ".") " ";
+ counter-increment: item;
+ /* ensure the counters align visually */
+ font-family: monospace;
+ font-weight: bold;
+ margin-inline-end: 1em;
+ }
+ #TableOfContents > ul > li {
+ /*
+ top-level items wrap after the number,
+ in order to add some visual separation
+ */
+ display: flex;
+ flex-flow: column;
+ }
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/features/search.scss b/wiki.hugo/assets/styles/features/search.scss
new file mode 100644
index 0000000..a8080e3
--- /dev/null
+++ b/wiki.hugo/assets/styles/features/search.scss
@@ -0,0 +1,71 @@
+.search-results__title {
+ display: block;
+ font-size: 2em;
+ line-height: 1;
+ margin-block-end: 1em;
+}
+
+.search-results strong {
+ font-weight: 900;
+ background: var(--primary-accent-transparent);
+ color: var(--ui-text-bold);
+}
+
+#search-results {
+ display: flex;
+ flex-flow: column;
+ max-inline-size: 80ch;
+}
+
+#search-results li:not(:first-child) {
+ border-block-start: 1px solid var(--ui-text-muted);
+}
+
+#search-results li {
+ padding-block: 1em;
+}
+
+.search-result-page-title {
+ font-size: 1.25em;
+ display: block;
+ margin-block-end: 1rem;
+}
+
+.search-result-item p {
+ line-height: 1.5;
+}
+
+#search-form {
+ width: 100%;
+ max-width: 18rem;
+ display: grid;
+ grid-template-columns: 20ch 8ch;
+ gap: 1rem;
+}
+
+#search-input {
+ background: var(--ui-overlay);
+ color: var(--ui-overlay-text);
+ border-radius: 100rem;
+ border: 0;
+ padding: 0.5rem 1rem;
+ box-sizing: border-box;
+ resize: horizontal;
+ width: 100%;
+ grid-column: 1;
+ block-size: 2rem;
+ line-height: 1rem;
+ font-size: 0.75rem;
+}
+
+#search-submit {
+ padding: 0.5rem 1rem;
+ border: 0;
+ background: var(--primary-accent);
+ color: var(--primary-accent-text);
+ border-radius: 4px;
+ grid-column: 2;
+ block-size: 2rem;
+ line-height: 1rem;
+ font-size: 0.75rem;
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/features/syntax-highlighting.scss b/wiki.hugo/assets/styles/features/syntax-highlighting.scss
new file mode 100644
index 0000000..b544de6
--- /dev/null
+++ b/wiki.hugo/assets/styles/features/syntax-highlighting.scss
@@ -0,0 +1,110 @@
+/* syntax highlighting */
+
+.highlight {
+
+ --error: #cc0000;
+ --keyword: #3361a7;
+ --class: #f57900;
+ --variable: #c049dd;
+ --number: #53ca24;
+ --operator: #5400c2;
+ --highlight: rgb(196, 196, 196);
+
+ @media (prefers-color-scheme: dark) {
+
+ --error: #cc0000;
+ --keyword: #e0d56e;
+ --class: #8700f5;
+ --variable: #008eb9;
+ --number: #53ca24;
+ --operator: #fffd6f;
+ --highlight: #555;
+ }
+
+}
+
+/* Background */ .bg { background-color: #f8f8f8; }
+/* PreWrapper */ .chroma { background-color: #f8f8f8; }
+/* Other */ .chroma .x { color: var(--ui-text-bold) }
+/* Error */ .chroma .err { color: var(--error) }
+/* CodeLine */ .chroma .cl { color: var(--ui-text) }
+/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
+/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
+/* LineHighlight */ .chroma .hl { background-color: var(--highlight) }
+/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* Line */ .chroma .line { display: flex; white-space: pre }
+/* Keyword */ .chroma .k { color: var(--keyword); font-weight: bold }
+/* KeywordConstant */ .chroma .kc { color: var(--keyword); font-weight: bold }
+/* KeywordDeclaration */ .chroma .kd { color: var(--keyword); font-weight: bold }
+/* KeywordNamespace */ .chroma .kn { color: var(--keyword); font-weight: bold }
+/* KeywordPseudo */ .chroma .kp { color: var(--keyword); font-weight: bold }
+/* KeywordReserved */ .chroma .kr { color: var(--keyword); font-weight: bold }
+/* KeywordType */ .chroma .kt { color: var(--keyword); font-weight: bold }
+/* Name */ .chroma .n { color: var(--ui-text-bold) }
+/* NameAttribute */ .chroma .na { color: var(--ui-text-bold) }
+/* NameBuiltin */ .chroma .nb { color: var(--name) }
+/* NameBuiltinPseudo */ .chroma .bp { color: #3465a4 }
+/* NameClass */ .chroma .nc { color: var(--ui-text-bold) }
+/* NameConstant */ .chroma .no { color: var(--ui-text-bold) }
+/* NameDecorator */ .chroma .nd { color: var(--class); font-weight: bold }
+/* NameEntity */ .chroma .ni { color: var(--name) }
+/* NameException */ .chroma .ne { color: var(--error); font-weight: bold }
+/* NameFunction */ .chroma .nf { color: var(--ui-text-bold) }
+/* NameFunctionMagic */ .chroma .fm { color: var(--ui-text-bold) }
+/* NameLabel */ .chroma .nl { color: var(--name) }
+/* NameNamespace */ .chroma .nn { color: var(--ui-text-bold) }
+/* NameOther */ .chroma .nx { color: var(--ui-text-bold)}
+/* NameProperty */ .chroma .py { color: var(--ui-text-bold) }
+/* NameTag */ .chroma .nt { color: var(--keyword); font-weight: bold }
+/* NameVariable */ .chroma .nv { color: var(--variable) }
+/* NameVariableClass */ .chroma .vc { color: var(--ui-text-bold)}
+/* NameVariableGlobal */ .chroma .vg { color: var(--ui-text-bold) }
+/* NameVariableInstance */ .chroma .vi { color: var(--ui-text-bold) }
+/* NameVariableMagic */ .chroma .vm { color: var(--ui-text-bold) }
+/* Literal */ .chroma .l { color: var(--ui-text-bold) }
+/* LiteralDate */ .chroma .ld { color: var(--ui-text-bold) }
+/* LiteralString */ .chroma .s { color: var(--variable) }
+/* LiteralStringAffix */ .chroma .sa { color: var(--variable) }
+/* LiteralStringBacktick */ .chroma .sb { color: var(--variable) }
+/* LiteralStringChar */ .chroma .sc { color: var(--variable) }
+/* LiteralStringDelimiter */ .chroma .dl { color: var(--variable) }
+/* LiteralStringDoc */ .chroma .sd { color: var(--keyword); font-style: italic }
+/* LiteralStringDouble */ .chroma .s2 { color: var(--variable) }
+/* LiteralStringEscape */ .chroma .se { color: var(--variable) }
+/* LiteralStringHeredoc */ .chroma .sh { color: var(--variable) }
+/* LiteralStringInterpol */ .chroma .si { color: var(--variable) }
+/* LiteralStringOther */ .chroma .sx { color: var(--variable) }
+/* LiteralStringRegex */ .chroma .sr { color: var(--variable) }
+/* LiteralStringSingle */ .chroma .s1 { color: var(--variable) }
+/* LiteralStringSymbol */ .chroma .ss { color: var(--variable) }
+/* LiteralNumber */ .chroma .m { color: var(--number); font-weight: bold }
+/* LiteralNumberBin */ .chroma .mb { color: var(--number); font-weight: bold }
+/* LiteralNumberFloat */ .chroma .mf { color: var(--number); font-weight: bold }
+/* LiteralNumberHex */ .chroma .mh { color: var(--number); font-weight: bold }
+/* LiteralNumberInteger */ .chroma .mi { color: var(--number); font-weight: bold }
+/* LiteralNumberIntegerLong */ .chroma .il { color: var(--number); font-weight: bold }
+/* LiteralNumberOct */ .chroma .mo { color: var(--number); font-weight: bold }
+/* Operator */ .chroma .o { color: var(--operator); font-weight: bold }
+/* OperatorWord */ .chroma .ow { color: var(--keyword); font-weight: bold }
+/* Punctuation */ .chroma .p { color: var(--ui-text-bold); font-weight: bold }
+/* Comment */ .chroma .c { color: var(--ui-text-muted); font-style: italic }
+/* CommentHashbang */ .chroma .ch { color: var(--ui-text-muted); font-style: italic }
+/* CommentMultiline */ .chroma .cm { color: var(--ui-text-muted); font-style: italic }
+/* CommentSingle */ .chroma .c1 { color: var(--ui-text-muted); font-style: italic }
+/* CommentSpecial */ .chroma .cs { color: var(--ui-text-muted); font-style: italic }
+/* CommentPreproc */ .chroma .cp { color: var(--ui-text-muted); font-style: italic }
+/* CommentPreprocFile */ .chroma .cpf { color: var(--ui-text-muted); font-style: italic }
+/* Generic */ .chroma .g { color: var(--ui-text-bold) }
+/* GenericDeleted */ .chroma .gd { color: var(--error) }
+/* GenericEmph */ .chroma .ge { color: var(--ui-text-bold); font-style: italic }
+/* GenericError */ .chroma .gr { color: var(--error) }
+/* GenericHeading */ .chroma .gh { color: var(--ui-text-bold); font-weight: bold }
+/* GenericInserted */ .chroma .gi { color: var(--ui-text) }
+/* GenericOutput */ .chroma .go { color: var(--ui-text-bold); font-style: italic }
+/* GenericPrompt */ .chroma .gp { color: var(--ui-text) }
+/* GenericStrong */ .chroma .gs { color: var(--ui-text-bold); font-weight: bold }
+/* GenericSubheading */ .chroma .gu { color: var(--ui-text-bold); font-weight: bold }
+/* GenericTraceback */ .chroma .gt { color: var(--error); font-weight: bold }
+/* GenericUnderline */ .chroma .gl { color: var(--ui-text-bold); text-decoration: underline }
+/* TextWhitespace */ .chroma .w { color: var(--ui-text-muted); text-decoration: underline }
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/layouts/list.scss b/wiki.hugo/assets/styles/layouts/list.scss
new file mode 100644
index 0000000..cc71b48
--- /dev/null
+++ b/wiki.hugo/assets/styles/layouts/list.scss
@@ -0,0 +1,27 @@
+.subsections,
+.subpages {
+ list-style: disc;
+ padding: 0;
+ margin-block-start: 1em;
+ margin-block-end: 2em;
+ li {
+ margin-inline-start: 1em;
+ margin-block-end: 1em;
+ }
+ a {
+
+ }
+}
+.section-title {
+ font-size: 2em;
+ border-block-end: 1px solid var(--ui-text-muted);
+ padding-block-end: 0.5em;
+ margin-block-start: 0;
+ margin-block-end: 1em;
+}
+.subsections-title,
+.subpages-title {
+ margin-block-start: 1em;
+ font-weight: 500;
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/layouts/single.scss b/wiki.hugo/assets/styles/layouts/single.scss
new file mode 100644
index 0000000..5f9e4b9
--- /dev/null
+++ b/wiki.hugo/assets/styles/layouts/single.scss
@@ -0,0 +1,3 @@
+.content {
+ padding-top: 0;
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/print.scss b/wiki.hugo/assets/styles/print.scss
new file mode 100644
index 0000000..75fe89c
--- /dev/null
+++ b/wiki.hugo/assets/styles/print.scss
@@ -0,0 +1,35 @@
+@import "common/reset";
+@import "common/colors";
+@import "common/base";
+@import "common/content";
+
+@import "layouts/list.scss";
+@import "layouts/single.scss";
+
+@import "components/site-header";
+@import "components/site-footer";
+
+@import "components/breadcrumbs";
+@import "components/table-of-contents";
+@import "features/headings";
+
+#search-form,
+.header-nav,
+.docs-nav,
+.site-footer,
+.edit-link,
+.footnote-backref,
+.heading__anchor-link,
+.section-nav
+{
+ display: none;
+}
+.page-header {padding: 0;}
+
+.page abbr[title]::after {
+ content: " (" attr(title) ") ";
+}
+
+a[href^="http"]:after {
+ content: " (" attr(href) ") ";
+}
\ No newline at end of file
diff --git a/wiki.hugo/assets/styles/screen.scss b/wiki.hugo/assets/styles/screen.scss
new file mode 100644
index 0000000..687a291
--- /dev/null
+++ b/wiki.hugo/assets/styles/screen.scss
@@ -0,0 +1,20 @@
+@import "common/reset";
+@import "common/colors";
+@import "common/base";
+@import "common/content";
+
+@import "components/site-header";
+@import "components/site-footer";
+
+@import "components/breadcrumbs";
+@import "components/table-of-contents";
+
+@import "layouts/list.scss";
+@import "layouts/single.scss";
+
+@import "features/headings";
+@import "features/syntax-highlighting";
+@import "features/search";
+
+@import "screen/layout";
+@import "screen/links";
diff --git a/wiki.hugo/assets/styles/screen/layout.scss b/wiki.hugo/assets/styles/screen/layout.scss
new file mode 100644
index 0000000..e69de29
diff --git a/wiki.hugo/assets/styles/screen/links.scss b/wiki.hugo/assets/styles/screen/links.scss
new file mode 100644
index 0000000..d9da7bd
--- /dev/null
+++ b/wiki.hugo/assets/styles/screen/links.scss
@@ -0,0 +1,37 @@
+a:link {
+ transition: all 0.1s ease-out;
+ color: var(--link-color);
+ text-decoration-thickness: .0625rem;
+ text-underline-offset: 0.125em;
+ text-decoration-skip-ink: none;
+}
+
+a:visited {
+ color: var(--link-visited);
+}
+
+a:focus {
+
+}
+
+a:hover {
+ text-decoration-thickness: 0.125em;
+ text-underline-offset: 0.25em;
+}
+
+@media (prefers-reduced-motion) {
+ a:link {transition: none}
+}
+
+a:link[target=_blank] {
+ svg {
+ margin-inline-start: 0.35em;
+ margin-inline-end: 0.15em;
+ vertical-align: baseline;
+ font-size: 0.65em;
+ }
+}
+
+a:link[title] {
+ text-decoration-style: dotted;
+}
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/_index.md b/wiki.hugo/content/_dump/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/_dump/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/activitypub-2.md b/wiki.hugo/content/_dump/activitypub-2.md
new file mode 100644
index 0000000..e3e9c07
--- /dev/null
+++ b/wiki.hugo/content/_dump/activitypub-2.md
@@ -0,0 +1,35 @@
+https://mastodon.social/@trwnh/109979200684979970
+
+@ people who keep saying we should rewrite the activitypub spec to ensure better interoperability with existing fedi projects
+
+[](specs-are-enough.jpg)
+
+idk how else to say that if you want to be compatible with a project then you need to have a shared worldview and conceptual space, and this necessarily involves communicating with that project on some level (by reading their documentation, asking their devs questions, etc) in order to know what their expectations and requirements are
+
+the question of "interoperability" makes no sense on its own. you must always ask, interoperability with what? and on which conditions?
+
+like, we all use activitypub more or less according to the spec, and that's because the spec is simple, it's basically just "HTTP POST to inbox". we could theoretically construct any as2 payload we wanted, but we largely limit ourselves to Create Note... why? because you want to be compatible with mastodon, right? and that's the real issue.
+
+there are things that mastodon et al do that are within some spec -- webfinger for translating usernames to actors, for example. then there are things that are technically a spec but outdated, like http signatures (cavage draft) and ld signatures (obsoleted entirely). and then there are things that are not specced -- quirks of the implementation that must be respected, things like using Note, how to structure a Mention, the use of specific algorithms for signatures. maybe these can be negotiated
+
+crucially, sometimes the assumptions you make, the quirks your software has, these will not line up with the assumptions that others make, the quirks that their software has. you might even disagree entirely, and without the possibility of reconciling those opposing assumptions.
+
+consider the assumption that every actor has a username, and that this username identifies them more canonically than their own activitypub identifier. what if you disagree? well, that's an incompatibility.
+
+how do you handle the root of identity being the activitypub id, versus the root of identity being the username, versus the root of identity being some cryptographic key? what is one to do, if one wants to be "compatible" and "interoperate" with three different softwares each following a different one of the above assumptions about identity? are these softwares even meaningfully part of the same network? and which of these three networks is the "true" "fediverse"?
+
+and even within those identity schemes, we might still have to consider further parameters, like the expectation of only supporting HTTPS URIs. or, let's imagine that we choose to use or support DIDs -- now, which DID methods do we support?
+
+all of these are decisions that each project has to either make for itself, or vest authority in some other entity to make those decisions in a binding way -- by publishing some meta-spec, some conformance profile, basically a bundle of specs that should be followed and their particulars.
+
+and even *then*, you will find some quirks remain, some projects are coded in a way which has implicit expectations. the more you try to eliminate these, the narrower the scope or conceptual space becomes.
+
+with enough limitations, you end up with what is basically the same software, just with different implementations. if mastodon, pleroma, and misskey all were overspecced like this, you may as well view them as "fedi implemented in rails", "fedi implemented in elixir", and "fedi implemented in nodejs".
+
+so, in closing, i leave with this to consider:
+
+is your view of the "fediverse" limited only to the conceptual space of existing projects? and, if so, then which ones?
+
+or will you allow yourself to dream a little bigger?
+
+https://www.youtube.com/watch?v=WcGbnX8Ay38
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/activitypub-proglang.md b/wiki.hugo/content/_dump/activitypub-proglang.md
new file mode 100644
index 0000000..30bb62b
--- /dev/null
+++ b/wiki.hugo/content/_dump/activitypub-proglang.md
@@ -0,0 +1,20 @@
+people think activitypub is a network protocol when it's really more like a programming language. you don't say "compatible with c++" you say "written in/with c++". similarly, we might say that fedi is "written with activitypub" or "implemented using activitypub", not "compatible with activitypub" or anything suggesting a network.
+
+analogously:
+
+ap = inter-process communication (e.g. d-bus)
+as2 = data interchange format (e.g. protobuf)
+json-ld = media type
+rdf = facts and logic
+
+if we're being honest the majority of "fedi" is part of the "network" that is "compatible with mastodon". mastodon *is* the network protocol. we just express it in terms of "mastodon-flavoured activitypub"
+
+put another way, there is no such thing as "fedi", but rather, multiple different and distinct "fedis" that only partially overlap.
+
+it occurs to me that activitypub may be best thought of as a cms with an optional distributed storage backend
+
+similarly: no one in fedi is doing real activitypub. it is probably more appropriate to say we are doing AS2 + Linked Data Notifications
+
+side effects are more accurately defined by the mastodon documentation than by the activitypub spec
+
+we're kind of in the situation where someone has invented the C Programming Language, maybe D-Bus, but we still don't have a FreeDesktop.org or XDG equivalent.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/concepts/stores-and-transports.md b/wiki.hugo/content/_dump/concepts/stores-and-transports.md
new file mode 100644
index 0000000..680e9c2
--- /dev/null
+++ b/wiki.hugo/content/_dump/concepts/stores-and-transports.md
@@ -0,0 +1,13 @@
+data flows into the application from "stores", and flows out via "transports"
+
+### stores
+
+IMAP
+AP C2S GET?
+XMPP C2S???
+
+### transports
+
+SMTP
+XMPP
+AP C2S POST?
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/copyright-is-theft.md b/wiki.hugo/content/_dump/copyright-is-theft.md
new file mode 100644
index 0000000..6fddb98
--- /dev/null
+++ b/wiki.hugo/content/_dump/copyright-is-theft.md
@@ -0,0 +1,15 @@
+well opposing copyright isn't thievery, for a start. theft is the act of taking something without returning it, removing the original. digital information can be infinitely and perfectly copied.
+
+copyright enforcement is instead about giving certain parties exclusive monopolies on the spread of information. this gatekeeps culture and stifles free expression. in return for what? trying to sell access?
+
+note also this monopoly is only enforced via the threat of state violence.
+
+tangentially, there's also the fundamental inversion of value that occurs when artists try to fund themselves by selling art as if it were a commodity. the value in art is not necessarily in the final product alone but moreso in the creation of it.
+
+copyright asks us to perform creative labour for free, and hope to recoup our losses via the market (in which you must differentiate yourself from millions of functionally equivalent forms of art and entertainment -- good luck!)
+
+when you recognize this inversion of value, you recognize that the real answer to making sure artists get paid is to actually pay them for the work they do, not to commodify what they produce. things like commissions, patronage, public works funds, etc. all get to the root and heart of the issue.
+
+copyright is in effect more akin to theft -- theft from the public, from the commons, from culture. it benefits no one except those who "own" a lot of art -- the disneys of the world.
+
+in short: if you want artists to get paid, copyright is a really poor and ineffective way to do that. it just leads to big monopolies on art, at the expense of everyone else.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/defining-quotes.md b/wiki.hugo/content/_dump/defining-quotes.md
new file mode 100644
index 0000000..c715e5e
--- /dev/null
+++ b/wiki.hugo/content/_dump/defining-quotes.md
@@ -0,0 +1,74 @@
++++
+date = 2023-05-02
++++
+
+fwiw my take about quotes is that either
+
+- they're just links with special tag markup that lets them be identifiable as activitypub objects
+- they're supported more at the protocol level a la Announce with content, or possibly a "quotes" collection a la "likes" and "shares"
+- they represent a new context (assuming mastodon ever adopts a first-class concept of conversations or threads, instead of relying solely on inReplyTo chains for logical grouping)
+
+my further idea was to decide if it notifies based on whether the type is Link or Mention (a la webmentions)
+
+in an alternate timeline we could have had generic rendering of activities based on name/summary/content and maybe actor/type/object
+
+such a generic renderer would be something like...
+
+>
+>
+>
+
+filling in the last two lines for summary and content
+
+> Darius boosted a post: "The problem with this is..."
+> "I disagree with this analysis."
+
+also this just highlights what i think a "quote post" should really be: more like a "loud reply". in a more ideal world it would use `inReplyTo` + a new `context`.
+
+yes, a regular "reply" is in effect a "quote" the second you embed the post you are replying to. look at the IndieWeb for example. what is the functional difference?
+
+the problem of course is that mastodon doesnt show replies in timelines, and doesn't have a proper concept of contexts aside from reply-chains. but at least half of that is a matter of policy, so it could be changed.
+
+imagine a property `toot:quoteReply` that is a boolean. if true, it embeds the `inReplyTo`post above your post. it also sends such posts to follower timelines.
+
+fundamentally there's the intent and the interpretation, intent can be seen as how you author the activity, interpretation is the processing rules applied by the receiver. if this were a proper spec, the two would be the same and there'd be no ambiguity, but... well, y'know.
+
+there's also the rest of the ecosystem of course, there's the "tag a substring of your content" as Foundkey does, in the past there was even "attach the post you're quoting" which Hubzilla and/or Zap did, there was also the proposal to "add content on Announce" which gargron and lain favored but never implemented. and then there's the two new ones -- "just make it a special type of reply" as i propose, and "just make it a new Activity" as you expressed just now
+
+we should focus on generic data modeling, describing resources and how they are related. mastodon doesn't do a good job of that, sure... and that's how we end up with leaky abstractions. it's a good idea to leave as much of the app-specific stuff out of the data model as we can. otherwise we just end up with The Mastodon Protocol which is built to interop with the mastodon app specifically
+
+like we have tag, attachment, inReplyTo, Announce...
+
+- tag = describing entities within the natural language properties (often microsyntaxes)
+
+- attachment = sidecar entities (not necessarily media)
+
+- inReplyTo = referencing a prior object (or objects) for which your current object can be considered a response
+
+- Announce = add to `shares` collection if present (this is the weakest one, to be fair)
+
+> I do agree with you that quotes are basically a form of loud reply
+
+semantics aside, i think functionally the difference is really the fallback
+
+- an Announce with content is basically "reshare with additional content" semantically, but it falls back to being a regular boost, and to control quotes you'd need to similarly be able to control boosts
+
+- a Note with inReplyTo + quoteReply=true would fall back to a regular reply. this means that when reply controls get added, you get quote control "for free"
+
+the other functional difference between those two is whether the "quote" gets added to `shares` or to `replies`
+
+---
+
+also tangentially i've thought about what people think a quote is vs what it actually is, the dimensions, its primary function, etc
+
+to me, the way i see quotes is essentially as a "loud reply" or as a "breakout thread".
+
+the former use-case could be handled by reply+boost. this is actually very easy in the API: just make a button that fires off 2 API calls.
+
+the latter could be handled by copypasting a link into a new post. this is much harder to detect and display. optinally mention
+
+really the problem with twitter "quote tweets" is that they conflated the two use-cases
+
+you were *always* notified, regardless of whether someone was talking "about" you or "to" you (no consideration for replies)
+
+plus the fact it was a new thread was stripping context, you could no longer see all the posts in one thread ("breaking out" isn't always wanted)
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/documentation-first.md b/wiki.hugo/content/_dump/documentation-first.md
new file mode 100644
index 0000000..a91be69
--- /dev/null
+++ b/wiki.hugo/content/_dump/documentation-first.md
@@ -0,0 +1,5 @@
+https://mastodon.social/@trwnh/109826683171183861
+
+if/when i get around to building [untitled social app] i want to set some hard design expectations for it before even thinking about if/when/how to release it (and which parts of it). there's a lot of expectations i want to challenge, i don't want to take anything for granted. if anything, whatever i build will simply be the practical application of my grand unified communication theory. it's as much an experiment and learning process as it is a tool or utility.
+
+which is to say: any code i write or software i build, it will not be the primary product. the primary product will be the documentation and reasoning behind it. it will be in researching existing protocols and ecosystems, then identifying how they map onto the theoretical patterns and structures. nail the recipe before baking the cake.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/domain-number-system.md b/wiki.hugo/content/_dump/domain-number-system.md
new file mode 100644
index 0000000..58d3c15
--- /dev/null
+++ b/wiki.hugo/content/_dump/domain-number-system.md
@@ -0,0 +1,40 @@
+https://mastodon.social/@trwnh/109965906891374818
+
+we have a domain name system but why don't we have a domain number system
+
+just like we can register human-friendly names, we should be able to register persistent machine-friendly numbers to websites and domains. the name and number are aliased together, or we map name => number => ip address
+
+yes this idea is copied from xri i-names and i-numbers, it's one of the best ideas to come out of that effort (aside from delegation of authority at any point in the identifier)
+
+the world if xri took off
+
+future.jpg
+
+i've talked/thought about doing something similar with webfinger, but the "authority delegation" bit is really hard without a persistent unchanging identifier in some common authoritative namespace. you can defer to some other DNS domain's webfinger endpoint, but that doesn't get rid of the fragility in expiring or reassigning domain names.
+
+it's interesting that bluesky comes to a similar conclusion with its "placeholder" DID scheme, did:plc: -- identifiers are centralized around a single "PLC server". the DNS stuff maps to a did:plc: that gets resolved by the centralized resolution server.
+
+we could do something similar with a centralized server/domain that did nothing but assign identifiers and map to current location... of course, that doesn't solve the problem, it just shifts the burden.
+
+so here's a crackpot idea that requires "minimal" changes to the way the world works
+
+1. register a TLD with the IANA/ICANN -- let's call it something like .uuid
+2. allow anyone to register UUIDs on this TLD -- this should be as easy as registering any other domain name, but instead of getting to pick the name, it's auto-assigned to you
+3. CNAME your desired public-facing domain name to the .uuid domain you registered
+4. optionally: run some software to "reverse map" your .uuid URIs (Webfinger)
+
+you could also use plain old HTTP redirects instead of Webfinger, if you trusted the thing at the other end to stay online
+
+but the main thing would be being able to use
+
+trwnh.com/some-resource => 05517367-0a6a-42c1-9810-9fcf264a505b.uuid/some-resource
+
+and then later change trwnh.com to some other domain
+
+any software/application dealing with identifiers SHOULD support using the "canonical" identifier, so you can signal that the .uuid-assigned URI is the canonical one
+
+crucially, the .uuid registry would never expire, and probably it should be free. the goal is to never let the .uuid registration lapse, ever
+
+maybe your domain name registrar could even host a reverse-mapping server for you, if they wanted to expand their services?
+
+also something to consider: under what circumstances might an entire TLD lapse? like this is super unlikely, sure, but what happens if the entity behind some TLD in the IANA root zone database goes insolvent?
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/drowning-in-awareness.md b/wiki.hugo/content/_dump/drowning-in-awareness.md
new file mode 100644
index 0000000..88fb8c0
--- /dev/null
+++ b/wiki.hugo/content/_dump/drowning-in-awareness.md
@@ -0,0 +1,9 @@
++++
+date = "2023-01-20"
++++
+
+i am reminded of an essay i read once called "avoid news" which might sound extreme to some people but it actually has a simple premise: most of what you encounter in media suffers from context collapse and/or is not actionable. therefore it can never truly be relevant. what is far more valuable is filtering through the news for anything actionable worth educating people about, and presenting it in a more relevant and digestible way. not everyone should have to do this.
+
+i'd really go further and say that these days, if you don't have a material call to action, you have nothing. what do you expect to accomplish by sharing what you're sharing? "awareness" on its own is not enough; it can even be an actively bad thing if you end up paralyzed by inaction and despairing over it. far better to actively educate people that need educating, instead of simply "raising awareness".
+
+like, ok, i'm aware. now what?
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/email.md b/wiki.hugo/content/_dump/email.md
new file mode 100644
index 0000000..b83e485
--- /dev/null
+++ b/wiki.hugo/content/_dump/email.md
@@ -0,0 +1,27 @@
++++
+updated = "2021"
++++
+### Mailpile
+- selfhosted mail archive?
+- more of a webmail client?
+- demo seems kinda slow :(
+- uses imap/pop3 to download mail, optionally delete it from server
+- uses its own http api instead of re-exposing imap UGH
+- https://github.com/mailpile/Mailpile/wiki/Synchronizing-Mailpile-with-Thunderbird
+- https://github.com/mailpile/Mailpile/wiki/Configuring-Linux-to-download-your-email
+- https://github.com/mailpile/Mailpile/wiki/Mail-sources
+
+### Notmuch
+- https://notmuchmail.org/
+- seems to be an email client with search caps
+- idk if this is what i want
+- https://github.com/johnnyutahh/search-based-email
+
+### OfflineIMAP
+- http://www.offlineimap.org/
+- combine with notmuch?
+- could also combine with mailpile?
+- it seems like it just downloads to a folder idk
+
+### Just download it with thunderbird or something?
+- idk
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/blocklists-as-hoa.md b/wiki.hugo/content/_dump/fedi-critiques/blocklists-as-hoa.md
new file mode 100644
index 0000000..1f8e79e
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/blocklists-as-hoa.md
@@ -0,0 +1,31 @@
+it's a bit weird that some fedi blocklists use language like "fence" because whenever i see that, i don't think "safety", i think "homeowners association", and i think the HOA characterization of certain blocklist efforts is actually not wrong. it is reminiscent of the abstract desire for "safety" rather than any sort of concrete safety or just treatment. "freedom of association" only goes so far to justify punitive and destructive actions at an instance-state level
+
+of course, what is to be done? what is a more appropriate solution? i think whenever such blocklists are circulated, it usually represents a failure mode at an institutional level. the rise of blocktogether on twitter was due to the systemic failure of their moderation. earlier fedi users may or may not remember the infamous "wil wheaton blocklist" that imported from infamous terf randi harper, who billed her list as "99% gaters and mras" (and i guess 1% trans ppl?)
+
+so i think the "question of the day" now, is, what is the failure of fedi and how could we have avoided it and how can we proceed to mitigate it.
+
+for my part i think it comes down to the "instance" model. no one cares if you have to ban someone from a building, but evicting them from their house or expelling them from their country is disproportionate. so naturally, it becomes an issue when the "community" and "living space" are the same thing.
+
+every day more and more it becomes clear we need to restructure around actual communities at a separate layer.
+
+similar to the dynamics of a cliquey community instance, but without the expanded audience that federation brings. imagine just turning off federation.
+
+maybe in some ways that's exactly what is going on -- clique communities are feeling threatened by the inherent lack of control. overblocking is in that vein similar to defensive centralization; after all, what is centralization if not simply blocking *all* remotes? and the balance is set by how much control they want to wrest back.
+
+i think the "objectionable" part to me is that clique mentality. especially as it tries to assert itself over others. the other day i had someone ask me which instance to join and i realized for the first time in 6 or 7 years that i didn't have an answer. they just wanted to exist. they didn't want to have to care about border controls and digital embargoes. and they didn't really have *any* good options.
+
+there isn't really any well-connected generalist instance that isn't overly blocked or doesn't overly block. much less an art-focused one. or a fandom-based one. so they stayed on tumblr and discord even though they *want* to join fedi. there just isn't anywhere for them to find a home in an area that is both good to live in *and* free of HOA type behavior. they don't want a gated community and they don't want a place with drive-by harassment. and they want to actually reach people.
+
+> [I] suspect that the reaching people, the lack of harassment, and lack of blocking are kind of corners of a triangle.
+
+yeah it certainly does seem like a trilemma
+
+instance moderation is absolutely a huge job if you want to stay on top of it. it can be easier if you take a reactive rather than proactive stance. but the problem with proactive stances is that you now need to judge someone *before* they have harassed you. and the way people approach recommended blocks, they might not have been harassed either. you'll never know the difference unless you investigate for yourself... and that's hard rn.
+
+now, if people just said "hey we dont like them, they failed the vibe check and we're not gonna spill any tears", that's more respectable than making something up. i can't count how many times i've seen people blocked for reasons that are patently absurd if you know the people. you use a reclaimed slur, you get blocked for using slurs. somewhere along the line that becomes "hate speech". a while ago it was "federates with the usual suspects". guilt by association morphed into "alt fedi"
+
+the hard part is... they're not always wrong! a lot of blocks make sense when you look into them. but it's a mix, and the false positive rate is a bit too high imo. and there's no indication when you lose friends over your admin's decisions. and the policies aren't always visible, bc some admins are hiding them now to prevent scrapers tracking them. it just becomes this whole uncertain mess where you never know who blocks who and why.
+
+---
+
+my problem with oliphant is that there really should be a "tier negative one", given that the "tier 0" list doesn't have 100% consensus. my problem with thebadspace is that every single entry has the same tags, even where it makes no sense. my problem with blocklist culture in general is that there's zero accountability, review, or forgiveness built into them; often, they lack any sort of context, and if there is any reason given, the reasons are laughably flat-out ridiculous, incorrect, or inaccurate. i've seen blocks for being "channers" or "edgelord" being levelled against people who couldn't be any further than that. i've seen blocks for "no moderation" when no reports were filed. i've seen blocks for reasons such as "underage" or "reclaimed slurs" or vague unspecified "accusations". there's no differentiation between "hosts twitter crosspost bots" and "contains literal nazis that will send you death threats". fundamentally, i do not think that it is healthy to conflate safety with mere annoyance or a misalignment of "our" values. this is before you even get into the subjectivity of all such judgements... it is, of course, everyone's freedom of association to do whatever they want for themselves, but it is the point at which people start recommending or expecting that you do the same, that it then becomes a problem. and the real problem is not who you do or do not block. the problem is that there are no clear boundaries or clearly-established spaces or contexts for people's communications. you talk to someone that happens to be on someone else's shitlist, and you just might end up on that same shitlist for "federating with the usual suspects", where "the usual suspects" is an unbounded and growing set of people that seems to propagate further every time you look at it. it very frequently leads into policing who any given person mentions offhand or boosts in passing.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/context-unaware.md b/wiki.hugo/content/_dump/fedi-critiques/context-unaware.md
new file mode 100644
index 0000000..c19ad1e
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/context-unaware.md
@@ -0,0 +1,29 @@
+i am more and more taking the position that we should have forums, and we should have blogs, and nothing in between. "social media" carries inherently poor ergonomics and a lack of clarity of purpose. you're never clearly "publishing" anything when you post on social media, unlike when you post on your own blog or website. you're never clearly "discussing" anything either, because threads aren't actual topics or conversations.
+
+so my ideal flow is kinda like
+
+- you make a "post" to your website/profile
+- it may or may not be "in reply to" some other post. this is just metadata
+- it may or may not be part of some "context". this is a moderated conversation or logical grouping owned by someone
+- the "audience" is up to you, completely arbitrary. it might be only visible from within the context of some other webpage, or it might be given a permalink on your website/profile
+
+fedi dropped the ball hard on those last two...
+
+we could realistically move toward something more context-and-audience-aware but it's gonna be a bit rough for the existing "instance" model because of structural limitations. you'd basically be building a new fediverse in the shell of the old. but i think it can be done...
+
+one prong is to support actual "publishing" with articles and a more fleshed-out web profile as a website. add webmentions as an optional thing.
+
+the other prong is to support "discussing" within walls/forums/rooms "context"
+
+eventually this kind of "posting" we have today would be split up and merged into the two new things. the UI would give you an option: do you want to publish a Post, or do you want to start a Discussion?
+
+---
+
+in my mental model. i have the following areas mapped out:
+
+- Publishing (posts)
+- Reading (feeds/timelines)
+- Discussing (forums)
+- Messaging (chats)
+
+all of these are types of communication, and naturally some apps are going to expand to cover more areas. but it's all dependent on context and presentation. a "chat room" and a "forum topic" and a "social media wall" are all just collections of objects, really.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/default-server-paradigm.md b/wiki.hugo/content/_dump/fedi-critiques/default-server-paradigm.md
new file mode 100644
index 0000000..bf6aed0
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/default-server-paradigm.md
@@ -0,0 +1,13 @@
+https://mastodon.social/@trwnh/110310774875374491
+
+re: mastodon and matrix having "default servers" that end up being too big: i feel like if they were easier to selfhost it would be less of a problem. the "default server" paradigm is more effective when you can't easily set up other servers.
+
+you ever try to host matrix? it's awful. like 2GB memory usage just for a single user in a big room.
+
+mastodon is getting to be pretty similar, not because of the base software per se, but because of how many moving parts it has and how much resource usage accrues as a result. rails, postgres, redis, optional elasticsearch if you want working search, a nodejs streaming server and frontend... that's before you even get to the network traffic due to architectural decisions
+
+sure, but you can at least block entire bad servers with little-to-no collateral damage. and you can also use allowlist federation or some other restriction mechanism to avoid fully open federation. just like avoiding fully open registrations.
+
+i've oft thought about an opt-in federation of instances that require human approval for registrations. or a closed "federation" in the irc distributed sense.
+
+it'll never happen because gargron wants more users, and approval-based signup makes a lot of disinterested people bounce before actually trying the software. but it's worth considering imo at least as a thought experiment
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/fedi-as-reformist-option.md b/wiki.hugo/content/_dump/fedi-critiques/fedi-as-reformist-option.md
new file mode 100644
index 0000000..7c30ff8
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/fedi-as-reformist-option.md
@@ -0,0 +1,51 @@
++++
+date = 2023-04-30
++++
+
+https://mastodon.social/@trwnh/110290827199480228
+
+nobody asked but i think fedi as a whole is actually kinda "bad" in the sense that it's holding us back from better things. it's like the "reform" option when we need radical change. and it keeps getting "worse". somewhere along the way we seem to have dropped the "blogging" from "microblogging", and what remains is incredibly muddled. contextual and ergonomic failure. we're copying "social media" and inheriting its flaws. ad-free and chronological ain't enough.
+
+see, we're all mostly here to just hang out and spill a stream of consciousness, right? but there are problems inherent to the structure. context collapse (or no context at all), misuse of the medium (doing a "thread" instead of writing an article), and so on. everything just goes into the square hole.
+
+i posit we can do better. but it's gonna require going back to basics and building out communication paradigms from the ground up. with thought given to effective communication, not profitability
+
+but. (and this is where i am afraid of shit-stirring)
+
+no one wants to do that
+
+the people working on fedi past and present seem mostly invested in mass adoption, and the way to do that is to keep building on broken foundations. and it feels kinda cultish at this point, like the goal is "success" defined by "growth", and it's a branding game, it's lip service.
+
+"mastodon", even "activitypub" itself, is seemingly about mindshare more than anything tangible.
+
+i don't particularly want to call out specific people for this, because it's not just a few people, it seems to be a cultural issue. the framing is that we can replace those social media platforms instead of tearing them down as we ought to. mastodon wants to become the next twitter. pixelfed wants to become the next instagram. and so on.
+
+on some level i think the people are just looking for validation of their work. but this leads to a kind of conservative outlook toward actually improving...
+
+yes, this thread could have been a blog post. that's part of the problem
+
+---
+
+i mean we stop doing "social media" as twitter and facebook made, and go (go back?) to clearly publishing and clearly discussing, as two separate things. remember blogs and forums? on blogs, you publish. on forums, you discuss. on "social media", this distinction gets collapsed. a "post" and its "replies" are all in this one big global context by default. who is the audience? what is the purpose? these questions don't have clear answers on "social media". corpos profit from this ambiguity.
+
+in "social media", the audience is "whoever we put this in front of" and the purpose is "an endless feed of posts for you to graze from". contrast this with the intentionality of cultivating your own audience, and of communicating with them. fedi gets us halfway. we move away from the profit-oriented mindset, but we keep the trappings and mechanisms that were created in service of them.
+
+tldr we're on the Web and we should remember that. death to "platforms". empower actual people to set up their own spaces and domains.
+
+---
+
+there is an argument to be made that the right thing would not have been made clear if we hadn't kept making mistakes like chasing the big corporate players. i'd be open to this argument 10 or 15 years ago around the time of identica or diaspora, but since then it's just become more apparent that this whole space will never be anything more than a transitional holding-place for people who leave the walled gardens for... fenced gardens, i gues? and the better thing hasn't been built yet.
+
+---
+
+here on the World Wide Web you have two threats: capitalist enclosure, and toxic community. and honestly the latter is probably less bad, because at least you have the self-determination to make your own community with your valued friends if the current one gets too bad. with the former, you have no escape.
+
+in short, "social media" is a failed model invented by capitalists. what we need is a "social web". focus on people, not "content".
+
+want to entertain yourself? that's fine, there can be media hubs and curators for that. but your communications and your media consumption should be separate.
+
+---
+
+honestly as much as meta gets tiring, at least these are conversations that can actually be had with a nonzero chance at actually shaping things.
+
+you think twitter or instagram gives a shit what its users want or think? nope, it's all about driving ad revenue
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/implicit-vs-explicit.md b/wiki.hugo/content/_dump/fedi-critiques/implicit-vs-explicit.md
new file mode 100644
index 0000000..8991c4f
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/implicit-vs-explicit.md
@@ -0,0 +1,35 @@
+the way to maintain an authoritative collection is to send out Add/Remove, not to have everyone send out Create and then expect everyone else to reconstruct the collection for themselves
+
+i can't say i blame developers for taking the lazy route and doing the bare minimum to be compatible with what already exists, but that is so limiting and i'm not here for it
+
+the bigger problem is that there's so many assumptions being made with zero basis or foundation in anything. we're just replicating stuff around and then every server assembles it however it *thinks* it should be put together.
+
+we're getting to the point that the contradictions and shortcomings are starting to become more apparent...
+
+- things like moderated conversations are impossible if you don't actually have a concept of a "conversation".
+
+- there's so many different ways to do "groups" that it's a running joke at this point, because everyone has a different idea of what a "group" is. it's the "blind men feeling an elephant" problem.
+
+- things like forums and subforums, chat rooms, etc are not easily possible rn.
+
+the "trick" is that there isn't actually any difference between all these different presentations. if you understand "objects" and "collections" you can construct whatever you want: forums, walls, chat rooms, conversations, aggregators, whatever. it's all just objects in collections.
+
+right now, no one understands "collections". we just pass around objects with Create and Announce and leave it up to the consumer to figure out how they should be grouped.
+
+it's not even a new idea. Dennis Schubert raised a similar criticism of "replies" distribution back in 2018: https://overengineer.dev/blog/2018/02/01/activitypub-one-protocol-to-rule-them-all.html#replies-and-interactions
+
+> As per the ActivityStreams spec, all objects [can] have a replies property. So, a more sensible, reliable, and even more AcitivityStream’y way of handling replies would probably be adding the interaction to the replies collection
+
+this is not always optimal of course -- it was proposed 5 years ago. but something similar could be done.
+
+i think the key disagreement, misunderstanding, lack of shared reality, etc, is this:
+
+are we just creating a bunch of "posts"? microblogging or regular blogging, we have our own websites or web profiles, and we only care about what we ourselves are sharing?
+
+or are we trying to collaborate across domains? are we building a Web, a Social Web, a Linked Data Web, a Semantic Web? where our actions have side effects, and there exists some state that we care about?
+
+we lack that clarity of purpose
+
+basically we're not doing one or the other, we're kind of mishmashing them together. when you post on most fedi projects, you are publishing to your profile locally, *but* you are also sending out an activity to notify your followers. and typically, that has side-effects on remote servers. usually that side-effect is "keep a locally cached archive of that post and show it to followers."
+
+i think we should be clearer about the separate use-cases and concerns.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/mainstreaming-mastodon.md b/wiki.hugo/content/_dump/fedi-critiques/mainstreaming-mastodon.md
new file mode 100644
index 0000000..d5380ee
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/mainstreaming-mastodon.md
@@ -0,0 +1,41 @@
++++
+date = "2023-02-02"
++++
+
+the shit i see on the mastodon issue tracker is driving me to just build my own thing because i honestly think whatever good culture mastodon has is quite possibly not long for this world
+
+some people literally just walk in and ask "why is this not like twitter" and demand that it be changed to suit their whims. and i feel like gargron is starting to take their side because gargron just wants More. old users be damned, they're just a vocal minority now.
+
+i mean, i wanna be wrong, but i don't actually think there are any guiding principles behind mastodon except "whatever gargron wants", so it is at the very least a possibility, if not a credible threat
+
+there was a post i saw earlier yesterday about something like, idk, i think biz stone said he was advising gargron, and one of the replies was something along the lines of how we should be "turning Mastodon from a small platform for the fringes and oppressed minorities to a platform that welcomes more mainstream members" and i legit shuddered while reading that. what a terrifying thought.
+
+on some level, sure, it's probably cool for "mainstream" people to have something healthier than corporate social media. but i'm really concerned that they'll ruin it for the rest of us, exactly those "fringe and oppressed minorities" who were here for years. years ago we talked about the sort of "detoxification cycle" that new users would go through, and with every new wave, people acclimate less and less. they import more of their old behaviors uncritically.
+
+ultimately? i think things will probably settle in at a point that's better than others but worse than it could have been.
+
+this exact kind of mentality by newcomers who feel entitled to influence
+
+> you don't owe the top of the pyramid jack squat. The early movers *need* you more than you need them.
+
+if i may be so frank, can i just say: we don't "need" you *at all*. our experiences are rich and valuable and span over half a decade. you're certainly welcome to be around here, and you're welcome to use this software, but you have no right to demand we center you above ourselves.
+
+also the idea that there's some sort of "secret mastodon development cabal" is ridiculous. for better or worse, there's gargron, and i guess in some ways there's claire, and that's about it. everyone else is simply acting independently in their own interests and on their own agendas. the entire reason i worry can be summed up by the fact that gargron has unilateral decision-making power and final say. but, to his credit, he does consider the consequences.
+
+anyway, anything i say is with the disclaimer that i am not a representative of anyone else, but perhaps i should be more overt and assertive about it. when i say something "without 100% certainty" i am not implying a vague recollection of events, i am only indicating that i have no decision power.
+
+tangentially, the real problem with these design decisions in mastodon is that they're inconsistent, precisely because it's all on gargron, and gargron is not strongly in favour of these decisions. it all depends on the feedback and advocacy of community members to convince him to do anything, and then he'll do it however he wants to or ends up doing it.
+
+real consistency? we'd not have numbers in explore/trending either, nor on detailed status views, nor in api. no "1+". it'd probably be some boolean like `has_replies` or something, which translates to an icon indicator to show the thread.
+
+but doing it that way takes commitment. it takes decisiveness. and that's simply not there.
+
+there's a lot of these scattered around the project codebase -- places where gargron wanted to do something one way, a lot of the community had to vocally disagree, and we ended up with a half-measure
+
+there was a similar case around hiding your follower counts, where gargron decided to only allow hiding the contents because he thought follower counts were important signals of account quality. even though the counts can be faked (and they have been!)
+
+once again, though... you have to give the guy credit for not rejecting all this outright. it's the only reason we ended up with anything better than twitter instead of Yet Another Twitter Clone.
+
+to quote someone anonymously:
+
+> i don't like a lot of the decisions mastodon makes but i god damn respect "we have a philosophy and that's why we are doing it that way" in particular if the philosophy is thinking carefully about how decisions affect the minority
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-critiques/nation-stateificiation.md b/wiki.hugo/content/_dump/fedi-critiques/nation-stateificiation.md
new file mode 100644
index 0000000..f870d4d
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-critiques/nation-stateificiation.md
@@ -0,0 +1,5 @@
+oh right i forgot we live in a geopolitical climate of tens of thousands of digital nation-states each with their own culture and borders. for a second there i thought i was using a general communication service
+
+anarchist, but against fediverse "instances"
+
+the dilemma of fedi is that i don't want to host my own service using current software, but i don't want to be judged by whose service i use or by who else uses that service
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/_dump.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/_dump.md
new file mode 100644
index 0000000..e69de29
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/aspects-circles-audiences-vs-lists-vs-collections.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/aspects-circles-audiences-vs-lists-vs-collections.md
new file mode 100644
index 0000000..a56a5d6
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/aspects-circles-audiences-vs-lists-vs-collections.md
@@ -0,0 +1,23 @@
+2017-11-12 13:43 | https://mastodon.social/@trwnh/98991746572627131
+
+problem with diaspora*'s aspects (and by extension, Google+ circles which aped it) is that it's a bidirectional metaphor for a unidirectional relationship. you're supposed to pick who can see a post, but they might not even follow you. I would understand if instead it functioned and was advertised as a way to split your timeline into multiple timelines. As is, sharing to aspects/circles/etc. is needlessly confusing.
+
+although having a way to tag/categorize your own toots could come in handy as well, if you post about multiple disparate topics. it's a nightmare to maintain one Twitter account per interest/community.
+
+---
+
+2017-12-17 09:55 | https://mastodon.social/@trwnh/99189033326279405
+
+unrelated thought: been trying to hash out a solution to the "multiple accounts" issue with social media. namely: why/when do people use multiple accounts, and what features can be implemented to reduce the friction in using just one account? would appreciate feedback.
+
+off the top of my head:
+
+- private vs public accounts for trusted people (answered by privacy options on toots)
+- multiple interests (not really solved currently; perhaps implementing a tag system and letting people mute certain tags? Diaspora*-style aspects can get complicated)
+- separate identity (unsolvable and would be insecure to attempt with one account)
+
+wrt multiple interests, this really is my biggest pain point with ANY social media (coming from someone who has had like 15 birdsite accounts at once)
+
+perhaps not exactly tags, but having a category system like google+ would be nice and perhaps easiest to manage when considering tootboosts. but this also might complicate the issue? nevertheless, it could be optional (default behavior would be to boost to your profile, no categorization involved)
+
+the tag approach would be easiest for your own toots, but the categories wouldn't be too bad and would also allow for separating different boosts
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/deactivating-twitter.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/deactivating-twitter.md
new file mode 100644
index 0000000..7de3d77
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/deactivating-twitter.md
@@ -0,0 +1,21 @@
+2017-12-20 10:53 | https://mastodon.social/@trwnh/99206247716252048
+
+I just deactivated some really old accounts I had on birdsite, ones I'd stopped using years ago, but had left up as a sort of archive... The last relics of a bygone era, of a personality long dead... A mark of my former selves.
+
+Makes me think about the fact that nothing is truly forever, not even the internet and the data we think will last forever. At some point, the final copy of any given data will be deleted. Or it will lose relevance. Or it will slip into obscurity.
+
+Of course, it was already not as I had left it. Accounts I had once conversed with, deleted. Maybe some of those people met the same fate as their accounts. Who knows? A lot changes in three years.
+
+I can't back up the DMs that have been deleted, and the only copy of the replies are in the notification emails sent out to an inbox of a Gmail I'd long forgotten I had.
+
+Kind of a heavy feeling.
+
+The pictures will be gone in 30 days, but I can't help but think of the pictures lost forever from Twitpic or Yfrog or all of those other image hosts we all used before image hosting became a standard part of any web app.
+
+---
+
+2018-03-07 04:05 | https://mastodon.social/@trwnh/99640641359436224
+
+twitter's culture since 2014 has been so machine-oriented, they probably trust machines more than actual people. like "i don't want to hear what's wrong, i want to know what The Algorithm says is wrong"
+
+essentially, right around the time twitter decided it wanted to be a media company instead of a conversational platform. it cracked down on third party API usage, put in absurd 100,000-user limits, and started breaking everything that was good pre-2014.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/fcc-repeals-net-neutrality.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/fcc-repeals-net-neutrality.md
new file mode 100644
index 0000000..ae0e101
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/fcc-repeals-net-neutrality.md
@@ -0,0 +1,27 @@
+2017-12-15 01:35
+
+Hey, remember when Comcast filtered P2P traffic including BitTorrent, Skype, and Spotify?
+
+Remember when AT&T blocked FaceTime and Google Voice on their network?
+
+Remember when Verizon throttled all video except mysteriously for their subsidiary go90?
+
+Because I remember.
+
+If you're celebrating today, then what you're saying is, it's a GOOD thing to have no legal authority to challenge ISPs when they pull the shit they clearly already did.
+
+Because that's literally all that happened in 2015, w/ forbearance
+
+In fact, Wheeler ONLY pursued the clauses of Title II that dealt with nondiscrimination (common carrier status), and didn't apply rate regulation or taxes or last-mile unbundling.
+
+He did this because Verizon successfully sued to prevent the FCC from using Section 706, and the judge told Wheeler he needed to reclassify as Title II.
+
+It should be obvious that the "free market" will not solve a problem created by the market. This is market failure, plain and simple.
+
+---
+
+Which rules "allow" ISPs to monopolize regions? ISPs collude to not enter markets, renege on coverage expansion contracts, and prevent competition by claiming ownership of the backbone.
+
+In fact, I would support taking it out of the FCC's hands entirely, so that people like Pai can't take us backwards at their whims as the political winds change. The Open Internet Order of 2015 which was just repealed was not too much. It was not enough. There needs to be an act specifically protecting the free and open internet, and repealing the Telecommunications Act of 1996. Among other acts...
+
+So pardon me for thinking the decision today was not great. There's an overwhelming pile of evidence that Pai ignored wholesale in order to push an agenda that benefits the ISPs who simply want to profit more, users be damned.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/making-better-stuff-is-unprofitable.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/making-better-stuff-is-unprofitable.md
new file mode 100644
index 0000000..c975e25
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/making-better-stuff-is-unprofitable.md
@@ -0,0 +1,5 @@
+2017-12-22 12:06 | https://mastodon.social/@trwnh/99217860566004390
+
+Only to a certain extent. There will inevitably be a point where it is unprofitable to improve a product any further.
+
+i.e., if Apple's primary goal was to make useful products, it would make choices that result in a better product even if it was slightly more expensive. But their primary goal is profit, as it is for every corporation under capitalism. Making better stuff is unprofitable.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/stop-using-crossposters.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/stop-using-crossposters.md
new file mode 100644
index 0000000..e22d2e6
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/stop-using-crossposters.md
@@ -0,0 +1,21 @@
+2017-11-26 08:20 | https://mastodon.social/@trwnh/99069749589979672
+
+Stop using crossposters.
+
+Not to, like, force y'all to do something, but crossposters are self-defeating.
+
+It's far better to commit to a network rather than just make a carbon copy of yourself, because if you're posting exactly the same things, then what even is the point of having two networks?
+
+That's just unnecessarily redundant.
+
+I've been through this kinda rigmarole before when I tried using diaspora*, and the end result was that I completely abandoned it because I wasn't getting any meaningful interactions out of it compared to Twitter. Which was a shame, because I really liked diaspora*.
+
+The problem, of course, is that you will inevitably gravitate to whichever platform nets you more interaction. And crossposts really don't engender organic engagement. They feel robotic and distant, largely because they're just that
+
+---
+
+2017-11-30 13:36 | https://mastodon.social/@trwnh/99093644445157168
+
+ugh i really hope crossposters don't slowly choke mastodon like they did to diaspora*
+
+if you're just crossposting everything you tweet on birdsite then what even is the point of making a mastodon account? that's glorified spam at worst, and a recipe for abandonment.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/why-read-theory.md b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/why-read-theory.md
new file mode 100644
index 0000000..0edb2e7
--- /dev/null
+++ b/wiki.hugo/content/_dump/fedi-threads-to-republish-as-articles/why-read-theory.md
@@ -0,0 +1,5 @@
+2018-01-27 08:44 | https://mastodon.social/@trwnh/99420908783601966
+
+the point of reading theory is to see what ideas other people already came up with, so you don't have to spend time formulating them yourselves. like... you start out with political beliefs and experiences, but they can always be solidified if you have a framework to contextualize them.
+
+and that doesn't really require discussion unless you want to or need more understanding, and it doesn't require organizing if you're not capable of it, and it really doesn't require voting since many people can't vote and many voting systems are designed to minimize choice. it feels wrong to say one *can't* be politically engaged unless one does these things
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/hackerwars.38.md b/wiki.hugo/content/_dump/hackerwars.38.md
new file mode 100644
index 0000000..67a1cd3
--- /dev/null
+++ b/wiki.hugo/content/_dump/hackerwars.38.md
@@ -0,0 +1,221 @@
++++
+draft = true
++++
+
+## puzzles
+
+The First Puzzle:
+98.151.11.252 - Tic Tac Toe
+99.13.31.189 - `3`
+131.209.236.188 - `Eyjafjallajökull`
+38.184.207.244 - `12, 4`
+134.202.106.252 - `24`
+179.60.148.182 - `Area 51`
+47.72.72.190 - `4`
+177.222.33.107 - `Hacker Wars`
+205.117.130.137 - `Too Many Secrets`
+12.198.127.243 - Sudoku
+[sends you to WHOIS 1]
+
+1.2.3.4 [WHOIS 1] - 2048
+
+```
+$.ajax({
+type: "POST",
+url: 'gotcha.php',
+dataType: "json",
+data: {
+func: '2048',
+type: 6
+},
+success: function(data){
+if(data.status == 'OK') {
+result = $.parseJSON(data.msg);
+$('#puzzle-header').html(result[0].header);
+$('#puzzle-status').html(result[0].result);
+$('#puzzle-next').html(result[0].next);
+$('#puzzle-isSolved').attr('value', result
+
+[0].isSolved);
+$('#puzzle-solve').hide();
+}
+}
+})
+```
+sends you to WHOIS 2
+
+219.253.106.3 [Too Many Secrets] - `Stay Hungry, Stay Foolish`
+175.136.25.16 - `Aramis`
+101.33.53.239 - `62.5`
+12.8.92.181 - `50`
+190.177.124.74 [Lorem ipsum] - `5, 1, 94`
+213.207.2.12 - Minesweeper
+162.92.240.86 - `Phoebe, Milena, Naomy`
+78.77.189.202 - `4, 3`
+65.106.189.164 - `a, d, c`
+164.36.19.95 - `3, 3, 9`
+44.184.200.40 - `5, 2`
+156.9.137.74 [Hangman] - `99+99/99`
+186.43.119.219 - `49, 35`
+143.114.166.104 - `Every player who buys premium is awesome`
+185.42.143.179 - `9, 18`
+179.196.168.131 - `To be or not to be`
+188.85.245.142 - `Phoebe`
+200.11.13.159 [WHOIS 2] - Turn the switches on
+
+```
+$.ajax({
+type: "POST",
+url: 'gotcha.php',
+dataType: "json",
+data: {
+func: 'lightsout'
+},
+success: function(data){
+if(data.status == 'OK') {
+result = $.parseJSON(data.msg);
+$('#puzzle-header').html(result[0].header);
+$('#puzzle-status').html(result[0].result);
+$('#puzzle-next').html(result[0].next);
+$('#puzzle-isSolved').attr('value', result
+
+[0].isSolved);
+$('#puzzle-solve').hide();
+}
+}
+})
+```
+
+8.22.72.164 - `penny`
+94.236.84.16 - `Nishiyama Onsen Keiunkan`
+53.83.66.249 - `Hack The Planet`
+82.212.91.122 - `password123`
+200.28.37.47 - `47`
+127.73.175.172 - `SHOW NO REMORSE`
+61.170.113.240 [WHOIS 3] - `1, 2, 3`
+87.75.25.103 - `diamond, ruby, sapphire`
+207.0.9.101 - `Kung Fury`
+40.204.6.239 - `Morpheus`
+240.93.247.103 [WHOIS 4] - The End... for now
+
+191.169.88.208 [Fsck you] - placeholder puzzle
+
+### ??? hidden puzzles
+
+[hasher 11, need cracker 11.1 to get in]
+158.79.69.167 - `hacker`
+25.25.200.137 - `LCM+L`
+37.0.237.238 - `Burj Khalifa`
+158.79.69.167 - `Satoshi Nakamoto`
+13.14.243.214 - `SHA256`
+54.215.105.98 - `10/11/2019`
+[takes you back to WHOIS 4]
+
+### alt paths
+
+86.24.54.79 [WHOIS 3 -> Eduard Khil -> WHOIS 3] - `Despacito`
+
+52.6.13.235 [WHOIS 3 -> Gnirut -> WHOIS 2] - Turn the switches on (again)
+
+```
+$.ajax({
+type: "POST",
+url: 'gotcha.php',
+dataType: "json",
+data: {
+func: 'lightsout'
+},
+success: function(data){
+if(data.status == 'OK') {
+result = $.parseJSON(data.msg);
+$('#puzzle-header').html(result[0].header);
+$('#puzzle-status').html(result[0].result);
+$('#puzzle-next').html(result[0].next);
+$('#puzzle-isSolved').attr('value', result
+
+[0].isSolved);
+$('#puzzle-solve').hide();
+}
+}
+})
+```
+
+
+
+## cool shit
+
+44.133.241.160 - torrent 1,2,3
+61.170.113.240 - analyzer 3.0
+200.11.13.159 - spam 5.0, warez 5.0, miner 5.0
+188.85.245.142 - collector 5.0
+94.236.84.16 - collector 7.0
+86.24.54.79 - collector 10.0
+156.62.156.183 - hasher/firewall 10.0
+87.75.25.103 - hidder 10.0, antivirus 10.0, cracker 9.0, ssh 7.0
+207.0.9.101 - seeker 10.0, ddos 10.0
+40.204.6.239 - breaker 10.0, cracker 10.0
+240.93.247.103 - cracker 11.0, warez 10.0, miner 10.0
+130.216.37.220 - cracker 12.0
+78.192.143.228 - cracker 12.0, hasher 11.0, hidder 11.0, antivirus 12.0
+
+37.0.237.238 - warez 14
+158.79.69.167 - hidder 15, antivirus 14
+13.14.243.214 - seeker 15
+54.215.105.98 - ftp 13, ssh 13, cracker 17, firewall 12
+
+## me
+
+bank #757385614
+123.40.218.38
+
+1wXjdkDA9V4kKtRQ1LCbCpiTHTLviAmbxd
+X2ke7k3RB05YKa4zRIl5SlPFLykl4eIa1KGSdOwcc38um0igvBdWiUnewQScoUBA
+
+## banks
+
+bank #203344377 at 123.40.218.38
+
+686206684 at 123.40.218.38
+
+ #485880455 on bank [123.40.218.38]
+
+## bitcoin
+
+1tKr4CjHeCMv0X69bxZG8j0BWfyOqKiiRs
+iARby4xdWxXlOH7VdmRF3vVlu82hcnLzHi0NC8YqMKhd0vdJWtuMJgyAZXOvo95T
+
+1P8vEmxyBhldcmjjlgdYvg4MT908dQu
+AUICn2EfwcjbSR4kwY3AgzCydsxO2UamqN2z7iyNeOp7sGgL5O6XQNyXlaKXLzn
+
+165PrvvXaznPBoRRXjwKQssIiOA2VopOhY
+sNCi2fDCDf4lI3YBwKLVdJlUC26mgfg7X9pNuZHDYyQOLfWDZ5d0mFvQEWxVbvo3
+
+## ips to hack?
+
+187.219.92.196
+
+45.197.80.78
+
+## meta caps
+
+cracker 50.7
+hasher 44.9
+firewall 30.5
+
+
+
+
+
+```
+ips = document.getElementById("list").children;
+output = ""
+
+for (var i = 0; i < ips.length; i++) {
+ ipElement = ips[i]
+ ip = ipElement.children[0].children[0].children[0].children[1].innerText
+ virus = ipElement.children[1].innerText
+ output += ip + "\n"
+}
+
+console.log(output)
+```
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/mastodon-api-value.md b/wiki.hugo/content/_dump/mastodon-api-value.md
new file mode 100644
index 0000000..91b9673
--- /dev/null
+++ b/wiki.hugo/content/_dump/mastodon-api-value.md
@@ -0,0 +1,12 @@
++++
+date = 2023-02-06
+published = 2023-02-06T00:56:00Z
++++
+
+https://mastodon.social/@trwnh/109815069913581608
+
+to what extent can it be said that the primary value of mastodon is in its api
+
+mastodon isn't really all that special in the fediverse or as a software, because you have so many options and differing implementations of the activitypub protocol. but the second you try to have a mobile app, you immediately recognize the value of the mastodon api. it's a pseudo-standard at this point because it mostly just works, and pleroma/pixelfed/gotosocial copied it for compatibility with existing clients. it's a shame it isn't a real standard...
+
+or, rather, what would a real standardized microblogging api look like? the nearest thing is probably micropub/microsub which doesn't quite do as much
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/plaintext-xml-json.md b/wiki.hugo/content/_dump/plaintext-xml-json.md
new file mode 100644
index 0000000..15fb627
--- /dev/null
+++ b/wiki.hugo/content/_dump/plaintext-xml-json.md
@@ -0,0 +1,8 @@
+actually it's kinda interesting how every single spec largely breaks down along one of three ideological lines: plaintext, xml, or json
+
+i'm seeing a general analogy between DNS, XRI, and Webfinger resolution
+
+- DNS returns a plaintext answer
+- XRI returns an XRD
+- Webfinger returns a JRD
+
diff --git a/wiki.hugo/content/_dump/services-vs-communities.md b/wiki.hugo/content/_dump/services-vs-communities.md
new file mode 100644
index 0000000..3fa5ee0
--- /dev/null
+++ b/wiki.hugo/content/_dump/services-vs-communities.md
@@ -0,0 +1,13 @@
+https://mastodon.social/@trwnh/110329802576726213
+
+services aren't communities
+
+the gmail community
+
+imo the biggest mistake of fedi is tying together the social and technical layers. local timelines should have been group chats all along
+
+it's a huge misunderstanding because some people want services and some people want communities and they are not the same thing. some people can run a community but offer bad service. some people offer great service but can't run a community
+
+instances shouldn't exist as the only model. the service layer and the community layer should be separate. combining the two makes both of them worse -- as can be seen if you violate the rules of your community, you lose access not just to the community, but to the service entirely. and if the community cannot continue to provide service, you again lose both.
+
+i do think there is some value in being both, because then people feel more likely to donate as they are personally invested. but you could have incentives to donate even while keeping them separate.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/shorts-are-too-long.md b/wiki.hugo/content/_dump/shorts-are-too-long.md
new file mode 100644
index 0000000..e7b53a9
--- /dev/null
+++ b/wiki.hugo/content/_dump/shorts-are-too-long.md
@@ -0,0 +1 @@
+i fucking hate the "shorts" format. vine was okay purely because it was limited to 6 or 7 seconds -- if you're going to take away the video controls, prevent me from seeking, maybe autoloop? then i am NOT sitting there for a whole minute while you fail to get to the point. i'm not doing more than 10 seconds, maybe 15 seconds at the most. anything over that should let me seek through the video!!!! videos should always be seekable but if you're not going to make them seekable then at least limit them to one coherent logical "moment"
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/social-media-failure.md b/wiki.hugo/content/_dump/social-media-failure.md
new file mode 100644
index 0000000..81af6f1
--- /dev/null
+++ b/wiki.hugo/content/_dump/social-media-failure.md
@@ -0,0 +1,7 @@
+the more i think about and research communication paradigms, i'm starting to think more and more that this whole "social network" thing is just fundamentally flawed. in pure terms you might send a message or publish a resource. but with these social networks it's not that clear cut. you're never unambiguously sending a message or publishing a resource, but instead, some weird hybrid that we call a "post". not quite message, not quite resource. it exists in part or in whole exclusively on-network
+
+and i guess that makes it easier to put in a silo which is how companies maintain their profit motive.
+
+but in replicating the design of these social networks we replicate their properties too. fedi hasn't entirely moved past silos because it's embedded in the design level. thankfully not the protocol level, but still. it's going to persist in implementations as long as we limit ourselves to "twitter but better", "instagram but better", etc. we're not building the commons that we could build.
+
+and the lack of clarity in our metaphors and associated abstractions leads to subtle violations of what people expect. there should be a clearer split. consider the duality of tumblr as both a social network and a publishing platform. they're making this split more apparent than it used to be. in addition to username.tumblr.com for blogs they now have tumblr.com/username for network profiles.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/social.md b/wiki.hugo/content/_dump/social.md
new file mode 100644
index 0000000..6b83b34
--- /dev/null
+++ b/wiki.hugo/content/_dump/social.md
@@ -0,0 +1,83 @@
+is2g ifwhen i make my thing i am going to put a lot of effort into a filter system that actually makes sense. i will not be supporting "mute" or "block" as binary features, but rather, everything flows through the filter system. mastodon filter v2 system is an improvement but doesn't go far enough
+
+---
+
+in any case yes it would be better to encrypt everything or just not peer/replicate at all. fedi has a problem with this because for some unknown reason we all decided it would be a convoluted distributed state machine which is a bad idea when you don't trust all participants, and also worse when those participants are explicitly redistributing it while attributed to you. at that point you might as well go all-in on syndication rather than federation. put another way: federation makes sense for message passing but not for publishing (and fedi is an awkward and unclear hybrid between messaging and publishing)
+
+---
+
+idle thought: idk if i care so much about "fedi" as much as it is "people who are on fedi". either in the abstract or in the concrete, i just wanna make friends and talk to cool people. fedi is little more than a place for fateful encounters based on the streams of consciousness we put out there. the important thing is that no one meddles with this for profit or otherwise. the second fedi stops providing that, i'm out.
+
+it's a big part of why i don't really relate or sympathize with people who just want fedi to grow. i think any growth has to be sustainable. the values are valuable. if the values are compromised then fedi isn't valuable to me anymore.
+
+note that there's a big distinction between this and communicating with people you know. if some people are only on fedi then that has a different type of value. network value is not the same as the value of the network.
+
+it's always the people, i'm only here for the people. i do not want to keep track of the diplomatic politics of tens of thousands of nation-states. no one should! we made a wrong turn somewhere back in 2017 when people started making "community" instances, and arguably we were on the wrong path from the very beginning. maybe the whole thing is wrong tbh. we need to go back to actual forums. the ergonomics are all wrong. the model is wrong. we're just trying to mash everything roughly into the shape of twitter. and worse, every twitter has its own culture and community and is assumed to be homogeneous! how do you atomize all this?
+
+---
+
+[asking natalie what should be removed or what is missing from misskey](https://mastodon.social/@trwnh/109958119755489250)
+
+
+
+i like that it's an outsider take on fedi and is not afraid to push boundaries and go beyond what mastodong has envisioned
+
+what's missing is muting/blocking actually being functional. i'd also like to see Room come back lol
+
+what should be removed: basically nothing. maybe proxy accounts. if i wanted minimal i'd go use some useless software like honk, misskey maximalism is actually really fun
+
+
+
+---
+
+the general objection is "that's not how we currently federate", as if the way we currently federate should be preserved forever
+
+---
+
+"relays" on fedi are like the worst possible interpretation of relays. imagine one big irc room that has no topic whatsoever. just thousands of people posting whatever they want. why
+
+also imagine your irc client had autologging turned on, and didn't have an easy way to clear specific logs
+
+---
+
+this shit should be generic and it can be browsed by a social web browser or a linked data renderer
+
+i think it makes the most sense to lean into the Web and just focus on making the publishing as easy and straightforward as possible. i think most people (ideologues aside) don't actually want "federation" as commonly thought of. in absolute terms they want their posts to show up in a reader.
+
+there still is a place for federation, the "federation" i'm interested in is more like replication in a distributed database. and i'd like to link it all up across domains like "nomadic identity".
+
+example: imagine a network of generic servers
+
+your server shuts down, you walk up to any server that has your posts already, prove your identity, pick up like nothing happened
+
+basically you should be able to "claim" your federated profile on other domains, kind of like how on a centralized site you can claim your profile page if you're a celebrity or whatever
+
+nomadic identity is literally just doing this process yourself beforehand by setting up mirrors/replicas of your key
+
+---
+
+i forget who it was that said "a single timeline is unsustainable" (aaron parecki?) but i'm feeling more like the real cardinal sin is publishing to a single profile. i don't mind *reading* everything in a single view, although making lists certainly helps. it's the *publishing* that annoys me. i almost *never* want to send a post to *all* of my followers. and this goes doubly for replies. i often want to reply within a specific context and only *optionally* tell my followers about it.
+
+"one account per feed" is a goddamn travesty. an account should be able to have multiple profiles, and a profile should be able to have multiple feeds, and you should be able to follow individual feeds instead of being forced to follow an entire profile.
+
+yeah, i was thinking similarly. except i was going to make Collections into actors that could be followed. which would be incompatible with mastodon, because mastodon assumes wrongly that actors must be exactly one of The Five Types. but then again, i am somewhat losing interest in this whole "social media" thing and would prefer to focus on a purer model of publishing web resources and managing them with collections. so maybe "mastodon compatibility" is not all it's cracked up to be...
+
+if anything, i was thinking of treating "mastodon compatibility" similar to a crossposter up until such point that mastodon relaxes or removes its unnecessary type-checking. you'd have an actor that you can send your activities to, and it will translate them into mastodon-flavoured activitypub and deliver out that translated copy. this actor would have its preferredUsername and all that compat stuff.
+
+---
+
+btw i think that deletes being so costly is something that is entirely a consequence of having essentially replicated the data with a ttl of forever. that's the default mode of every "fedi" software. it makes no sense for most people and it stems from the ideological decisions of over a decade ago
+
+by which i mean: there's a word for having your published content be replicated to other sites, and it's "syndication". we had this technology for really simple syndication... rss. it later evolved into atom. the "fediverse" was founded on ostatus built on atom feeds. when we say we're "federating" we're really more accurately "syndicating". you just don't have control over the accounts being created on other domains, on your behalf.
+
+i keep talking about how the metaphors are wrong, like how we merged the concepts of publishing and messaging to the detriment of both. we're sending messages that contain the entirety of a resource that we meant to be published. of course it's going to lead to outcomes that don't make sense. maybe one day people will understand this
+
+also... authorized fetch won't solve this. if you have a password protected blog, and someone is saving every new post and republishing it, and you let this happen continually, then what's the point of the password?
+
+---
+
+i think it's very important that users be able to understand and reason about the software that they are using! when it "does the thing", it should do so predictably.
+
+the argument for generic AP is that generic AP allows you to manage resources predictably, without having to care what others will do. it's a standardized storage layer. without it, you need a mastodon account, a pixelfed account, etc... every "platform" owns your data separately.
+
+imagine if switching from outlook to thunderbird necessitated losing all your emails and maybe even your contacts.
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/_index.md b/wiki.hugo/content/_dump/socialhub-threads/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/dereferencing-non-https.md b/wiki.hugo/content/_dump/socialhub-threads/dereferencing-non-https.md
new file mode 100644
index 0000000..a597fa7
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/dereferencing-non-https.md
@@ -0,0 +1,127 @@
++++
+title = "Dereferencing non-HTTPS URIs as `id`"
+date = "2019-10-11"
++++
+
+{{toc}}
+
+## Preserved text
+
+
+
+---
+
+@trwnh:
+
+> 3.1 Object Identifiers
+>
+> All Objects in [ActivityStreams] should have unique global identifiers. ActivityPub extends this requirement; all objects distributed by the ActivityPub protocol MUST have unique global identifiers, unless they are intentionally transient […] These identifiers must fall into one of the following groups:
+>
+> 1. Publicly dereferencable URIs, such as HTTPS URIs, with their authority belonging to that of their originating server. (Publicly facing content SHOULD use HTTPS URIs).
+> 2. An ID explicitly specified as the JSON null object, which implies an anonymous object (a part of its parent context)
+>
+> Identifiers MUST be provided for activities posted in server to server communication, unless the activity is intentionally transient. However, for client to server communication, a server receiving an object posted to the outbox with no specified id SHOULD allocate an object ID in the actor’s namespace and attach it to the posted object.
+>
+> All objects have the following properties:
+>
+> id
+>
+> The object’s unique global identifier (unless the object is transient, in which case the id MAY be omitted).
+>
+> type
+>
+> The type of the object.
+
+One thing I've wondered about is point 1 under 3.1 -- the id MUST be publicly dereferencable, with its authority belonging to the origin server... but it only SHOULD be https.
+
+So, does this mean that there are other possible choices for a publicly dereferencable id with proper authority, that *isn't* HTTPS? I assume that the intention was to suggest using HTTPS over HTTP (e.g. section 3.2 assumes HTTP GET and content negotiation, as well as headers and 403/404 error codes; section 5.1/5.2 specifies HTTP POST to outbox/inbox; Section 6 uses MUST for making an HTTP POST to actor outboxes and 201 codes), but my curiosity is with other URI schemes entirely.
+
+Perhaps one practical consideration (as there are various impractical ones, such as file://, ftp://, ftps://, sftp://, and so on) is to not use a URL but instead use a URN (such as doi, isbn, and other urn: URIs). Of course, this requires us to do a little more work to treat them as "dereferencable", such as by including a HTTPS proxy or some other resolver service. I wonder how that might be done, and whether this is at all worth pursuing. It could be used for deduplication, for example, by assigning a network-wide URN, with the authority deferred to the lookup service/proxy used as an instrument.
+
+---
+
+@cwebber:
+
+> So, does this mean that there are other possible choices for a publicly dereferencable id with proper authority, that isn’t HTTPS?
+
+Yes and the [Golem demo](https://gitlab.com/spritely/golem/blob/master/README.org) shows exactly an example of this, using a (very-cut-down demo) of using [Datashards](https://datashards.net/) with ActivityPub (it was called “magenc” back then) to distribute activities. A similar example could be done with IPFS, for instance (though that doesn’t provide the privacy/security properties that Datashards does).
+
+Similarly, [bearcaps](https://github.com/cwebber/rwot9-prague/blob/bearcaps/topics-and-advance-readings/bearcaps.md) are a possible non-https URI scheme that we might use.
+
+[...] Wanting to support Tor Onion Services is a reason I explicitly pushed back against pressure to make the spec https-only, which some people wanted.
+
+---
+
+@trwnh:
+
+I guess what I’m trying to comprehend the most would be, how would compatibility work between the HTTPS linked-data web, and the non-HTTPS documents? If we start passing around AP JSON-LD documents with non-HTTPS `id` then it would obviously break due to basically all implementations assuming that all they need to do is HTTP GET `id`.
+
+I remember reading the [RWoT paper about DIDs in ActivityPub](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/final-documents/activitypub-decentralized-distributed.pdf) and having the same confusion at the time about how it would work practically. The closest thing I could find was [`instrument`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument) in the AS2 Vocab, but that has a domain of `Activity` only, and is described as "Identifies one or more objects used (or to be used) in the completion of an `Activity`", so it would have to be redefined to work on `Object` as well.
+
+---
+
+@rinpatch:
+
+Wouldn't an array of `id` work?
+
+---
+
+@trwnh:
+
+Actually, multiple `id` seems interesting to me for a different thing: nomadic identity. Consider a case where an Object has multiple HTTPS URIs.
+
+That might not be the best way to do it, though. In fact, one shortcoming that is immediately apparent to me is the question of what to do if the document retrieved from one `id` is different from that retrieved from another `id`. So it would be better to have one canonical `id` only, where possible. But technically, the problem of differing documents can still happen, due to something as simple as a desync.
+
+[[future errata: this is what `alsoKnownAs` could be used for?]]
+
+I’d really like to focus on modeling how to dereference non-HTTPS in a way that is still roughly compatible with the HTTPS Web-based network. So far the following options have been mentioned:
+
+* `id` as Array; pick whichever one you understand.
+* `url` as Array; pick whichever one you understand but leave `id` as HTTPS.
+* just break compat and let implementations figure out how to resolve `id` (if they can)
+* use a local proxy directly as `id` (technically still globally unique but represents change of authority)
+* use a proxy Service as `instrument` (and extend `instrument` to be applied to `Object` and not just `Activity`)
+
+---
+
+@how:
+
+I’m a bit concerned about extending to objects what could be done with creating an object-specifc actor acting as a proxy. The `instrument` service seems to be adapted to this use-case: you get a representation of the object’s metadata but must use the out of band service to retrieve the actual object. Best of both worlds?
+
+---
+
+@nightpool:
+
+The ActivityPub standard does not define that any given server must support any one scheme. I don’t understand what the purpose of having it do so would be? it would just limit the flexibility of the protocol for no practical benefit (If two servers don’t support the same schemes, then they’re obviously not going to be able to talk to each other, MUST or no MUST)
+
+---
+
+@trwnh:
+
+I think there’s probably mixing of concerns to treat non-HTTPS as primarily an issue of nomadic content; while there is *potential* application toward this, I think the incompatibility issue is probably more pressing in the long run. You can claim that a software is “compatible with ActivityPub”, but this is a statement that needs clarification and qualification. And this is also something that would become even more of an issue if ActivityPub is implemented via networks other than HTTP(S).
+
+In that sense, there is no “ActivityPub network” – there is only currently an “ActivityPub over HTTPS network” (using HTTPS ids), as well as a sub-network of “ActivityPub over HTTPS network, with WebFinger” (perhaps more colloquially referred to as “the Mastodon network”).
+
+Even if every (or the majority of) software implementation(s) moves to adopt `bear:` URIs as `id`, there is now still the question of which URI schemes are supported with the `u` parameter of the bearcap. The draft for bearcaps defines `u` as “The stable URL that the bearer capability URI is associated with for requests”, which is, again, not specifically HTTP(S). But even then, specifying a “stable URL” means that we are precluding URNs as a form of reference.
+
+As nightpool mentions:
+
+> If two servers don’t support the same schemes, then they’re obviously not going to be able to talk to each other
+
+So I guess my main concern is that so-called “ActivityPub” software will settle around the lowest common denominator or the most restrictive set of requirements for interoperability. I’d like to lessen that if possible, so that individual implementations have the option to explore alternative lookup strategies for other “publicly dereferencable” schemes without that implying a choice between “hard break in network compatibility” or “stuck using HTTPS for `id` because everyone else is”. Although a hard break might be desirable in some cases, e.g. “if you don’t understand bearcaps then you can’t interact with this object”.
+
+---
+
+## current thoughts
+
+we've well and truly collapsed into the "https only" world by now. any attempt to use a different scheme represents a sort of netsplit. this is not all good or bad though; it just means that the only network we have is the World Wide Web.
+
+`alsoKnownAs` may be useful here as well:
+
+> i see a few possible approaches:
+>
+> 1. defer `alsoKnownAs` to mastodon's usage (concept 2, controlling the listed actor). define a new term `aliases` (pending name) to represent concept 1, different identifiers for the same subject. we might also define `subject` or some similar term to identify a "canonical" identifier?
+>
+> 1. defer `alsoKnownAs` to the DID core definition (concept 1, different identifiers for the same subject). implement a transitional period in which mastodon and other projects switch to a different mechanism more along the lines of rel-me. eventually deprecate the use of `alsoKnownAs` for determining rel-me.
+
+aside from that, the `instrument` idea still has some potential
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/exposing-edit-history.md b/wiki.hugo/content/_dump/socialhub-threads/exposing-edit-history.md
new file mode 100644
index 0000000..1690d2e
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/exposing-edit-history.md
@@ -0,0 +1,24 @@
++++
+title = "Notifying remote servers that they should refetch an object"
+date = "2019-11-01"
++++
+
+{{toc}}
+
+## Preserved text
+
+
+
+@trwnh:
+
+Per [expose edit history in ActivityPub representation · Issue #23292 · mastodon/mastodon · GitHub ](https://github.com/mastodon/mastodon/issues/23292)
+
+@Johann150 raises a feature request for being able to view earlier versions of an activity or object before an Update was received. In the case where an object is Created and then Updated, someone receiving the Update who didn’t receive the Create first would have no way of knowing what was contained in the original version. Someone fetching the object without having received either of the activities would be able to know that it was edited based on the presence of the `updated` property, but likewise would not be able to retrieve any additional information about previous versions.
+
+Looking at the existing Activity Vocabulary we see that the only existing way to do this would be in the case that `context` was published, although this requires that the context MUST be a Collection, and you would have to dig through all the items to filter for Update activities (plus the initial Create). Additional issues arise from the ordering of Collections not always being consistent, but in general you will still have to traverse the entire context collection.
+
+Therefore it likely makes sense to propose a new property called something like `history` or `revisions`. If there is any prior art or some existing specifications that could apply here, it would be helpful to know about them.
+
+## current thoughts
+
+idk
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/follow-arbitrary-collections.md b/wiki.hugo/content/_dump/socialhub-threads/follow-arbitrary-collections.md
new file mode 100644
index 0000000..1840bd0
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/follow-arbitrary-collections.md
@@ -0,0 +1,436 @@
++++
+title = "Unresolved issues surrounding Follow activities"
+date = "2019-10-10"
++++
+
+{{}}
+
+## Preserved text
+
+
+
+
+# First, some context…
+
+What the C2S spec says:
+
+> 6.5 Follow Activity
+>
+>
+>
+> The Follow activity is used to subscribe to the activities of another actor.
+>
+>
+>
+> The side effect of receiving this in an outbox is that the server SHOULD add the object to the actor’s following Collection when and only if an Accept activity is subsequently received with this Follow activity as its object.
+
+What the S2S spec says:
+
+> 7.5 Follow Activity
+>
+>
+>
+> The side effect of receiving this in an **inbox** is that the server *SHOULD* generate either an `Accept` or `Reject` activity with the Follow as the `object` and deliver it to the `actor` of the Follow. The `Accept` or `Reject` *MAY* be generated automatically, or *MAY* be the result of user input (possibly after some delay in which the user reviews). Servers *MAY* choose to not explicitly send a `Reject` in response to a `Follow` , though implementors ought to be aware that the server sending the request could be left in an intermediate state. For example, a server might not send a `Reject` to protect a user’s privacy.
+>
+>
+>
+> In the case of receiving an `Accept` referencing this `Follow` as the object, the server *SHOULD* add the `actor` to the object actor’s [Followers Collection ](https://www.w3.org/TR/activitypub/#followers). In the case of a `Reject` , the server *MUST NOT* add the actor to the object actor’s [Followers Collection ](https://www.w3.org/TR/activitypub/#followers).
+> > Note
+> >
+> >
+> >
+> > Sometimes a successful `Follow` subscription may occur but at some future point delivery to the follower fails for an extended period of time. Implementations should be aware that there is no guarantee that actors on the network will remain reachable and should implement accordingly. For instance, if attempting to deliver to an actor for perhaps six months while the follower remains unreachable, it is reasonable that the delivering server remove the subscriber from the `followers` list. Timeframes and behavior for dealing with unreachable actors are left to the discretion of the delivering server.
+
+Special collections:
+
+> 5.3 Followers Collection
+>
+>
+>
+> Every [actor ](https://www.w3.org/TR/activitypub/#actors) *SHOULD* have a `followers` collection. This is a list of everyone who has sent a [Follow](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow) activity for the actor, added as a [side effect](https://www.w3.org/TR/activitypub/#follow-activity-outbox). This is where one would find a list of all the actors that are following the actor. The `followers` collection *MUST* be either an [ `OrderedCollection` ](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection) or a [ `Collection` ](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection) and *MAY* be filtered on privileges of an authenticated user or as appropriate when no authentication is given.
+> > Note: Default for notification targeting
+> >
+> >
+> >
+> > The follow activity generally is a request to see the objects an actor creates. This makes the Followers collection an appropriate default target for [delivery](https://www.w3.org/TR/activitypub/#delivery) of notifications.
+>
+>
+> 5.4 Following Collection
+>
+>
+>
+> Every actor *SHOULD* have a `following` collection. This is a list of everybody that the actor has followed, added as a [side effect](https://www.w3.org/TR/activitypub/#follow-activity-outbox). The `following` collection *MUST* be either an [ `OrderedCollection` ](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection) or a [ `Collection` ](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection) and *MAY* be filtered on privileges of an authenticated user or as appropriate when no authentication is given.
+
+In summary… C2S Follow puts a Follow activity in your outbox, your server waits for an Accept, then adds that actor to following. S2S Follow takes a Follow activity in your inbox, your server wraps it in Accept/Reject and delivers that. S2S Accept Follow adds that actor to followers. (All of this is SHOULD language.)
+
+However, this leaves some things too ambiguous…
+
+# Following only a *subset* of activities
+
+By default, when you Follow an Actor, most implementations interpret that as a sign of interest in every single activity that the actor publishes, similar to the note in 5.3 (“The follow activity generally is a request to see the objects an actor creates.”). But there is no way to signal an interest in receiving only *some* of the activities. Perhaps the only possible concession here is the `streams` property of an actor, but there is basically nothing to guide implementations aside from a passing mention that is only 10 words long:
+
+> **streams**
+> A list of supplementary Collections which may be of interest.
+
+This suggests a pull-based approach, where you can GET the `streams` of an actor… but you cannot have the actor deliver any activities from those streams. Nor is it explicitly defined whether these collections contain activities or objects, or what the collections are actually for (aside from heuristically guessing based on the name of the collection?) Perhaps there could be a way to consistently understand these collections and maybe follow just those streams instead of the actors, but that would require…
+
+# Following non-actor objects
+
+Per 6.5, “The Follow activity is used to subscribe to the activities of another actor.” But sometimes you don’t necessarily care what a single actor does with multiple objects, you care about what multiple actors are doing with a single object.
+
+AFAIK some implementations interpret Follow Object to generally mean that the software will deliver any activities targeting that object to any actor that has expressed interest through the Follow Object activity. Perhaps this should be formalized, as the following are currently not agreed upon:
+
+* Who should you send the Follow Object to? The `attributedTo` actor? Does following that object imply also following the actor?
+* How should you keep track of followed objects? Should they be added to the `following` collection like actors? Should individual objects define a `followers` collection?
+* How do you know if an object is followable? If you send a Follow Object to remote software, it may not understand it. Is the presence of a `followers` collection enough for this? Does it also need `attributedTo`? Some other method?
+
+# Practical applications
+
+As prior art, Google+ Collections come to mind. For each post made to Google+, a user could choose to address it to Public, or to selected users (like actors), or to a Circle (like a collection of actors), or to a Community (like a group), or to a Collection (like a category/stream). This could be seen as confusing since it wasn’t really well-explained to users what any of these concepts meant, and Google+ also used Circles both for addressing those users *and* for viewing posts from those users, whereas most other services have a separate Lists feature for viewing posts from a subset of users. In essence, users can categorize their posts at the same time as they choose who to address them to. Consider the following hypothetical documents:
+
+```
+{
+"id": "https://social.example/actors/1",
+"type": "Person",
+"inbox": "https://social.example/inboxes/1",
+"outbox": "https://social.example/outboxes/1",
+"followers": "https://social.example/actors/1/followers",
+"streams": ["https://social.example/collections/1"]
+}
+```
+
+```
+{
+"id": "https://social.example/objects/1",
+"type": "Note",
+"content": "a simple note",
+"attributedTo": "https://social.example/actors/1",
+"followers": "https://social.example/objects/1/followers"
+}
+```
+
+```
+{
+"id": "https://social.example/collections/1",
+"type": "OrderedCollection",
+"items": ["https://social.example/objects/1"],
+"followers": "https://social.example/collections/1/followers"
+}
+```
+
+```
+{
+"id": "https://social.example/activities/1",
+"type": ["Create", "Add"],
+"actor": "https://social.example/actors/1",
+"object": "https://social.example/objects/1",
+"target": "https://social.example/collections/1",
+"to":
+ [
+ "https://social.example/actors/1/followers",
+ "https://social.example/objects/1/followers",
+ "https://social.example/collections/1/followers"
+ ]
+,
+"cc": ["as:Public"]
+}
+```
+
+# Etc
+
+Any comments, additions, etc. about this?
+
+
+
+---
+
+@trwnh:
+
+I should also add some discarded approaches that I considered at one point while thinking about this but determined to be too problematic:
+
+* interpreting a Follow as subscribing to multiple actors instead of just one
+* multiple outboxes (although this might still be applicable to other problems, just not this one for now)
+* using Profiles instead of Actors (though this could still be done, it would be unsupported in current implementations; it would however become possible to Follow Profile instead of Follow Actor)
+* having objects just be made into actors, a la the concept of message passing in computer science (although this adds a lot of complexity because objects generally only need a small part of what Actor provides)
+* hackily having multiple actors representing the same Person, but using them to create objects, then Announcing those from a more “central” actor (too complicated and unwieldy)
+
+---
+
+@trwnh:
+
+Sure, but how should we discover this?
+
+As stated above I went with `attributedTo` and the presence of a `followers` property, but perhaps it may be better to use an explicit endpoint like `inbox`?
+
+---
+
+@trwnh:
+
+It’s almost 3 years later and I think I’ve come around on this a bit –
+
+> As stated above I went with `attributedTo` and the presence of a `followers` property, but perhaps it may be better to use an explicit endpoint like `inbox`?
+
+I think explicit is better than implicit. All that’s required for an Object to be an Actor is to have `inbox` and `outbox`. The only issue with current language in the spec is that
+
+> The outbox stream contains activities the user has published,
+
+and semantically speaking actors are not equivalent to users, nor is the attribution required to match the same actor (or even *be* an actor – `attributedTo` can include another activity, for example).
+
+Where the previous approach fails is that the `followers` collection may not be included or published. The `followers` property is only a SHOULD and not a MUST.
+
+For delivery of the Follow activity, we can refer to the guidance on delivery:
+
+> The [inbox](https://www.w3.org/TR/activitypub/#inbox) is determined by first [ retrieving the target actor’s JSON-LD representation](https://www.w3.org/TR/activitypub/#retrieving-objects) and then looking up the `inbox` property. If a recipient is a `Collection` or `OrderedCollection`, then the server *MUST* dereference the collection (with the user’s credentials) and discover inboxes for each item in the collection. Servers *MUST* limit the number of layers of indirections through collections which will be performed, which *MAY* be one.
+
+Which, again, implies that we should just attach `inbox` on anything followable. And if we do that, then we should/must attach `outbox` as well to make it an actor (although in practice this may not be strictly required – it is possible to model having an inbox but no outbox, and some implementations might do this already in apparent violation of the spec).
+
+---
+
+@macgirvin:
+
+I do recall when Mastodon first implemented ActivityPub and some folks were still using OStatus. In this case the inbox was set to NULL. We implemented AP at exactly the same time and this threw exceptions in my code. Was going to file a bug, but technically speaking I think it’s spec compliant. The language states that an actor must have the “following properties” and these records had the required properties, except they weren’t de-reference-able. In any case I consider this to be a legal interpretation and have code to handle it appropriately.
+
+A more serious issue is that we implement access permissions to several collections and these are not de-reference-able unless the requestor has permission to access the collection. The spec is incredibly weak where it comes to dealing with permissions, but I have every right to restrict access of a resource to anybody I desire - even if it means my software isn’t technically compliant. This makes the quoted section in your reply contentious. These are deliverable through the forward-to-owner sections referenced elsewhere in the spec so everything still works; but not all collections are de-reference-able by every actor that receives an activity — nor should they be.
+
+---
+
+@trwnh:
+
+[quote="macgirvin, post:8, topic:114"]
+In this case the inbox was set to NULL.
+[/quote]
+
+Hmm. My interpretation is that `inbox` and `outbox` properties MUST be provided, but not necessarily be public. I’m not sure whether it makes sense to set `inbox` to `null` explicitly; is that not the same as excluding it? In any case, the practical implication of the current network (“ActivityPub over HTTPS”, or as I’ve taken to calling it recently, “ActivityPub over HTTPS with Webfinger and HTTP Signatures” :stuck_out_tongue: ) is that one can simply POST to an inbox IRI and have it either return successfully or error out with a 405 Not Allowed (if federation is not implemented). I’d be curious to hear any objections or concerns regarding this.
+
+[quote="macgirvin, post:8, topic:114"]
+I have every right to restrict access of a resource to anybody I desire - even if it means my software isn’t technically compliant.
+[/quote]
+
+I’m not sure if it’s technically “incompliant” to do so, but for what it’s worth, Pixelfed for example provides `inbox` for actors (currently equivalent to users, but under this proposal, it doesn’t have to be), and this `inbox` only supports POST and not GET, for obvious reasons – federation works by POSTing to the `inbox` and GET is only needed for C2S fetching your own inbox with authorization. That doesn’t seem like a problem to me; if anything, it seems natural since the inbox is only for delivery. Setting `inbox: null` or leaving it out implies that the object is not an actor, since it does not have both `inbox` and `outbox` (the only two required properties for actors). Aside from this heuristic, there doesn’t seem to be any other meaning to being an actor. So I would agree that yes, access to resources may be restricted without authorization. This doesn’t seem like an issue, although I may be misunderstanding or overlooking something.
+
+[quote="macgirvin, post:8, topic:114"]
+This makes the quoted section in your reply contentious. These are deliverable through the forward-to-owner sections referenced elsewhere in the spec so everything still works; but not all collections are de-reference-able by every actor that receives an activity — nor should they be.
+[/quote]
+
+Inbox forwarding could perhaps be applicable, but not any more so than it already is.
+
+To clarify, the assumed / proposed flow is something like this:
+
+1. I GET an actor at `https://example.social/actors/1` and see that their `streams` advertises `https://example.social/collections/1`:
+
+```
+GET https://example.social/actors/1 HTTP/1.1
+Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"
+
+{
+"@context": [...],
+"id": "https://example.social/actors/1",
+"type": "Person",
+"inbox": "https://example.social/inboxes/1",
+"outbox": "https://example.social/outboxes/1",
+"streams": ["https://example.social/collections/1"],
+...
+}
+```
+
+2. I want to `Follow` the `Collection` at `https://example.social/collections/1` for updates. (Let’s say this `Collection` is advertised within `streams` and represents some categorization of posts, similar to Wordpress categories or Google+ Collections. Its items contain some arbitrary objects like `Note`s that have been published within the category/stream.)
+3. I perform `GET https://example.social/collections/1`, optionally with an HTTP Signature for my actor `https://ap.trwnh.com/actors/1`. The server responds with a `Collection` containing only the items I am authorized to see, based on the HTTP Signature attached. If no signature is attached, then only items with `audience: as:Public` will be returned (likewise for `to`/`cc`/etc if the server software uses those for addressing instead of `audience`).
+
+```
+GET https://example.social/collections/1 HTTP/1.1
+Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"
+Signature: keyId="https://ap.trwnh.com/actors/1/publicKey",...
+
+{
+"@context": [...],
+"id": "https://example.social/collections/1",
+"type": "OrderedCollection",
+"totalItems": 1312,
+"first": "https://example.social/collections/1?page=1",
+"last": "https://example.social/collections/1?page=132",
+"inbox": "https://example.social/inboxes/1",
+"outbox": "https://example.social/outboxes/2"
+}
+```
+
+4. From this response, I parse for the `Collection`’s `inbox` property. If it does not have one, I assume it cannot be followed. If it does have one, then I assume I can send a `Follow` there. In this example, `https://example.social/collections/1` has `inbox: https://example.social/inboxes/1`. (This happens to be the inbox for `https://example.social/actors/1`, but it doesn’t have to be. This is an implementation detail.) To follow the stream for updates:
+
+```
+POST https://example.social/inboxes/1 HTTP/1.1
+Content-Type: application/ld+json; profile="https://www.w3.org/ns/activitystreams"
+
+{
+"@context": [...],
+"type": "Follow",
+"actor": "https://ap.trwnh.com/actors/1",
+"object": "https://example.social/collections/1"
+}
+```
+
+5. The remote server then responds as per the individual implementation’s logic, e.g. with an `Accept Follow`
+
+This is of course open to different methods of access control, object capability delegation, etc. – the key point is that the followable object has an `inbox` to `POST` a `Follow`, which I prefer over heuristics like dereferencing `attributedTo` and looking for an `inbox` there. It is simpler to just provide the `inbox` directly. And you might as well provide an `outbox` too and make it a full-fledged actor, since being an actor doesn’t actually imply much. Neither `inbox` nor `outbox` has to be public, anyway – they just have to be there.
+
+One other addendum is that, last I looked into this, I saw some discussion around Friendica and Zap having or planning support for `Follow Note`, but I was not able to find how this support was implemented, if it was.
+
+---
+
+@macgirvin:
+
+Interesting. Yeah, that all make sense.
+
+As I recall the rationale for inbox = null was a hint that an actor exists at this address, but it is only useful by some other protocol from ActivityPub. If you perform some alternate or broader scoped discovery (outside of AP) you might find that you can actually communicate with it.
+
+We perform Follow Note and if I recall Ignore Note as internal activities to indicate you want to see (or not see) notifications for this thread in the future. We currently don’t federate these activities - they’re strictly for internal use. The object is always the top-level post in a thread as these platforms default to conversation/threaded display.
+
+Oh and the comment about permissions wasn’t really about inbox/outbox but about recipient collections. We permit people to hide who is in their followers/following and circles/aspects collections if they don’t feel like sharing these with the world. These will return 403 if the owner doesn’t want anybody to see their contents. This affects the address de-duplication sections of the spec since these collections can only be expanded/iterated by their origin server. We do filter outbox contents based on the request http-signature but I think this is common practice.
+
+---
+
+@trwnh:
+
+This may be off-topic but it’s worth pointing out that most projects I’m familiar with tend to respond with some valid JSON(-LD), but intentionally leaving out any details the author does not want visible.
+
+* Mastodon’s “Hide your network” option will return an `OrderedCollection` with the only useful property being `totalItems`. This is because Mastodon’s philosophy is to hide only the contents of the collection while still revealing metadata (presumably out of some concern for signaling “trustworthiness”, which to me seems flawed, but I digress):
+
+```
+GET https://mastodon.social/users/trwnh/followers HTTP/1.1
+Accept: application/activity+json
+
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://mastodon.social/users/trwnh/followers",
+ "type": "OrderedCollection",
+ "totalItems": 2482
+}
+```
+
+* Pixelfed currently does something similar, but intentionally “lies” and claims that there are 0 items while explicitly returning an empty array as the value:
+
+```
+GET https://pixelfed.social/users/trwnh/followers HTTP/1.1
+Accept: application/activity+json
+
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://pixelfed.social/users/trwnh/followers",
+ "type": "OrderedCollectionPage",
+ "totalItems": 0,
+ "orderedItems": []
+}
+```
+
+* Pleroma has separate toggles for hiding either the items or the count (or both). If the items are hidden, the `orderedItems` will simply not be present. If the count is hidden, the `totalItems` will simply not be present. If both are hidden, both properties will simply not be present. On a UX level, hiding the counts requires hiding the items, because hiding only the count leaves you open to manually counting the items yourself.
+
+```
+GET https://letsallovela.in/users/at/followers HTTP/1.1
+Accept: application/activity+json
+
+{
+ "@context": [...],
+ "first": "https://letsalllovela.in/users/at/followers?page=1",
+ "id": "https://letsalllovela.in/users/at/followers",
+ "type": "OrderedCollection"
+}
+```
+
+* Misskey does the same thing as what you described: 403 Forbidden.
+
+---
+
+@trwnh:
+
+In any case, I don’t think that the spec necessarily intended to have the *sender* dereference follower collections for other actors – rather, that role falls on the *receiver*, and the logic/rationale is as described in the Inbox Forwarding section, “avoiding ghost replies”:
+
+> When Activities are received in the [inbox](https://www.w3.org/TR/activitypub/#inbox), the server needs to forward these to recipients that the origin was unable to deliver them to. To do this, the server *MUST* target and [deliver](https://www.w3.org/TR/activitypub/#delivery) to the values of `to`, `cc`, and/or `audience` if and only if all of the following are true:
+>
+> * This is the first time the server has seen this Activity.
+> * The values of `to`, `cc`, and/or `audience` contain a Collection **owned by the server**.
+> * The values of `inReplyTo`, `object`, `target` and/or `tag` are objects **owned by the server**. The server *SHOULD* recurse through these values to look for linked objects **owned by the server**, and *SHOULD* set a maximum limit for recursion (ie. the point at which the thread is so deep the recipients followers may not mind if they are no longer getting updates that don’t directly involve the recipient). The server *MUST* **only target the values of `to`, `cc`, and/or `audience` on the original object** being forwarded, and **not pick up any new addressees** whilst recursing through the linked objects (in case these addressees were purposefully amended by or via the client).
+>
+> The server *MAY* filter its delivery targets according to implementation-specific rules (for example, spam filtering).
+
+Essentially, inbox forwarding is a failsafe that allows a sender to say “look, here’s the Activity, I don’t know what this collection contains, so you deal with it, since it’s ostensibly under your authority.” This is why the “owned by the server” language is used multiple times in the above quoted section. Replying to, tagging, or performing an activity with the (locally owned) actor should trigger some discovery behavior. I must admit I find this recursive discovery behavior a bit problematic, although it is easier to swallow if you take it to mean “remote server implementations may notify / deliver to local actors that you reply to, tag, or act upon”. Perhaps it makes sense to notify someone if they were tagged or replied to, even if they were not explicitly addressed. Perhaps the implication is that they should be careful while doing so to not expand the scope of delivery. Perhaps the language in this third bullet point is simply bad language or bad guidance.
+
+With that said, what matters for the purpose of inbox forwarding is that, if you are delivering to someone else’s followers collection, then the sender needs to know how to refer to the `followers` IRI. But `followers` as a property is only a SHOULD and not a MUST. And I guess the “spam filtering” clause above also opens the door to implementations simply choosing *not* to forward to someone else’s followers. (I think Mastodon does indeed filter out activities delivered to someone else’s followers collection, based on a friend’s testing, but I can’t remember for sure.) Anyway, a server that only implements S2S and not C2S might as well leave out the `followers` and `following` entirely, for privacy purposes. I don’t think this would break anything – if it does, that points to bugs in existing implementations. (Okay, it might break sharedInbox.)
+
+One other tangent about inbox forwarding and addressing in general, that I might follow up on in another topic: I wish implementations would use `audience` more. It should be standard behavior to comment on someone’s post and address them, plus the value of `audience` (plus any other arbitrarily mentioned/added people, plus maybe your own followers). The audience of a post should be used even above `to`/`cc`, because to me `audience` carries human semantics while `to`/`cc`/`bto`/`bcc` are for server communication. For S2S purposes, the server implementation is actually free to deliver several slightly different activities to different inboxes, and in the case of `bto` and `bcc` this differing behavior is actually required. This, combined with the previous paragraph, leads to an issue where one may target their own `followers` collection without actually advertising it as their `followers` collection. I’m not sure what kind of undefined behavior that would lead to… it’s things like this that make me think sharedInbox was a mistake.
+
+---
+
+@macgirvin:
+
+This whole clause is about “conversational delivery” ; which is completely different from microblog use. We use conversational delivery so I understand it very well. This is the two fediverses problem I speak about quite often.
+
+I’ll put it in very simple terms. We have the Twitter fediverse and the Facebook fediverse. The protocol supports the Facebook fediverse through inbox forwarding but Twitter-like projects don’t understand it and do things that break the Facebook fediverse. We can get along together but the first step is acknowledging that both models exist and learning how to implement both. The Facebook fediverse is important for things like private groups (ok “restricted”) and circles (restricted collections), so Twitter-like projects can get some benefit from supporting both.
+
+And we can implement both. In the Facebook fediverse all comments to a restricted (not public) post go back to the sender of the top-level post and to nobody else. The actor that sent the top-level post delivers the comments downstream to all of the original recipients of the top-level post - and to nobody else. If it’s a public conversation commenters can send to whoever they want. This is the secret sauce that makes restricted conversations work.
+
+In this model the sender of the top-level post is the only delivery authority for the entire threaded conversation. Now realise that this section was added to ActivityPub so that Facebook-like projects such as Friendica, Diaspora, and Hubzilla could exist in an ActivityPub fediverse, but the people writing the spec were nearly all from the Twitter side of the fediverse and to this day the Twitter side doesn’t recognise that the Facebook side exists and has a different addressing/delivery model than they do.
+
+It seems from your reply that conversational delivery is a bit alien to you as well. No worries. I’ve proposed a mechanism to let everybody know for any given conversation which model to use. It’s pretty simple and uses ‘replyTo’ and works the same as email’s reply-to. If it’s set, that’s who you reply to - and you don’t cc or deliver to anybody else; and you also copy that replyTo to your own comment before sending. If it isn’t set, send your comment to whoever you want. Twitter-like projects will never set it except maybe in circles/aspects or private/restricted groups. Facebook-like projects will probably always set it except maybe in public conversations when their posts benefit from exponentially widening reach. And everybody lives happily ever after in the same fediverse. We support this today.
+
+---
+
+@trwnh:
+
+Small point of contention: “Twitter fedi” projects like Mastodon implement inbox forwarding, but they don’t make it the main mechanism of delivering replies in the same way that “Facebook fedi” projects expect to redistribute comments.
+
+I am familiar with that model, and in fact Dennis Schubert proposed it some years back in criticism of the “twitter fedi” approach – [ActivityPub - one protocol to rule them all? - Dennis Schubert ](https://overengineer.dev/blog/2018/02/01/activitypub-one-protocol-to-rule-them-all.html#replies-and-interactions) proposed back in 2018 that “Alice’s host is the one who delivered the shareable, so it feels somewhat natural to also ask Alice’s host to distribute the interactions […] a more sensible, reliable, and even more AcitivityStream’y way of handling replies would probably be adding the interaction to the replies collection and sending an `update`”. Whether the original activity is forwarded or whether an Update is sent doesn’t particularly matter to me, since the model works the same either way – your interaction exists in context of some top-level object.
+
+In fact, we could be more explicit with this model by using the `context` property (which sadly goes largely unused on “twitter fedi”). If a post has a `context` of another post, it is a comment (Facebook-style). Otherwise, it is just a post (Twitter-style). These (Twitter-style) posts can exist in context of a Collection representing a conversation, or they can exist in a null context.
+
+> I’ve proposed a mechanism to let everybody know for any given conversation which model to use. It’s pretty simple and uses ‘replyTo’ and works the same as email’s reply-to. If it’s set, that’s who you reply to - and you don’t cc or deliver to anybody else; and you also copy that replyTo to your own comment before sending. If it isn’t set, send your comment to whoever you want.
+
+Hmm, I guess this makes sense as a mechanism – it’s like a more explicit version of `context`. Prior to this conversation I would have probably proposed something like the following algorithm:
+
+1. Try to resolve `context` and check for `attributedTo`.
+2. Resolve everything in `attributedTo` and deliver to any `inbox` found.
+3. If there was no `context.attributedTo` or no actors/inboxes could be found, or if there was no `context`, then deliver your reply to whomever (your followers, as:Public, etc).
+
+Again, though, I’m not sure if `context.attributedTo.inbox` is the best approach here. At least `replyTo.inbox` saves a lookup step, and allows delivering to different actors, which would allow modeling anonymous objects.
+
+As far as `context` goes, though, it would probably be a good idea to assign `context` = the top-level post (Facebook-style) or `context` = some Collection representing the conversation or thread, and then copy the `context` as-is when replying/commenting.
+
+Perhaps an algorithm which supports both `context` and `replyTo` would look like this in pseudocode:
+
+```
+# Determine to/cc addressing
+if "replyTo" in activity:
+ to = [
+ actor["inbox"]
+ for actor in activity["replyTo"]
+ if "inbox" in actor
+ ]
+
+elif (
+"context" in activity
+and "attributedTo" in activity["context"]
+):
+ to = [
+ actor["inbox"]
+ for actor in activity["context"]["attributedTo"]
+ if "inbox" in actor
+ ]
+
+else:
+ to = ACTOR["followers"] + PUBLIC
+
+# Copy any values that should be copied
+if "replyTo" in activity:
+ replyTo = activity["replyTo"]
+if "context" in activity:
+ context = activity["context"]
+```
+
+---
+
+@macgirvin:
+
+We also use context as you’ve described - but recently a number of new projects have started using context for other things than conversation ids. Fetching our context in fact returns a collection of the entire threaded conversation as seen by the root node - which is something I also wish more projects supported. But now that folks are doing other things with context and we also still have folks using them with OStatus semantics (which aren’t de-reference-able) I suppose we’ll eventually have to come up with a different cross-platform way of fetching the entire conversation. Oh well.
+
+Cheers.
+
+## current thoughts
+
+i plan to synthesize several things here -- a collection that could also be an actor, and maybe set as context. see FEP-7888 and a future FEP for that i guess
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/note-vs-article-distinction.md b/wiki.hugo/content/_dump/socialhub-threads/note-vs-article-distinction.md
new file mode 100644
index 0000000..710ac50
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/note-vs-article-distinction.md
@@ -0,0 +1,159 @@
++++
+title = "Resolving the Note vs. Article distinction"
+date = "2019-11-01"
++++
+
+## preserved text
+
+
+
+# Background
+
+[Activity Vocabulary - 3.3 Object Types ](https://www.w3.org/TR/activitystreams-vocabulary/#object-types):
+
+> **Note**: Represents a short written work typically less than a single paragraph in length.
+> **Article**: represents any kind of multi-paragraph written work.
+
+Example 48 (Article):
+
+```
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "type": "Article",
+ "name": "What a Crazy Day I Had",
+ "content": "
... you will never believe ...
",
+ "attributedTo": "http://sally.example.org"
+}
+```
+
+Example 53 (Note):
+
+```
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "type": "Note",
+ "name": "A Word of Warning",
+ "content": "Looks like it is going to rain today. Bring an umbrella!"
+}
+```
+
+Semantically, the difference is never explicitly defined (how do you define a “paragraph”?), so the current fediverse has sort of assumed Article should be viewed natively on the remote website, while Note can be displayed as an inline status. Thus, Note is used to represent a status update, and a lot of the network just defaults to Note. The distinction is assumed to be formatting, but once again this is not an explicit definition (how do you define “formatting”?)
+
+# Disambiguation
+
+Going purely from the Activity Vocabulary descriptions and examples, I would possibly assume one or both of the following:
+
+* Note SHOULD be plain text, Article SHOULD use HTML (or should these be a MUST?)
+* Note SHOULD NOT use newlines (but are technically allowed to do so)
+
+However, there is [ActivityPub 3.3 ](https://www.w3.org/TR/activitypub/#source-property), Example 8:
+
+```
+{
+ "@context": ["https://www.w3.org/ns/activitystreams",
+ {"@language": "en"}],
+ "type": "Note",
+ "id": "http://postparty.example/p/2415",
+ "content": "
I really like strawberries!
",
+ "source": {
+ "content": "I *really* like strawberries!",
+ "mediaType": "text/markdown"}
+}
+```
+
+This example Note uses HTML for its `content`, in order to demonstrate the `source` property.
+
+Also, ActivityPub Example 4:
+
+```
+{"@context": "https://www.w3.org/ns/activitystreams",
+ "type": "Create",
+ "id": "https://chatty.example/ben/p/51086",
+ "to": ["https://social.example/alyssa/"],
+ "actor": "https://chatty.example/ben/",
+ "object": {"type": "Note",
+ "id": "https://chatty.example/ben/p/51085",
+ "attributedTo": "https://chatty.example/ben/",
+ "to": ["https://social.example/alyssa/"],
+ "inReplyTo": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19",
+ "content": "
Argh, yeah, sorry, I'll get it back to you tomorrow.
+
I was reviewing the section on register machines,
+ since it's been a while since I wrote one.
"}}
+```
+
+This example Note uses two `
` elements, representing two short paragraphs (once again not “less than a single paragraph”).
+
+So even the specs themselves are inconsistent on any distinction.
+
+# How much does this actually matter?
+
+Arguably not much, since implementations often convert Note and Article into their own internal schema for statuses anyway. But it could still be beneficial to set a clearer distinction going forward on how these types should be assigned, ideally.
+
+
+
+---
+
+@lanodan:
+
+The distinction I make between Article and Note isn’t related directly to it’s content but on how it’s supposed to be presented and used, Articles are more things for blogs where you have about a post per day and so articles should be easy to find back with a list of articles/tags and maybe a bit of search features, Notes are more stuff like microblogging where you can easily have hundreds in a day and aren’t that easy to find back even with good keywords in full text search.
+
+Also I find that formatting is actually very useful for notes because it allows to express more/equivalent with less (like a word-list vs a paragraph).
+
+This question goes a lot in the fediverse because they are the two mainly used activity types but one could also ask about the actor distinction between Organisation and Group, Application and Service. And so far I’ve only seen ActivityPub Document be used in the wild for Images with textual description (like if Image couldn’t have it in the first place), but Document has no inherent meaning either.
+
+Note: Pleroma keeps the distinction between Articles and Notes internally, no real differencies for the Mastodon API though but there could be a query filter.
+
+---
+
+@trwnh:
+
+For prior art, I can think of semantic HTML’s `` being a section of HTML that can be reproduced elsewhere in its entirety.
+
+W3Schools: "independent, self-contained content. An article should make sense on its own and it should be possible to distribute it independently from the rest of the site."
+
+MDN: "a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable e.g. in syndication."
+
+This could be a distinction worth making, maybe? that an Article should roughly map to an ``, whereas a Note is just arbitrary text?
+
+---
+
+@nightpool:
+
+I think using `Article` is a perfectly fine solution for when the desired semantics are “I think it’s better in a short-form microblogging context to display a link to this thing rather then the full content itself”.
+
+When considering that some clients (especially native clients) often won’t support increasingly rich text formatting, I think using Article vs Note for content where you think plain-text fallback is unacceptable is a totally fine decision to make. (But you shouldn’t ignore the fact that it’s probably likely that people are going to write long-form clients that *do* support Articles but don’t support every possible type of rich text formatting, like the way RSS readers restrict allowed formatting for readability)
+
+---
+
+@trwnh:
+
+I can’t remember where this was said to me, but I think someone (maybe nightpool?) suggested that Note could be used for message passing a la Discord, which would be a third distinction and perhaps better than length/newlines or plaintext (as explained previously why those are inconsistent). So in that case, we could say Note vs. Article is one of *formality*. IMO this could complement the Article-to-`` suggestion above.
+
+Taken together:
+
+* Note = for informal message-passing
+* Article = for publication or syndication
+
+The only thing unresolved with this distinction would be the blurry line that is microblogging. Microblogs are often both informal *and* intended for republishing in feeds. It’d be pretty clear-cut to use Note for a messaging application and Article for a blogging platform, but… perhaps this implies top-level microblogging posts should be an `Article` and replies should be `Note`? Or that they should all be `Article` regardless of the fact that they are informal? There’s still room for discussion there.
+
+---
+
+@darius:
+
+I think this is right on the money. My main use case for Article is that it’s a way to say that “this is a publication” – I’ve often talked about how this might actually help solve the “quote-tweet” design problem in Mastodon (and presumably other software). If an Article is something that is formal and published then it’s also something that can reasonably be commented upon. Articles can be quoted-commented, and Notes cannot. So I can dunk on a New York Times article, but not on a random thing someone posted as a note.
+
+Edited to add: for composing posts on a microblogging service, I wonder if a “people can quote-comment on this post” checkbox or whatnot could be, at its most basic, a switch that underneath it all changes type for your post from Note to Article.
+
+---
+
+@trwnh:
+
+quoting and commenting is kind of out-of-scope and it’s up to each platform to decide how they want to handle it, tbh. from a data view, it doesn’t really matter because you can put whatever you want in `content`, and `inReplyTo` is just metadata (like `tag`). You can have an Article inReplyTo another Article, just as you can have a Note inReplyTo another Note (or a Note inReplyTo an Article, or even vice-versa, etc etc.)
+
+the thing is, though, that it’s really seeming like if we use “syndication” as the distinction, then that would imply a lot of things that are currently Note might be better conceived of as Article.
+
+---
+
+## current thoughts
+
+i wrote a whole thing abt this [here]({{< relref "note-vs-article" >}})
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/notification-to-refetch-object.md b/wiki.hugo/content/_dump/socialhub-threads/notification-to-refetch-object.md
new file mode 100644
index 0000000..8bffb3b
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/notification-to-refetch-object.md
@@ -0,0 +1,60 @@
++++
+title = "Notifying remote servers that they should refetch an object"
+date = "2019-11-01"
++++
+
+{{toc}}
+
+## Preserved text
+
+
+
+@trwnh:
+
+[quote="trwnh, post:1, topic:259, full:true"]
+S2S Update:
+
+> 7.3 Update Activity
+>
+> For server to server interactions, an `Update` activity means that the receiving server *SHOULD* update its copy of the `object` of the same `id` to the copy supplied in the `Update` activity. Unlike the [ client to server handling of the Update activity ](https://www.w3.org/TR/activitypub/#update-activity-outbox), this is not a partial update but a complete replacement of the object.
+>
+> The receiving server *MUST* take care to be sure that the `Update` is authorized to modify its `object` . At minimum, this may be done by ensuring that the `Update` and its `object` are of same origin.
+
+Presumably sending something like this over S2S would just get the object replaced by an empty copy:
+
+```
+{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://example.com/activities/1",
+ "type": "Update",
+ "actor": "https://example.com/actors/1",
+ "object": "https://example.com/objects/1"
+}
+```
+
+So how would this update/refetch notification be done properly?
+[/quote]
+
+---
+
+@nightpool:
+
+wait, what? why would the example posted not be compliant? The two representations (including an IRI to dereference vs including an embedded object) should be identical on the JSON-LD level.
+
+I agree that the spec might expect you to inline the object, but I absolutely disagree that it requires it.
+
+---
+
+@kaniini:
+
+I agree with nightpool, a bare IRI is completely fine here.
+
+---
+
+@trwnh:
+
+OK, then. If a bare IRI is fine, then the next question would probably be how this would be handled in existing implementations. If an ActivityPub implementation were to hypothetically use Update in this manner, would it be received and handled properly?
+
+## Current thoughts
+
+needs testing or review, but should be possible imo. and if it's possible then maybe it could be expected?
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/signaling-side-effects-async.md b/wiki.hugo/content/_dump/socialhub-threads/signaling-side-effects-async.md
new file mode 100644
index 0000000..5398236
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/signaling-side-effects-async.md
@@ -0,0 +1,82 @@
++++
+title = "Signaling side effects asynchronously by generalizing Accept/Reject"
+date = "2019-10-11"
++++
+
+{{toc}}
+
+## Preserved text
+
+
+
+
+
+# Background
+
+Per S2S (since Accept/Reject are not described in C2S):
+
+> 7.6 Accept Activity
+>
+> The side effect of receiving this in an **inbox** is determined by the type of the `object` received, and it is possible to accept types not described in this document (for example, an `Offer` ).
+>
+> If the `object` of an `Accept` received to an **inbox** is a `Follow` activity previously sent by the receiver, the server *SHOULD* add the `actor` to the receiver’s [Following Collection](https://www.w3.org/TR/activitypub/#following).
+>
+> 7.7 Reject Activity
+>
+> The side effect of receiving this in an **inbox** is determined by the type of the `object` received, and it is possible to reject types not described in this document (for example, an `Offer` ).
+>
+>
+>
+> If the `object` of a `Reject` received to an **inbox** is a `Follow` activity previously sent by the receiver, this means the recipient did not approve the `Follow` request. The server *MUST NOT* add the `actor` to the receiver’s [Following Collection](https://www.w3.org/TR/activitypub/#following).
+
+Note that for S2S purposes, Accept/Reject is only really defined for Follow activities. Per the Activity Vocabulary, it is also implicitly appropriate for `Offer` and `Invite`, but also [Example 10](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept) shows a much more ambiguous Accept Person targeting Group, which seems semantically awkward.
+
+# Possible generalizations
+
+Currently, the majority of the network uses Accept/Reject only for Follow on an Actor, and thus Accept/Reject is used only in that narrow definition. But there are other Activities that might require these semantics…
+
+## Accept/Reject Join
+
+Closed-membership `Group` semantics is maybe the most obvious benefit of generalizing Accept/Reject. It is of course possible to both Follow and Join a Group; Follow Group would semantically translate to being interested in what the Group posts to its outbox, as per the base AP spec. Some softwares handle Group membership based on its `followers`, but this is a bit of a hacky way to do things that is motivated by compatibility with the existing “Follow Actor” network. A much more semantic way to handle things would be to allow Join/Leave Group, but then Join would need Accept/Reject to allow modeling closed groups (at least, in a way different than just using the `Group` `followers` with `manuallyRequiresApproval` + `Announce` any activities received at `inbox` – which is still a valid way of doing things for “mailing list” use cases). This would be clearer than Accepting a Person into a Group.
+
+## Accept/Reject Create
+
+When sending a Create to a remote server, there will generally be side effects interpreted by that remote server’s software. One common example is that sending Create Note with `inReplyTo` may attach your Note as a reply to another Note. But this is not guaranteed to happen, e.g. if the remote software has a concept of “disabled comments” or “approved comments”. In that case, the remote software may want to signal that the use of `inReplyTo` will not automatically cause side effects to be processed, in the same way Follow must first be Accepted or Rejected. It might not make sense to explicitly *require* Accept/Reject semantics for such a case (as they are for Follow), but they can still be used for hinting the result.
+
+## Accept/Reject Update/Add/Remove/Delete
+
+In cases where an actor is performing actions on an object other than creating it, these actions may require approval from another actor who “owns” or “manages” that object. You may want to Accept an Offer of an Update, but it would be simpler to just Accept the Update. Per the AP spec, the only considerations made are as follows:
+
+7.3 Update:
+
+> The receiving server *MUST* take care to be sure that the `Update` is authorized to modify its `object` . At minimum, this may be done by ensuring that the `Update` and its `object` are of same origin.
+
+7.4 Delete:
+
+> (assuming the `object` is owned by the sending actor / server)
+
+7.8 / 7.9, Add/Remove:
+
+> * the `target` is not owned by the receiving server, and thus they can’t update it.
+> * the `object` is not allowed to be added/removed to the `target` collection for some other reason, at the receiver’s discretion.
+
+So we have some guidance toward the “receiver’s discretion”, but no formal way of signaling that discretion back to the author of the received activity.
+
+# But why not just use HTTP status codes?
+
+HTTP status codes are synchronously returned at the time of the request, even if the request is handled asynchronously. You may send out a `202 Accepted` to indicate that the document was successfully received, but later send out a `Reject` Activity after some manual action was taken by an actor. This manual action may be performed long after the initial delivery to the remote server.
+[/quote]
+
+
+
+---
+
+@nightpool:
+
+I think this is a good idea, but i would like to see some implementor support before defining it further.
+
+---
+
+## current thoughts
+
+yeah, actually. let's do it
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/socialhub-threads/stricter-spec-for-collections.md b/wiki.hugo/content/_dump/socialhub-threads/stricter-spec-for-collections.md
new file mode 100644
index 0000000..fc4f4da
--- /dev/null
+++ b/wiki.hugo/content/_dump/socialhub-threads/stricter-spec-for-collections.md
@@ -0,0 +1,114 @@
++++
+title = "Stricter specifications for pagination of Collections and OrderedCollections"
+date = "2022-11-05"
++++
+
+## Preserved text
+
+
+
+@trwnh:
+
+
+
+## Overview
+
+ActivityPub primarily depends on direct delivery of activities, but many implementations expose old post history via the `outbox`. In theory, you could fetch the outbox to discover old posts that weren’t delivered to you but should still be visible to you (e.g. Public posts that persist in the outbox). However, there is one big problem: pagination.
+
+Specifically, pagination is an issue because you will have to fetch multiple pages, and you don’t know exactly when to stop, or how to discover gaps. You may be able to fetch up until you see a post that you already have, but there may be other unseen posts beyond that one. The only way to be sure is to fetch every single page of the outbox, which can be a costly operation.
+
+## Recommendations
+
+Arguably, this situation can be improved by making some specific recommendations:
+
+### Construct chronologically, but present in reverse order
+
+Because an OrderedCollection is mandated to be “reverse chronological” specifically, extra care needs to be taken to allow stable page references. Perhaps pages should be built chronologically and simply presented in reverse order, crucially with the `first` page containing less than than the max page size.
+
+Example: A page size of 10 and a collection of 23 items should be split into pages of 3, 10, 10. These pages would be presented as such:
+
+```
+[
+[23 22 21]
+[20 19 18 17 16 15 14 13 12 11]
+[10 9 8 7 6 5 4 3 2 1]
+]
+```
+
+### Stable page references should also be reversed
+
+Furthermore, in order to maintain stable page references, such that if you’ve fetched a page before you don’t have to fetch it again, page counters should be assigned in reverse order as well.
+
+Taking the example from above, the pages would be identified as 3, 2, 1:
+
+```
+[
+[23 22 21] // page 3
+[20 19 18 17 16 15 14 13 12 11] // page 2
+[10 9 8 7 6 5 4 3 2 1] // page 1
+]
+```
+
+### Deleted items should either be Tombstoned or change the page size
+
+All this work is useless if the pages have to be recalculated or the items get shifted to a different page. To prevent this, either serve a Tombstone in place of deleted items, or otherwise freeze the upper and lower bound of a page while allowing variable page sizes.
+
+For example, let’s say we delete post 17. The result might look like this:
+
+```
+[
+[23 22 21] // page 3 (3 items)
+[20 19 18 T 16 15 14 13 12 11] // page 2 (10 items, 1 Tombstone)
+[10 9 8 7 6 5 4 3 2 1] // page 1 (10 items)
+]
+```
+
+Or, it might look like this:
+
+```
+[
+[23 22 21] // page 3 (3 items)
+[20 19 18 16 15 14 12 11] // page 2 (9 items)
+[10 9 8 6 5 4 3 2 1] // page 1 (10 items)
+]
+```
+
+Notice that page 3 remains unchanged, rather than item 21 becoming part of the 2nd page.
+
+### Accessing pages should be done in a consistent way
+
+The final piece of the puzzle is a way to consistently load specific pages. For example, consider a collection at `/collection/id`. You might be able to attach a query parameter `?page=N` to access the Nth page via `/collection/id?page=N`. Or you might have some route such as `/collection/id/page/N`. Whatever the case, there should be a way of getting pages that can be expected to work across all implementations. Or, at the very least, a way that may be inferred easily, but a standard pagination technique would be better.
+
+My thinking is that `/page/N` would be better, because it would allow for static pages as an option more easily,
+
+Also for consistency: Tombstone is preferable to exclusion, because it allows dynamic page sizing on-the-fly in dynamic servers that use query parameters.
+
+
+
+---
+
+@silverpill:
+
+Perhaps a timestamp filter could solve this problem?
+For example, `/collection/id?after=1667766000` can return a paginated subset of the collection, and if the client knows the time of the last sync, it can retrieve missing objects with fewer requests.
+This way implementations can continue to use their preferred pagination mechanism.
+
+---
+
+@trwnh:
+
+Having a timestamp filter might work for dynamic server implementations but not for static server implementations. I took care in making sure, while writing the above post, that the recommendations would be applicable to both static and dynamic servers.
+
+---
+
+@trwnh:
+
+in writing this up i seem to have overlooked the `startIndex` property of OrderedCollectionPage, which is basically just a positive offset for how far into the OrderedCollection you are with the first item. unfortunately this is less useful due to reverse chronology being mandated by ActivityPub; it would be far more useful in a forward-chronological collection. it also doesn’t apply to regular CollectionPage sadly.
+
+there is still the option of having a regular Collection contain OrderedCollectionPage, though, or otherwise simply disregarding the “MUST be reverse chronological” bit and committing a spec violation.
+
+---
+
+## current thoughts
+
+idk. really wish the OrderedCollection wasn't mandated to be reverse-chron and it was instead forward-chron at least. this carries over to OrderedCollectionPage too...
\ No newline at end of file
diff --git a/wiki.hugo/content/_dump/w3c-http-supremacy.md b/wiki.hugo/content/_dump/w3c-http-supremacy.md
new file mode 100644
index 0000000..05ba8ac
--- /dev/null
+++ b/wiki.hugo/content/_dump/w3c-http-supremacy.md
@@ -0,0 +1,16 @@
+https://mastodon.social/@trwnh/109886416964217719
+
+reading a lot of old w3 literature and while there's a lot of good stuff in there, it is *infuriating* how they are so blindly in support of using http for everything, including identifiers. they probably just failed to predict the future, but they keep stopping just short of admitting http's biggest problem: when the server goes down, your uri can't be dereferenced anymore!
+
+(specifically i was reading https://www.w3.org/2001/tag/doc/URNsAndRegistries-50.xml which argues against urns because you can't dereference them)
+
+am i being too harsh on an editorial from 2001, sure, yeah, probably no one was seriously thinking of decentralized systems back then. if you just wanna obtain a resource from a given organization or whatever, it is generally a given that the org has its own domain name and can assign ids on that domain. but the whole thing falls apart when you need a global namespace that can be requested from multiple domains. this is *exactly* where urns are useful! like, naming things is in some way id!
+
+if we follow the logic of http maximalists from 2001, then we would not need the isbn or doi namespaces, we could just assign identifiers on an http hostname. a doi can be resolved using an http url so why not just use the url directly?
+
+well, that assumes persistence that simply isn't guaranteed. the doi foundation will tell you itself: https://www.doi.org/the-identifier/resources/factsheets/doi-system-and-persistent-urls
+
+> PURLs are all http and inherit both the strength and weakness of that approach
+
+it's those weaknesses that kept being ignored
+
diff --git a/wiki.hugo/content/_dump/webfinger-as-dns.md b/wiki.hugo/content/_dump/webfinger-as-dns.md
new file mode 100644
index 0000000..fa53c11
--- /dev/null
+++ b/wiki.hugo/content/_dump/webfinger-as-dns.md
@@ -0,0 +1,53 @@
+https://mastodon.social/@trwnh/110361352685140966
+
+so we might reasonably recreate bluesky's "placeholder" nameserver by having a well-known endpoint for resolving identifiers to as2 documents (with possibly a layer of indirection, in which case webfinger would probably work)
+
+this basically replaces DNS for resolution. you'd just have to figure out how to assign ids in a distributed way without conflicts
+
+for that matter: why isn't xrpc a .well-known endpoint? it absolutely should have been
+
+i'm thinking if we wanted to reify webfinger and identity providers, we could just have identifiers assigned under the authority of webfinger subjects. where is the data? idk, check the current links via webfinger.
+
+problem with that is, your IdP better be long-lived... in fact, it makes sense for a persistent IdP to last basically "forever" and just point to your current data stores. and then i guess you'd want IdP federation to ease migration between IdPs? or otherwise conflict-free id minting
+
+tldr the open problems:
+
+- how to assign ids without conflict? (preferably without dns or key based authority, so you can change those later)
+
+- how to resolve those ids across multiple servers without tampering? (see also: dns poisoning and authoritative nameservers)
+
+there's a lot of prior art in DNS and you'd be moving it all down to the HTTP level over webfinger and oidc and related stuff
+
+basically instead of resolving names -> authoritative DNS nameservers -> IP addresses, you have to resolve uh... names -> authoritative Webfinger servers -> http(s) links
+
+so i guess we need an equivalent to DNSSEC but for WebFinger
+
+---
+
+erincandescent writes:
+
+
+
+hash of public key; hash of first version of document (in chain), like they did. many decent options!
+
+the did:plc approach allows you to rotate keys because your current identity document will eventually chain back to the original one which hashes to the value of your account ID
+
+the bit the central server is doing in this system is - basically - ordering things & letting you use your recovery key to oblitterate any updates from your primary key from the last 72 hours (for if your primary key was compromised)
+
+the key difficulty without any central server is timestamping things to ensure & validate ordering
+
+
+
+cobaltvelvet writes:
+
+
+
+i think i just like the idea of a minimal relay as this resolver, that would keep the least state possible inside it, so it can be swapped in and out easily, maybe even transparently so by your instance. but it would always need A Way to validate the 'latest location', either the keypairs that arent very securely held atm but instances already have, or a third secret thing (a dedicated channel, like making the resolver email you to confirm a migration, or another layer of signatures)
+
+if i had to point to an inspiration, i think bittorrent trackers are great, easily replceable by a DHT, but also easy to just use two for redundency . ofc they don't really have to bother with any validation, but your instance can
+
+
+
+---
+
+i'd just need to think through how to get consistency between different webfinger services, so that they agree on the response and serve you up the same JRD from some decentralized/distributed data store
\ No newline at end of file
diff --git a/wiki.hugo/content/_index.md b/wiki.hugo/content/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/foobar2000.md b/wiki.hugo/content/foobar2000.md
new file mode 100644
index 0000000..1560c32
--- /dev/null
+++ b/wiki.hugo/content/foobar2000.md
@@ -0,0 +1,19 @@
++++
+updated = "2024-08-04"
++++
+
+## "copy of repositories maintained by kode54"
+
+according to https://hydrogenaud.io/index.php/topic,123394.0.html you can go to https://foobar2000.xrea.jp/?Input+64bit#aada4e80 and get 64-bit compatible builds of some old 32-bit only plugins/decoders like USF support for N64 music. also supports dark mode
+
+### fixing foo_snesapu
+
+
+
+foobar >v2.0 before v2.2 preview 2024-06-24 has a bug where it will remove any dll that doesn't match plugin architecture, so it when installing the fb2k-component it will copy over the foo_snesapu.dll plugin but not its dependency snesapu.dll -- you will have to copy it manually to the install directory for foobar2000 (for windows this will be either `\AppData\Roaming\foobar2000-v2\user-components-x64\foo_snesapu\` for standard install, or `\profile\user-components-x64\foo_snesapu\` for portable install -- get the files out of the fb2k-component using an archive viewer)
+
+## recompiled plugins for x64 and dark mode support
+
+https://foobar.hyv.fi/
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/_index.md b/wiki.hugo/content/gaming/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/gaming/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/gc.md b/wiki.hugo/content/gaming/gc.md
new file mode 100644
index 0000000..f1a7801
--- /dev/null
+++ b/wiki.hugo/content/gaming/gc.md
@@ -0,0 +1,11 @@
++++
+updated = "2024-08-03"
++++
+
+tbh just play gamecube games on the [wii](../wii). it's easier to softmod and cheaper overall (have you seen the price of 480p component cables for the gamecube vs for the wii??????). nintendont + usb loader gx is a great experience too
+
+the only reason i can think of to invest in gamecube as a platform is if you want to use the game boy player? which... it would probably be better to use a gba consoleizer instead
+
+i guess the gamecube produces a (imo negligibly) better image (subjectively / to some people) but really it isn't anywhere near the difference between a wii and wii u (where the wii u produces a noticeably darker and muddier image for wii/vc games) -- and also the issue pretty much entirely stems from the filtering that the wii does + the aspect ratio it's rendering at. just disable deflicker + enable framebuffer rendering in usb loader gx to close any gaps between the two systems (and hardmodding the wii for hdmi output should be even less of a difference)
+
+so yeah unless you wanna use a gameboy player specifically then skip the gc and go straight for a wii
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/minecraft/_index.md b/wiki.hugo/content/gaming/minecraft/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/gaming/minecraft/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/minecraft/server/_index.md b/wiki.hugo/content/gaming/minecraft/server/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/gaming/minecraft/server/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/minecraft/server/multiverse.md b/wiki.hugo/content/gaming/minecraft/server/multiverse.md
new file mode 100644
index 0000000..f9f9a5c
--- /dev/null
+++ b/wiki.hugo/content/gaming/minecraft/server/multiverse.md
@@ -0,0 +1,83 @@
+# multiverse
+
+## skyblock in bukkit/spigot/paper
+
+prerequisites:
+- multiverse-core
+- multiverse-inventories
+- multiverse-netherportals
+- voidgen
+
+```
+/mvcreate world_skyblock NORMAL -g VoidGen:{structures:true,decoration:true,mobs:true}
+/mvcreate world_skyblock_nether NORMAL -g VoidGen:{structures:true,decoration:true,mobs:true}
+/mvcreate world_skyblock_the_end NORMAL -g VoidGen:{structures:true,decoration:true,mobs:true}
+```
+
+create a multiverse-inventories group to share player data
+
+```
+/mvinv group
+create
+# name the group something like "world_skyblock"
+world_skyblock # add world
+world_skyblock_nether # add world
+world_skyblock_the_end # add world
+@ # continue after adding all worlds
+all # share all player data
+@ # finish
+```
+
+go to the world and change settings
+
+```
+/mvtp world_skyblock
+/gm c # go into creative, make a starter island
+/mvsetspawn # set a reasonable spawn point
+/mvmset respawnWorld world_skyblock # respawn in overworld
+/mvmset diff hard
+/mvmset allowflight false
+/mvmset alias Skyblock
+/mvmset color AQUA
+
+/mvtp world_skyblock_nether
+/gm c # go into creative, make a starter island
+/mvsetspawn # set a reasonable spawn point
+/mvmset respawnWorld world_skyblock # respawn in overworld
+/mvmset hidden true # hide non-overworld from mvlist
+/mvmset diff hard
+/mvmset allowflight false
+/mvmset alias Skyblock
+/mvmset color AQUA
+
+/mvtp world_skyblock_the_end
+/gm c # go into creative, make a starter island
+/mvsetspawn # set a reasonable spawn point
+/mvmset respawnWorld world_skyblock # respawn in overworld
+/mvmset hidden true # hide non-overworld from mvlist
+/mvmset diff hard
+/mvmset allowflight false
+/mvmset alias Skyblock
+/mvmset color AQUA
+```
+
+if you use essentialsx-chat: go to `plugins/Essentials/config.yml` and `chat.world-aliases` and define your aliases
+
+if you use essentialsx-spawn: set `respawn-listener-priority: lowest` so multiverse can handle respawns
+
+### caveats
+
+voidgen will generate water in ocean ruins, so if you want to play without water (ie getting rain in cauldrons) then this will be an easier way to get water
+
+voidgen will also not let you control which structures spawn, only all or nothing. you can get golden apples and regular apples from certain loot chests
+
+### todo
+
+- apples are dropping from spruce trees in skyblock
+- /spawn in test world takes you to survival
+- per-world warps (so you dont pollute the whole list)
+- check /weather permissions in skyblock
+- check /time permissions in skyblock
+- check /seed permissions in skyblock
+
+i think a lot of perms are owner only but skyblock should remove them bc higher weight
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/n64.md b/wiki.hugo/content/gaming/n64.md
new file mode 100644
index 0000000..7e02a61
--- /dev/null
+++ b/wiki.hugo/content/gaming/n64.md
@@ -0,0 +1,114 @@
++++
+updated = "2024-07-31"
++++
+
+## video output
+
+currently using an s-video cable from insurrection industries: https://insurrectionindustries.com/product/nintendo-s-video/
+
+was previously using https://amzn.to/3SuywUe which is cheaper (only $10 instead of $25 plus shipping) and also worked just as well. i can't vouch for any specific cable because i've read reports of even the insurrection industries one possibly being bad, but you'll know if it's bad or not pretty soon. an earlier cable i was using which had both composite and s-video on the same cable would display a checkerboarding pattern over the signal
+
+### s-video distribution amplifier
+
+tried some passive splitters for s-video and they produced the checkerboarding pattern over the signal
+
+radioshack distribution amplifier https://amzn.to/3YyldWy - this works well and also allows for composite output at the same time as s-video. (my magnavox 20mt1331/17 crt tv only takes composite in). amazon has them out of stock but search for a RadioShack 1500320 1 in 4 out, maybe you can find elsewhere
+
+## display
+
+currently using the aforementioned magnavox 20mt1331/17 which works okay i guess. mine has some bowing at the bottom and used to have pretty bad overscan before i fiddled with the service menu and geometry. to get into the service menu, power the tv on and quickly press 062596 then MENU before it has a chance to load an RF channel
+
+
+
+### best display
+
+n64 outputs 15khz 240p and some games do 480i so whatever you use needs to support that which means a tv and not a monitor will be best. (crt monitors often do 31khz and do not support 480i so you will get an "out of sync range" error if you try to hook up to one of those via adapters to vga)
+
+cream of the crop is probably sony pvm 14l5 or 20l5? this even supports 480p so stuff like the wii might work on it as well with component output (which enables 480p)
+
+really anything will work fine, n64 was made with composite blurring in mind so even composite output looks *fine* from the n64. although s-video is a decent upgrade for clarity. this means you should probably be looking for a crt tv that at least takes in s-video if you want extra clarity. otherwise use s-video at least for capture...
+
+### best capture
+
+so yeah use a good s-video capture card. i have tried three
+
+- io-data gv-usb2: https://amzn.to/46KhFTz this one is good (probably best) usb capture card for gaming/240p but drivers are windows only. there are reverse engineered drivers for linux though! https://github.com/Isaac-Lozano/GV-USB2-Driver -- bit annoying to setup and enable/load every time you want to use it, also i have not gotten audio capture to work reliably, but it technically exists.
+
+- hauppauge usb-live2 610 (old version): https://amzn.to/3WI2K8S this one is also good (maybe not as good as the gvusb2 but good *enough*) usb capture card and supports 240p. it has coxenant cx23100 internals which are apparently also used in the diamond vc500 but i haven't tried that one specifically (same for avermedia c039 and august vgb100). the good thing about this usb capture card is that it works out of the box on linux for me.
+
+- blackmagic intensity pro / pro 4k: really good pcie capture that works in windows and linux, with a few issues in linux, mainly that getting it to work with obs studio is annoying because it doesn't work in the flatpak version, you need the native version. but the native version of obs studio in arch doesn't support browser sources. the solution i have is to use `obs-studio-tytan652` from the AUR. still a good device i guess, supports component as well via a breakout cable, and two rca pins (green/blue, so i think Y/Pb) can be adapted to s-video (Y/C). the quality is actually too good, as it's meant to be used with uncompressed capture of all kinds of tv signals. also because of it being a thing for tv, it doesn't support 480p. i got this as an upgrade over the hauppauge and it honestly is a sidegrade over the gvusb2 but the better option if you use linux (just install `decklink` from AUR and use a native obs studio build)
+
+people also say good things about the pinnacle 710 (and dazzle dvc100?) but i can't really vouch for either
+
+#### gvusb2 software setup
+
+https://iotku.pw/gvusb2-guide/ is a good resource but basically
+
+- go to https://www.iodata.jp/lib/software/g/1780.htm and download drivers -- some people recommend v1.11 but i am running the latest v1.14 and it's fine (edit: just checked while writing this and there's already a v1.15 that released today lol)
+
+ok so in obs or amarec or whatever open your video settings, this is what i use for "device setting" in windows
+
+- video input = "2/s-video"
+- deinterlace = "weave ( off )" --
+
+if you have a newer driver version keep the stuff in "advanced driver property" off except maybe "skype support (pls replug)"
+
+under "video decoder":
+
+- video standard = NTSC_M_J (even if you're recording NTSC, this brightens the image up and makes it look more like what you'd get on a CRT -- 7.5 IRE)
+
+under "video proc amp":
+
+- brightness = 128
+- contrast = 90
+- hue = 128
+- saturation = 128
+- sharpness = 40
+
+then make sure to capture in 720x480 at 59.94fps (on older driver versions like 1.11 pick 29.97fps instead, then deinterlace with Retro in either amarec or obs)
+
+on arch linux i just install `gv-usb2-driver-dkms-git` from the AUR and it just works in obs studio after that
+
+in obs studio regardless of OS you want to apply retro deinterlacing and add a scaling filter to scale it from 720x480 to 640x480 bicubic (or bilinear if you want a slightly blurrier look that suits the n64 better)
+
+## flash carts
+
+summercart64 is what i have and it's cool. way cheaper than everdrive x7.
+
+- check the firmware on it by booting it up, if it's out of date then update it using the instructions at https://github.com/Polprzewodnikowy/SummerCart64 -- i didn't need to do this (yet) but the process is basically downloading sc64deployer and sc64-firmware
+
+- install the cr2032 battery into the holder such that the small pins bend upward and make contact with the top (positive side). the springy pins should be on the bottom (negative side) https://github.com/Polprzewodnikowy/SummerCart64/discussions/83
+
+you will want to set up your microsd card with https://github.com/Polprzewodnikowy/N64FlashcartMenu
+
+when done your sd layout should look something like this:
+
+- /sc64menu.n64
+- /menu/config.ini
+- /menu/boxart/*
+- /menu/64ddipl/
+ - /menu/64ddipl/NDDE0.n64
+ - /menu/64ddipl/NDDJ2.n64
+ - /menu/64ddipl/NDXJ0.n64
+- /menu/emulators/
+ - /menu/emulators/neon64bu.rom
+ - /menu/emulators/sodium64.z64
+ - /menu/emulators/gb.v64
+ - /menu/emulators/gbc.v64
+
+now load your roms and maybe saves on there. i've currently got mine in a `/roms/` folder but they can be loaded from anywhere. anything outside the above list is fair game.
+
+## hardmodding
+
+pixelfx n64digital obsoletes the old ultrahdmi?
+
+looks like there's a "pixelfx retro gem" which replaces the n64digital but doesn't support rgb output, only hdmi
+
+supposedly there's also the "n64advanced v2" which is open source on github but doesn't seem to be readily available
+
+- https://github.com/borti4938/n64adv2_pcb
+- https://github.com/borti4938/n64adv2_fw
+
+https://www.reddit.com/r/n64/comments/1d6pzdm/n64_hdmi_2024_guide/
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/retroarch.md b/wiki.hugo/content/gaming/retroarch.md
new file mode 100644
index 0000000..1e67290
--- /dev/null
+++ b/wiki.hugo/content/gaming/retroarch.md
@@ -0,0 +1,11 @@
+## n64
+
+### shaders
+
+retro crisis n64
+
+Slot Mask Height: 2x1 or 4x1...
+: 1.00
+
+LUT Colors: Trin.1 | Trin.2 | Nec Mult. | NTSC
+: 1.00 (Trin.1)
\ No newline at end of file
diff --git a/wiki.hugo/content/gaming/wii.md b/wiki.hugo/content/gaming/wii.md
new file mode 100644
index 0000000..dfa5aef
--- /dev/null
+++ b/wiki.hugo/content/gaming/wii.md
@@ -0,0 +1,97 @@
++++
+updated = "2024-08-03"
++++
+
+## video output
+
+assuming no hard mods, the best you can get is to go through the component (YPbPr) signal chain in order to unlock 480p output. this is THE primary consideration when playing off of a wii, imo. there are a few games that only support 480i as well so that is another consideration.
+
+### display
+
+the "best you can do" is going to vary based on goals
+
+there's basically two "happy paths" here:
+
+- SD CRT TV that supports both 480i and 480p over component. This pretty much locks you into something high-end like a Sony PVM 14L5 or 20L5, but you get a setup that's not finicky and you also get lagfree gaming.
+
+- finding a 1440p IPS screen with HDMI input, and using something like an ElectronWarp https://electron-shepherd.com/collections/all/products/electronwarp or Mayflash Wii to HDMI https://amzn.to/4ft7Ddm -- this plugs right into the back and converts analog component into an hdmi output. couple that with a 1440p (300% or 3x integer scale) monitor that has a good upscaler/deinterlacer and low input lag, and you can get a way better experience than the LCD or plasma TVs of the era.
+
+things that don't work as well:
+
+- HD CRT TVs have horrible upscalers with lots of lag
+
+and then there's a finicky option:
+
+- PC CRT monitors. this locks you out of 480i which can be really annoying because not only do some games only run in 480i (and vc titles can run in 240p), the system menu will not show you anything until you blindly manage to switch it to 480p output. without doing this, you will just get an error like "out of sync range". so it's not enough to go from component to vga.
+
+
+
+i guess for upscaling/deinterlacing you could use something like an ossc or ossc pro or retrotink or whatever, to at least eliminate the 480i out of your analog chain and also have something easier to work with for any modern monitor/tv.
+
+### capture
+
+if doing component and nothing else, then get a component distribution amplifier like a calrad 937b. you can run it into a component capture card afterward, which... your only option pretty much ends up being the magewell pro capture hdmi and its breakout cable. yes that thing is $300 but it supports 240p over component so you won't have any issues with getting a signal out of the wii -- 240p/480i/480p should all work.
+
+
+
+if you convert from component YPbPr directly to VGA then you can look into VGA capture cards or also anything that accepts DVI-A should work too. i am told that the startech USB3HDCAP should work (but maybe not on linux?). a VGA splitter should also allow you to go into a PC CRT.
+
+if you convert from component YPbPr to HDMI or otherwise throw an ossc/etc at it, then you can easily capture HDMI these days using just about anything under the sun. (the avermedia bu113 live streamer cap 4k is like $99 at https://amzn.to/4fDLRn0 and does a great job from my experience -- only about 40ms latency in obs studio, no real quality loss, can handle 720x480@59.94Hz input just fine) you still have the option of going into a PC CRT with an HDMI to VGA adapter which is supposed to be lagless as well (as long as it doesn't scale content)
+
+### my setup
+
+wii -> component hd retrovision cables -> calrad 937b component distribution amp -> \[ magewell pro capture hdmi | sony vaio trinitron hmd-a100 via a YPbPr-to-VGA transcoder | mg16xu via an rca audio 1in4out switch \]
+
+alternatively:
+
+wii -> electronwarp wii2hdmi -> ezcoo splitter 1in2out -> \[ sony hmd-a100 via moread hdmi-to-vga dongle | avermedia bu113 capture card \]
+
+component costs: $423 ($123 without capture)
+- retrovision $30 https://amzn.to/4dBenEd
+- calrad ~$30 https://www.ebay.com/sch/i.html?_nkw=calrad+937b
+- magewell pro capture $300 https://amzn.to/3YFfePY
+- YPbPr to VGA transcoder $27 https://amzn.to/3WCh3up
+- 2x component cable sets for interconnect $36 https://amzn.to/3WCV9qN or https://amzn.to/4cfCebz / https://amzn.to/3YDnzDB
+
+hdmi costs: $190 ($90 without capture)
+- wii2hdmi $24 https://electron-shepherd.com/products/electronwarp
+- ezcoo hdmi splitter $30 https://amzn.to/4diVNRr
+- avermedia bu113 $100 https://amzn.to/3Acbb3l
+- tendak adapter + gender changer $20 https://amzn.to/3SHpLq5 + https://amzn.to/46CqcI5
+- 2x hdmi cables ~$16 https://amzn.to/4fCdtsR
+
+so it would be overall cheaper to go through hdmi and probably more convenient paradoxically lol. even if your ultimate output is a pc crt. somehow a2d2a doesn't take a noticeable toll
+
+the last thing to mention is if you really want to avoid any 480i/240p signal hassles you probably should get an ossc or retrotink to deinterlace / linedouble to 640x480 progressive signal. yes this is like another hundred or three. such is the price of pc crt i guess. really makes you think if it would be worth just going for a high-end pvm that accepts 480p/480i/240p over component... \*glances at ebay prices\* nvm
+
+## softmodding
+
+https://wii.guide
+
+once you're homebrewed and installed your ios stuff then usb loader gx is a far superior way to play your games for both wii and gamecube. just make sure to use 480p patches, turn off the deflicker filter if you're not using a CRT, and highly consider using the framebuffer output instead of the stretched output.
+
+## hardmodding
+
+electronAVE obsoletes a lot of other things except maybe the Wii Dual? https://electron-shepherd.com/collections/all/products/electronave-kit
+
+personally idk if it's worth it though, if you want pure digital output you might as well emulate. also having hdmi out could make it harder to route your signal around -- for example i have an issue where my blackmagic intensity pro 4k doesn't support 480p at all. component only supports 480i and hdmi doesn't support less than 720p.
+
+## wifi
+
+wii only supports wifi b/g on 2.4ghz with wpa2 at most
+
+i knew about the wpa2 thing (not really an issue since wpa3 is so new) and i figured out the 2.4ghz thing (i guess 5ghz was also too new but also the wii u doesn't do 5ghz wifi either -- probably bc 5ghz is reserved for the gamepad communication)
+
+the thing i did not know about until i went searching for it is that apparently wifi n is also too new? i had my router in "n only" mode for efficiency reasons but had to change it back to auto b/g/n/(ax) -- that stopped the error 51330 from happening and i could connect to wifi again
+
+it will prompt you to check for an update (phrased as "perform an update") but if you do this you will softlock the wii since the nintendo servers seem to be down?
+
+## etc
+
+### hardware revisions
+
+supposedly the RVL40 is better for 480p but i have an older wii and it isn't bad so i wouldn't replace a wii i already have. i might spend more effort looking for a rvl40 though if i didn't already have one. also if you softmod (which you should) then you can enable "480p bug fix" in usb loader gx to get corrected output on older wiis
\ No newline at end of file
diff --git a/wiki.hugo/content/links/_dump.md b/wiki.hugo/content/links/_dump.md
new file mode 100644
index 0000000..0971c90
--- /dev/null
+++ b/wiki.hugo/content/links/_dump.md
@@ -0,0 +1,53 @@
+### web
+
+minimum common web platform
+
+webfinger redirect in nginx config
+
+```nginx
+location /.well-known/webfinger {
+ if ( $arg_resource = "acct:hello@yaakov.online" ) {
+ return 302 'https://cloudisland.nz/.well-known/webfinger/?resource=acct:yaakov@cloudisland.nz';
+ }
+
+ return 404;
+}
+```
+
+mast logo
+
+openxri project
+
+
+
+indiekit, a nodejs server that helps static websites do indieweb stuff (is it like a cms?)
+
+### demetrification
+
+What Do Metrics Want?
+
+The quest to create a world without likes, retweets, and follower counts
+
+Will hiding likes on Instagram and Facebook improve mental health?
+
+### concert recording
+
+
+
+
+
+### varia
+
+V7MLIZ392DXQ4UC5GEMF
+
+### merch
+
+
+
+
+
+### music
+
+
+
+
\ No newline at end of file
diff --git a/wiki.hugo/content/links/_index.md b/wiki.hugo/content/links/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/links/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/links/essays.md b/wiki.hugo/content/links/essays.md
new file mode 100644
index 0000000..5c7deab
--- /dev/null
+++ b/wiki.hugo/content/links/essays.md
@@ -0,0 +1,62 @@
++++
+updated = "2018"
++++
+
+# Essays
+
+## Have you considered the alternative?
+https://homebrewserver.club/have-you-considered-the-alternative.html
+
+> There is a reason why we’re falling into this pattern of needing alternatives to the alternatives. And that is because… There are no alternatives. [...] what these alternatives all have in common is that they share the same model. A model that revolves around centralized services, vendor lock-in and marketing related surveillance, and all of that within a neoliberal context of the free market [...] The reason is that they have no choice within the economic system they choose to operate in.
+
+---
+
+> In short, both Whatsapp and FacebookMessenger can afford to deploy end-to-end encryption for your messages because it won’t hurt their bottom line, which is making money based on the surveillance of your behavior and your social graph. Adding crypto thus merely patches your privacy worries, but not the threat to it.
+
+---
+
+> the problem is not that federation doesn’t adapt, but rather that there are problems with its implementation for a very significant reason: software developers working on federated systems mostly work for free in their spare time or with little means [...] while Marlinspike seems to defend his product from a technological perspective, Gultsch’s counter argument moves back the discussion to the context of political economy.
+
+## Avoid News
+
+ 1) News does not represent the real world [...] the highly visible misleads us.
+
+ 2) News is irrelevant [...] It’s very difficult for us to recognize what’s relevant. It’s much easier to recognize what’s new [...] if something really important happens, you will hear about it, even if you try to live protected from the news in a cocoon
+
+ 3) News limits understanding [...] It’s not “news facts” that are important, but the threads that connect them
+
+ 4-5) News is toxic for your body/society [...] News consumers risk impairing their physical health [...] News leads to collective neurosis [...] **Psychological scars do not heal easily**
+
+ 6) News massively increases cognitive errors [...] Our brains crave stories that “make sense” – even if they don’t correspond to reality
+
+ 7) News inhibits thinking [...] **The passageway from working memory to long-term memory forms a bottleneck in our brain** [...] Because news disrupts concentration, it actively weakens comprehension
+
+ 8) News changes the structure of your brain [...] The more news we consume, the more we are exercising the neural circuits devoted to skimming and multitasking while ignoring those used for reading and thinking deeply [...] Your attention is set on fast-breaking events, so you hunger for more data about them [...] [this] feeds compulsive information-seeking behavior (CISB) [and long term potentiation (LTP)]
+
+ 9) News is a waste of time [...] Information is no longer a scarce commodity. But attention is.
+
+ 10) News separates reputation from achievement [...] people become famous for reasons that have little relevance to our lives
+
+ 11) News is produced by journalists [...] Fewer than ten percent of the news stories are original. Fewer than one percent are truly investigative
+
+ 12) Reports and forecasts can be or are wrong [...] Incorrect forecast are not only useless, they are harmful
+
+ 13) News is manipulative [...] News is the perfect Trojan horse. Few bits of news arrive without a hidden
+ agenda [...] It sets the public agenda
+
+ 14) News makes us passive [...] **News stories are overwhelmingly about things you cannot influence** [...] it can lead to passivity and a sense of victimhood. The scientific term is learned helplessness
+
+ 15) News gives us the illusion of caring [...] [it] delivers the illusion of care but doesn’t get us anywhere [...] we are not connected because we consume news
+
+ 16) News kills creativity [...] Things we already know severely impact creativity [...] If you want to come up with old solutions, read news
+
+ //Isn’t it inhumane not to care about Haiti? Your shtick feels pretty cold.//
+
+ Is it inhumane not to care about horrific things happening on other planets? The point is: You can’t care about everything in the universe, on the earth, in your country, not even in your city. Nor should you.
+
+ //Where is the compassion?//
+
+ Let me state this even stronger: Caring without action is inhumane. It gives us the illusion of making the world a better place. Truth is, we do it for us. We revel in the marinade of caring. What does it change? It makes us feel good (humane if you like) but doesn’t help a thing. [...] Empathy – if it remains empathy – is useless.
+
+http://www.dobelli.com/en/essays/news-diet/
+https://web.archive.org/web/20180106154431/http://www.dobelli.com/en/essays/news-diet/
\ No newline at end of file
diff --git a/wiki.hugo/content/links/quotes.md b/wiki.hugo/content/links/quotes.md
new file mode 100644
index 0000000..7590952
--- /dev/null
+++ b/wiki.hugo/content/links/quotes.md
@@ -0,0 +1,21 @@
++++
+updated = "2018"
++++
+
+# Quotes
+
+## Managers need private offices for "productivity" but put their workers in open offices
+
+https://arstechnica.com/science/2018/07/in-open-offices-workers-chat-70-less-are-less-productive-and-email-more/?comments=1&post=35658503#comment-35658503
+
+> When they went to open office one of my friends said in the announcement meeting it was asked why managers and higher ups needed offices. Productivity was the answer. Didn't seem to phase them that the people actually doing the producing were going to be producing less.
+
+## "I watched an entire Flat Earth Convention for my research – here’s what I learnt"
+
+https://theconversation.com/i-watched-an-entire-flat-earth-convention-for-my-research-heres-what-i-learnt-95887
+
+> While flat earthers seem to trust [...] scientific methods, what they don’t trust is scientists [...] those in power control what is considered to be correct [...] According to Foucault, there is therefore an intimate [...] relationship between power and knowledge.
+
+> With the increased voice afforded by social media, knowledge has been increasingly decentralised, and competing narratives have emerged.
+
+> one of the physicists pleaded with the audience to avoid trusting YouTube and bloggers. The audience and the panel of flat earthers took exception to this, noting that “now we’ve got the internet and mass communication … we’re not reliant on what the mainstream are telling us in newspapers, we can decide for ourselves”.
\ No newline at end of file
diff --git a/wiki.hugo/content/optics/_index.md b/wiki.hugo/content/optics/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/optics/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/optics/how-to-order-glasses-online.md b/wiki.hugo/content/optics/how-to-order-glasses-online.md
new file mode 100644
index 0000000..13de196
--- /dev/null
+++ b/wiki.hugo/content/optics/how-to-order-glasses-online.md
@@ -0,0 +1,64 @@
++++
+updated = "2018"
++++
+# How to order glasses online
+
+## My measurements
+
+SIZE =
+- frame width: medium (135mm-139mm -- ~136mm) // 141mm?
+- bridge width: small (17-18mm -- ~17mm) // 18mm
+- lens width: medium (52-54mm -- ~53mm) // 52mm
+- lens height: medium (33-40mm -- ~35mm) // 32mm??
+- temple arm: medium (135-144mm -- ~140mm) // 145mm?
+
+PD =
+- Single: 65mm (64.5mm)
+- Dual: ~32.5mm right / ~32.5mm left? 33/32? 32/33?
+
+PRESCRIPTION = Single Vision
+```
+ SPH CYL AXIS
+OD -6.50 -0.75 30
+OS -5.75 -0.75 170
+```
+------------------------------
+
+## NOTES:
+
+### Abbe numbers
+- Abbe value measures color dispersion.
+- Higher Abbe means less chromatic aberration.
+- glass is the best, low-index plastics are close, polycarbonates suck
+- Crown glass = 59
+- CR-39 Plastic = 58
+- Trivex = 43
+- Polycarbonate = 30
+
+### Clarity, peripheral vision, chromatic aberration
+- look for a high abbe value if you want
+ - more clarity,
+ - better peripheral vision,
+ - and less chroma aberration.
+- consequently, the index actually doesn't matter for clarity; it only really matters for thickness! a high-index lens will typically lower the abbe value and therefore reduce clarity.
+
+### Aspheric lens
+- aspheric designs will change curvature gradually, leading to flatter lens and better peripheral clarity. many high-index plastics might have aspheric designs to counteract the thicker edges.
+
+### Distortion
+- i ordered one trivex and one 1.67 high-index from zenni but both glasses had distortion at edges.
+- i think that's normal but i personally can't live with it, so i returned them and will be saving money to buy something with a better material.
+ - lenscrafters advertises this as "hd lenses", which is also a manufacturing process-based technique. if that's anything like what i did in amman, then an eye scan will be required. the digital scan of your eyes is used to carve out much more precise lenses up to 0.01D instead of 0.25D increments.
+
+### UV / Blue Light
+- UV protection coating is kinda bullshit, the lens material will typically block <380nm anyway
+- Blue light filters are even more bullshit, and can actively cause color shifts!
+
+------------------------------
+
+## RESOURCES:
+
+- https://www.visioncareproducts.com/high-index-lens-materials-past-present-future/
+- http://www.mastereyeassociates.com/eyeglass-lens-materials
+- http://www.trivexspecialist.com/blog/slimming-down-are-high-index-lenses-always-the-answer/
+- https://www.allaboutvision.com/lenses/how-to-choose.htm
\ No newline at end of file
diff --git a/wiki.hugo/content/photography.md b/wiki.hugo/content/photography.md
new file mode 100644
index 0000000..fa60d43
--- /dev/null
+++ b/wiki.hugo/content/photography.md
@@ -0,0 +1,19 @@
++++
+title = "Photography"
+updated = "2019"
++++
+## "Beginner" vs "expert" is a false dichotomy
+
+There is no camera for "beginners". It doesn't make any sense to recommend a camera based on skill level at all. Instead, getting into photography should go something like this:
+
+### Self-discovery
+Identify the area / subject matter you're interested in, and just start taking pictures! It doesn't matter if you only have a smartphone that only does auto. The important thing is to start taking pictures. Start gaining experience and get that sense of when something is photo-worthy, and how you want it to look. Start learning about framing and focus and other stuff like that.
+
+### Theory
+Once you've got those basics understood, it's time to learn about how photography works. Get a camera with manual mode. Teach yourself about aperture, shutter speed, and sensitivity, then teach yourself how each of those settings affects the output of your camera. Internalize the effects that each parameter will have on the picture -- how will it affect brightness? noise? blur? etc. Start learning to tune your camera's settings for each scene.
+
+### Development
+Find a camera that can take RAW photos. Learn how to develop those photos. Familiarize yourself with all the factors that go into outputting a finalized image -- exposure levels, color balance, sharpening and denoising filters, and so on. Pick a software and learn it.
+
+### Optional: Going pro / specializing
+By this point you should have a thorough understanding of the types of pictures you want to take, how to actually take those pictures with your camera of choice, and how to develop the raw output into a pleasing image. This is the point where you can start looking into specialized equipment and gear that suits the niche you're most interested in -- landscape? architecture? street? still-life? portrait? event? If you have enough money or you can start making money from photography, then you can start looking at picking out gear that will help you take the photos you want. Pick out a good body (sensor size? ISO? resolution? autofocus?) then pick out some lenses (focal length? aperture?) and you should be able to take all the photos you want.
diff --git a/wiki.hugo/content/politics/_index.md b/wiki.hugo/content/politics/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/politics/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/politics/fascism.md b/wiki.hugo/content/politics/fascism.md
new file mode 100644
index 0000000..ee4904e
--- /dev/null
+++ b/wiki.hugo/content/politics/fascism.md
@@ -0,0 +1,52 @@
++++
+title = "Fascism"
+updated = "2019"
++++
+
+
+## Definition
+**Fascism** is a political ideology defined by the following:
+
+1. The myth of the **great nation**, meant to elicit pride in the Nation and its former accomplishments.
+2. The myth of **degeneracy**, which is a scapegoat for all of the Nation's failings and the cause of its supposed decline.
+3. The myth of **national rebirth**, i.e. returning the Nation to greatness, typically by "cleansing" the Nation of the aforementioned "degeneracy".
+
+# Related fundamental concepts you should be aware of
+
+**What is a nation?** A *nation* is a shared cultural or political identity. It is not strictly the same as a *government* (legal body), a *country* (geography), or an *ethnicity* (culture), although it may be defined along those lines. It is also not to be confused with a *state* (monopoly on power).
+
+**Social radix:** For fascists, national identity is the root of all society.
+
+## Characteristics
+
+### Third Positionism against liberalism and against socialism
+Fascism positions itself as *against democracy* and *against Marxism*. It is anti-liberal and anti-socialist (especially anti-communist), and instead occupies the "Third Position".
+
+### Fetishization of order
+Fascism is more dedicated to *order* rather than *justice*. All individuals are expected to have a duty to protect the Nation-State and uphold its interests and values. Any concept of "the greater good" beyond the national interest is mostly nonexistent. All that matters is preserving "law and order", i.e. preserving the superiority of your own nation above others. This focus on stability, discipline, hierarchy, and national pride permeates all of society.
+
+>Individuals simply [cannot] be relied on voluntarily to 'obey the law, pay their taxes and serve in war'. **No well-ordered society could want the people to be sovereign.**
+>
+>*Benito Mussolini*
+
+## Things that are fascism
+
+* Wanting to establish a national empire
+* Wanting to conquer or subjugate other nations, or to make them subservient to your nation
+* Believing that some nations are inferior to others
+* Believing that certain peoples/cultures/lifestyles are bringing your nation down
+* Eliminating rights of a targeted subgroup for above reasons
+* Restricting entry or physically expelling a targeted subgroup for above reasons
+* Murdering a targeted subgroup for above reasons
+
+## Things that are not fascism
+
+* A willingness to use violence
+* A willingness to use violence in self-defense
+* Defending a community against violence
+* Having a government
+* Having a government that does things
+* Anything a government does
+* Not letting someone give a speech
+* Not letting someone organize in your community
+* Not listening to someone trying to speak
\ No newline at end of file
diff --git a/wiki.hugo/content/politics/neoliberalism.md b/wiki.hugo/content/politics/neoliberalism.md
new file mode 100644
index 0000000..c392d75
--- /dev/null
+++ b/wiki.hugo/content/politics/neoliberalism.md
@@ -0,0 +1,7 @@
++++
+title = "Neoliberalism"
++++
+
+neoliberalism is just largely a return to liberalism; the idea that govt's role is to help business, that markets can be used as a force for good https://en.wikipedia.org/wiki/Neoliberalism
+
+maybe best exemplified by thatcher, reagan, greenspan, clinton; the support of "free trade" agreements like NAFTA and TPP or organizations like the IMF or WTO; opposition to people like ralph nader in the 1970s; concepts like "the marketplace of ideas" or "soft power"; in short, everything is a market and the experts should decide the best policies to help the market
\ No newline at end of file
diff --git a/wiki.hugo/content/politics/policy.md b/wiki.hugo/content/politics/policy.md
new file mode 100644
index 0000000..93e9ad7
--- /dev/null
+++ b/wiki.hugo/content/politics/policy.md
@@ -0,0 +1,15 @@
++++
+updated = "2019"
++++
+
+# Policy
+
+## 'It’s a miracle': Helsinki's radical solution to homelessness
+Finland is the only EU country where homelessness is falling. Its secret? Giving people homes as soon as they need them – unconditionally
+
+
+> “We had to get rid of the night shelters and short-term hostels we still had back then. They had a very long history in Finland, and everyone could see they were not getting people out of homelessness. We decided to reverse the assumptions.”
+
+> As in many countries, homelessness in Finland had long been tackled using a staircase model: you were supposed to move through different stages of temporary accommodation as you got your life back on track, with an apartment as the ultimate reward.
+
+> “We decided to make the housing unconditional,” says Kaakinen. “To say, look, you don’t need to solve your problems before you get a home. Instead, a home should be the secure foundation that makes it easier to solve your problems.”
\ No newline at end of file
diff --git a/wiki.hugo/content/politics/radicalization.md b/wiki.hugo/content/politics/radicalization.md
new file mode 100644
index 0000000..72355c8
--- /dev/null
+++ b/wiki.hugo/content/politics/radicalization.md
@@ -0,0 +1,22 @@
++++
+title = "Radicalization"
+updated = "2018"
++++
+
+## The three factors of radicalization
+
+>For radicalization to occur, there are three necessary ingredients, according to Kruglanski’s research. The first is the universal need to live a worthwhile life — to have significance. People usually satisfy this need through socially accepted means, “like working hard, having families, other kinds of achievements,” Kruglanski said. Radicals instead tend to place significance on their gender, religion or race.
+>
+>The second is “the narrative,” which gives someone permission to use violence. Kruglanski said the narrative is usually that there is an enemy attacking your group, and the radical must fight to gain or maintain respect, honor or glory.
+>
+>The third necessary component is the community, or the network of people who validate the narrative and the violence.
+
+-- ["The psychology of how someone becomes radicalized" (Angela Fritz, The Washington Post, 2018 Nov 1)](https://www.washingtonpost.com/science/2018/11/01/psychology-how-someone-becomes-radicalized/?noredirect=on&utm_term=.bb1c34780f0b)
+
+## Deradicalization tactics
+
+>Weilnboeck says one lesson successful facilitators have learned is to avoid engaging in debates about politics or religious doctrine with those they are trying to deradicalize.
+>
+>He says such debates usually fail to alter the belief system of a violent extremist, especially in the early stages of a deradicalization program, but will almost certainly foster distrust.
+
+-- ["The Dos And Don'ts Of Deradicalizing Violent Extremists" (Ron Synovitz, Radio Free Europe / Radio Liberty, 2015 Sep 6)](https://www.rferl.org/a/deradicalizing-violent-extremists-what-works-what-does-not-work/27229417.html)
\ No newline at end of file
diff --git a/wiki.hugo/content/politics/voluntarism.md b/wiki.hugo/content/politics/voluntarism.md
new file mode 100644
index 0000000..a894440
--- /dev/null
+++ b/wiki.hugo/content/politics/voluntarism.md
@@ -0,0 +1,11 @@
++++
+title = "Voluntarism"
++++
+
+## criticisms
+
+pursuing pure voluntarism as an ideology (and not simply an ideal) tends to ignore the realities of power imbalances. If two people are inequal, then they can never come to a voluntary agreement -- the power of one will coerce the other, even if subconsciously.
+
+Consider whether one can "voluntarily" become a slave. Or, more relevant today, consider the wage labor system. Is it truly "voluntary" if your food, shelter, and very survival depends on such a "voluntary" arrangement?
+
+The cold reality is that voluntarism is merely idealism so long as any social class or hierarchy exists. Maybe some prefigurative politics are necessary, but you have to push for progress without 100% support or you'll wait forever.
\ No newline at end of file
diff --git a/wiki.hugo/content/search/_index.md b/wiki.hugo/content/search/_index.md
new file mode 100644
index 0000000..a7f481a
--- /dev/null
+++ b/wiki.hugo/content/search/_index.md
@@ -0,0 +1,3 @@
++++
+title = "Search"
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/sitemap/_index.md b/wiki.hugo/content/sitemap/_index.md
new file mode 100644
index 0000000..437bee0
--- /dev/null
+++ b/wiki.hugo/content/sitemap/_index.md
@@ -0,0 +1,3 @@
++++
+title = "sitemap"
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/!misc.md b/wiki.hugo/content/tech/!misc.md
new file mode 100644
index 0000000..a6ff085
--- /dev/null
+++ b/wiki.hugo/content/tech/!misc.md
@@ -0,0 +1 @@
+prefer xml for trees, json(ld) for graphs?
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/_index.md b/wiki.hugo/content/tech/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/tech/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/communication.md b/wiki.hugo/content/tech/communication.md
new file mode 100644
index 0000000..82f0e8f
--- /dev/null
+++ b/wiki.hugo/content/tech/communication.md
@@ -0,0 +1,36 @@
++++
++++
+
+## Paradigms
+
+### 1-1 or 1-n
+
+### push or pull
+
+### relaying aka intermediaries
+
+## Separation of concerns
+
+### Publishing
+
+> "I want to share this with the world."
+
+For a resource to be visible to other people, it must first be published. Typically, resources are published at a location or with a specific identifier; people who wish to view that resource can then go to that location or search for that identifier using a lookup service in order to view the resource. Most commonly, resources are published on the World Wide Web, and they are found via their uniform resource location (URL). When you type, paste, or click a link in your Web browser, your browser will make a request to fetch that resource on your behalf, and the server responsible for that resource will respond with the resource.
+
+### Subscribing
+
+> "I want to see the things I am interested in."
+
+OK, so there are resources that we can access if they are published at a known location or with a known identifier. How do we know when there are new or updated resources? At the most basic level, you can manually check a resource to see if it has been updated; for example, you can check a website to see if there are any new pages. To make this manual checking process easier, publishers can generate a feed or stream of resources that can be subscribed to. When you subscribe to that feed, your feed reader will periodically check the feed for any changes; for example, a feed may be updated with the latest articles from a Web site, which your reader will then pull and show to you as an update.
+
+### Messaging
+
+> "I want to communicate directly with people."
+
+In some ways, messaging can be covered by having a publisher and a subscriber on each end of a conversation, but it usually makes more sense to deliver messages to your conversational partners directly rather than having them check for new messages on their own schedule.
+
+### Discussing
+
+> "I want to gather in a community or around a topic."
+
+Traditionally, this has been handled by forums, bulletin board systems, and groups.
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/computers/_index.md b/wiki.hugo/content/tech/computers/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/computers/build-notes.md b/wiki.hugo/content/tech/computers/build-notes.md
new file mode 100644
index 0000000..699eb89
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/build-notes.md
@@ -0,0 +1,61 @@
++++
+updated = "2018"
++++
+# Build Notes
+
+## ASUS Z170I Gaming
+a mini-itx z170 board combo'd with an i5-6600k.
+
+### what to do with this board
+- should i use it as a windows gaming machine?
+- should i use it as a home server?
+
+right now i installed windows on a cheap nvme drive and have it powered by the evga 500bq; i bought a bitfenix prodigy for it so i guess it can be spec'd out for either use case thanks to that case's spaciousness. (whereas if i had gotten a ds380b it would've had some cooling issues, would've required me to buy an sfx psu, and wouldn't make for a good desktop at all -- so an expensive waste of money)
+
+## ASUS MAXIMUS VIII HERO
+z170 atx motherboard that i bought as part of a combo with an i7-6700k.
+
+### observations
+- one POST issue has been narrowed down to a weird interaction between thunderbolt support and igpu? specifically it seems to freeze (q code 60, as of latest testing) when both "igpu multi monitor" and "thunderbolt boot support" are enabled... and maybe some other thunderbolt options like usb or just thunderbolt in general, but i can't remember and i don't wanna retest, so i just disabled thunderbolt entirely.
+- another POST issue (q code 22 / 55 / occasionally cc?) was happening when a certain stick of g.skill trident z rgb ddr4-3200 was inserted. i sent that kit off for rma, but i've read that perhaps asus motherboards can silently corrupt some earlier gskill trident z revisions. not sure about the validity of that statement but i guess i might wanna take it as an opportunity to sell them off and upgrade to 4x16gb idk
+
+## Supermicro X9DAE
+
+boy do i kinda hate this motherboard after all the problems it's given me and how meh supermicro's rma process has been
+
+### gotchas
+
+#### uefi boot usb must use usb2.
+booting from uefi usb seemingly doesn't work, until you put the usb key into a **usb2** port.
+the two rear usb3 ports **do not work** for this!
+
+#### lpddr3 is gaslighting me.
+16x8gb samsung pc3L-12800R (lpddr3-1600 equivalent) would not work reliably...
+...until it suddenly does, and then again suddenly doesn't.
+i thought i had a dead stick because it wouldn't boot with all 16 filled.
+then i thought it was misaligned cpu2 pins
+then i thought it was cpu2 power delivery
+then shuffling the sticks around made it somehow work... temporarily
+clearing cmos made ALL the samsung ecc ram stop working
+...but some standard corsair / kingston ddr3 ram works perfectly fine!
+i still don't know if the ecc ram i bought is working,
+or if the motherboard is incompatible, or what.
+supermicro advertises 1.35v / 1.5v compatibility but
+1.35v has not worked consistently for me at all
+
+#### hangs on BIOS if any connected drive has corrupted boot
+i had an ssd connected with a windows 10 install that borked itself,
+and that inadvertently caused the BIOS to become completely inaccessible
+until i figured out that i needed to disconnect the disk...
+the same thing happened when i left an install usb key plugged in???
+
+### so many RMAs ughhhh
+
+1st rma was for not powering on when shorting the power pins, replaced. 2nd rma supposedly repaired a black screen issue / phantom overheat, and, well... it no longer trips the JOH1 header but it still has the black screen issue. after some amount of time the system hangs and the video output goes to "no signal". it seems to work for a few hours, then it doesn't work for like a full day, then it starts working again after you leave it alone for a while, ad nauseum.
+
+- is it the psu?
+- is it the cpu1 pins?
+- is it the ethernet?
+- is it the ssd?
+
+~who even knows~ seems to be that evga nex750g power supply, because it's not happening with a new evga 500bq... also apparently you can test supermicro mobos without the cpu1/2 pins -- those are just used for delivering more power when needed. thanks to being told this by a rep, i was able to test more psus and discover this. so i guess now i need to buy a new/working psu with dual eps. ugh. also presumably the ram actually works, but i haven't tested all 16 sticks with a working psu.
diff --git a/wiki.hugo/content/tech/computers/graphviz.md b/wiki.hugo/content/tech/computers/graphviz.md
new file mode 100644
index 0000000..8ee9d14
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/graphviz.md
@@ -0,0 +1,192 @@
+```
+graph desktop {
+ label = "desktop"
+ rankdir = LR
+
+ subgraph legend {
+ label = "Legend"
+
+ legend_label [label = ""; xlabel = "Legend"; width = 0; height = 0]
+ unavailable [label = ""; xlabel = "unavailable"; width = 0.25; height = 0.25; shape = box; color = grey]
+ unused [label = ""; xlabel = "unused slot"; width = 0.25; height = 0.25; shape = box]
+ used [label = ""; xlabel = "used slot"; width = 0.25; height = 0.25; shape = box; color = "#333"; style = filled]
+ component [label = ""; xlabel = "component"; width = 0.25; height = 0.25; shape = box; color = grey; style = filled]
+ warning [label = ""; xlabel = "warning"; width = 0.25; height = 0.25; shape = box; color = orange; style = filled]
+
+ legend_label -- unavailable [style = invis]
+ legend_label -- unused [style = invis]
+ legend_label -- used [style = invis]
+ legend_label -- component [style = invis]
+ legend_label -- warning [style = invis]
+ }
+
+ node [
+ shape = box
+ height = 0.5
+ width = 1
+ ]
+
+ edge [
+ penwidth = 1.25
+ ]
+
+ subgraph cluster_motherboard {
+ label = "Motherboard: Aorus MASTER rev1.2 (X570)"
+
+ subgraph cluster_usb3 {
+ label = "USB headers"
+
+ usb2_1
+ usb2_2
+
+ usb3_1
+ usb3_2
+
+ usbc_1
+ }
+
+ subgraph cluster_sata {
+ label = "SATA 3.0\nheaders"
+
+ sata_1
+ sata_2
+ sata_3
+ sata_4
+ sata_5
+ sata_6
+ }
+
+ subgraph cluster_nvme {
+ label = "3x PCIe 4.0 M.2 NVME"
+
+ # The Aorus Master 1.2 has 3x NVME slots
+ nvme_1
+ nvme_2
+ nvme_3
+
+ # My NVME drives
+ nvme_drive_1 [label = "WD SN850 2TB PCIe 4.0"; width = 2.5; color = grey; style = filled]
+ nvme_drive_2 [label = "WD SN850 2TB PCIe 4.0"; width = 2.5; color = grey; style = filled]
+ nvme_drive_3 [label = "WD SN850 2TB PCIe 4.0"; width = 2.5; color = grey; style = filled]
+
+ nvme_1 -- nvme_drive_1; nvme_1 [color = "#333"; style = filled; fontcolor = white]
+ nvme_2 -- nvme_drive_2; nvme_2 [color = "#333"; style = filled; fontcolor = white]
+ nvme_3 -- nvme_drive_3; nvme_3 [color = "#333"; style = filled; fontcolor = white]
+
+ # Filling the 3rd NVME slot disables two SATA slots
+ sata_5 [color = grey; fontcolor = grey]
+ sata_6 [color = grey; fontcolor = grey]
+ sata_5 -- nvme_3 [color = orange]
+ sata_6 -- nvme_3 [color = orange]
+ }
+
+ subgraph cluster_pcie {
+ label = "PCIe slots"
+
+ subgraph pcie_cpu_lanes {
+ label = "PCIe slots from CPU lanes are linked."
+ rank = same
+
+ pcie_x16_1 [label = "PCIe 4.0 x16 (running x16)"; width = 3]
+ pcie_x16_2 [label = "PCIe 4.0 x16 (running x8)"; width = 3; color = grey; fontcolor = grey]
+ # using the 8x slot reduces the 16x to 8x
+ pcie_x16_2 -- pcie_x16_1 [color = orange; tailport = n; headport = s]
+ }
+ pcie_x1 [label = "PCIe 4.0 x1 (running x1)"; width = 3]
+ pcie_x16_3 [label = "PCIe 4.0 x16 (running x4)"; width = 3]
+
+ # graphics card 16x
+ asrock_5700xt [label = "AMD RX 5700 XT\n(AsROCK Challenger D OC 8GB)"; color = grey; style = filled]
+ pcie_x16_1 -- asrock_5700xt; pcie_x16_1 [color = "#333"; style = filled; fontcolor = white]
+
+ # capture card 4x
+ bm_ip4k [label = "Blackmagic Intensity Pro 4K"; width = 3; color = grey; style = filled]
+ pcie_x16_3 -- bm_ip4k; pcie_x16_3 [color = "#333"; style = filled; fontcolor = white]
+ }
+
+ subgraph cluster_cpu {
+ label = "AM4 socket"
+
+ cpu [label = "AMD Ryzen 5950x"; width = 2; color = grey; style = filled]
+ }
+
+ subgraph cluster_ram {
+ label = "DDR4 RAM slots"
+
+ ram_1
+ ram_2
+ ram_3
+ ram_4
+
+ # 128gb kit
+ vengeance_128gb [label = "128GB (4x32GB) DDR4-3600 C18\nCorsair Vengeance LPX"; width = 3.5; height = 2.75; color = grey; style = filled]
+ ram_1 -- vengeance_128gb; ram_1 [color = "#333"; style = filled; fontcolor = white]
+ ram_2 -- vengeance_128gb; ram_2 [color = "#333"; style = filled; fontcolor = white]
+ ram_3 -- vengeance_128gb; ram_3 [color = "#333"; style = filled; fontcolor = white]
+ ram_4 -- vengeance_128gb; ram_4 [color = "#333"; style = filled; fontcolor = white]
+ }
+
+ }
+
+ subgraph cluster_case {
+ label = "Case: CM HAF 932"
+
+ subgraph cluster_front_bays {
+ label="5.25\" Front bays"
+
+ # 6x front bays
+ bay_1
+ bay_2
+ bay_3
+ bay_4
+ bay_5
+ bay_6
+
+ # Bay 1: USB 3.0 card reader
+ kingwin_bay_adapter [label = "Kingwin 5.25\" to 3.5\" adapter"; width = 3]
+ vantec_card_reader [label = "3.5\" USB 3.0 Card Reader\n(Vantec UGT-CR935)"; width = 3; color = grey; style = filled]
+ bay_1 -- kingwin_bay_adapter -- vantec_card_reader; bay_1 [color = "#333"; style = filled; fontcolor = white]
+ vantec_card_reader -- usb3_1 [tailport = n; headport = w]; usb3_1 [color = "#333"; style = filled; fontcolor = white]
+
+ # Bay 2: SATA hotswap bays
+ syba_hotswap [label = "Syba 5.25\" Hotswap Bay"; width = 3; color = grey; style = filled]
+ bay_2 -- syba_hotswap; bay_2 [color = "#333"; style = filled; fontcolor = white]
+ syba_hotswap -- sata_1 [tailport = e; headport = w]; sata_1 [color = "#333"; style = filled; fontcolor = white]
+ syba_hotswap -- sata_2 [tailport = e; headport = w]; sata_2 [color = "#333"; style = filled; fontcolor = white]
+ syba_hotswap -- usb3_2 [tailport = e; headport = w]; usb3_2 [color = "#333"; style = filled; fontcolor = white]
+
+ # Bay 3: DVD drive
+ asus_dvd [label = "ASUS DVD Drive 24x"; width = 3; color = grey; style = filled]
+ bay_3 -- asus_dvd; bay_3 [color = "#333"; style = filled; fontcolor = white]
+ asus_dvd -- sata_3 [tailport = e; headport = w]; sata_3 [color = "#333"; style = filled; fontcolor = white]
+
+ # Bay 4: Kloud City drawer
+ kloud_city_1 [label = "Kloud City 5.25\" drawer"; width = 3; color = grey; style = filled]
+ bay_4 -- kloud_city_1; bay_4 [color = "#333"; style = filled; fontcolor = white]
+
+ # Bays 5-6: Evercool Dual
+ evercool_dual [label = "Evercool Dual\n5.25\" to 3x 3.5 drives"; height = 1.25; width = 3]
+ bay_5 -- evercool_dual; bay_5 [color = "#333"; style = filled; fontcolor = white]
+ bay_6 -- evercool_dual; bay_6 [color = "#333"; style = filled; fontcolor = white]
+ }
+
+ subgraph cluster_drive_sleds {
+ label = "Drive sleds"
+
+ sled_1
+ sled_2
+ sled_3
+ sled_4
+ sled_5
+ }
+
+ subgraph cluster_cpu_clearance {
+ label = "CPU cooler\nclearance: 172mm"
+
+ cpu_cooler [label = "Noctua NH-D15S"; width = 1.75 color = grey; style = filled]
+ }
+
+ }
+
+}
+```
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/computers/linux-laptop.md b/wiki.hugo/content/tech/computers/linux-laptop.md
new file mode 100644
index 0000000..8486ad0
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/linux-laptop.md
@@ -0,0 +1,35 @@
++++
+updated = "2019"
++++
+# Linux laptop
+i'm using an asus zenbook infinity (ux301la-dh71t) for this. main challenges of laptops are being limited to 1 monitor, needing to set up hotkeys, and other such stuff.
+
+## WM/DE experiences/ratings
+
+### Good?
+- Sway (pure Wayland, no big dependencies, but need to figure out how to supplement it with DE stuff like notification area, easily-configurable panel, notifications, audio settings, and a better menu than dmenu) (i ended up going with sway as my main environment, paired with waybar / mako / pavucontrol / rofi, and also screenshots with grim+slurp)
+- XFCE + xfwm (no-nonsense traditionalism but bad tiling, so you need to use a different workflow based around a dockbar/panel instead of tiling and workspaces.)
+- XFCE + i3-gaps (a good compromise between DE and WM, at least for X11)
+- Deepin (pretty but idk if it's functional yet -- play around more with it)
+
+### Interesting
+- Qtile (need to learn how to use it bc it seems decent, similar to sway/i3 but no idea how to open menus yet, unfortunately doesn't seem to be mouse-driven at all)
+
+### IDK
+- bspwm / herbsluftwm (need config before opening?)
+
+### Not-so-good?
+- Budgie (scaling a bit weird, and idk why but i don't really like the styling of it even though it's clean and makes sense)
+- awesome (haven't been able to configure it how i want to with the title bars, but otherwise *seems* solid)
+
+### Eh...
+- GNOME (too limited and boring)
+- KDE (bad design)
+
+### Not good
+- Openbox/Fluxbox (too much hardcoded stuff)
+- Notion (too bare/ugly)
+
+### Broken
+- way-cooler (failed to compile)
+- liri-desktop (no input from mouse/keyboard)
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/computers/obs.md b/wiki.hugo/content/tech/computers/obs.md
new file mode 100644
index 0000000..a0090e4
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/obs.md
@@ -0,0 +1,18 @@
+## crt filter pipeline in obs studio
+
+source: 640x480 progressive signal (so deinterlaced with obs Retro or through amarectv plus automatic line-doubling)
+
+- [if capturing through amarec] Crop/Pad "Crop off Amarec window border"
+ - relative crop, 4px in each direction
+- Scaling/Aspect ratio "Scale up for high-res effects"
+ - Point scale 3840x2880 (6x 480p)
+- User-defined shader "Shader: TV CRT subpixel" [from obs-shaderfilter]
+ - width 1, height 3, horizontal/vertical gaps 1
+- Scaling/Aspect ratio "Scale back down to 4x (1280x960)"
+ - Bilinear scale 1280x960
+- User-defined shader "Shader: Bloom" [from obs-shaderfilter]
+ - amp factor 2.00, angle/radius steps at least 6 (but 20 is better)
+- Image Mask/Blend "Scanlines mask"
+ - alpha mask (alpha channel) [image](/scanlines-mask-640x480.png)
+- [Optional] User-defined shader "Shader: CRT curvature" [from obs-shaderfilter]
+ - adjust to taste. i was toying around with strength 16 and feathering 16 before turning it off
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/computers/zfs.md b/wiki.hugo/content/tech/computers/zfs.md
new file mode 100644
index 0000000..f237617
--- /dev/null
+++ b/wiki.hugo/content/tech/computers/zfs.md
@@ -0,0 +1,7 @@
+## test dedup performance
+
+generally not a good idea to enable dedup unless you have a lot of similar vms or database backups or whatever, and have more RAM to spare than hard disk space
+
+```
+zdb -S poolName
+```
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/gorillaglass.md b/wiki.hugo/content/tech/gorillaglass.md
new file mode 100644
index 0000000..5fb2d65
--- /dev/null
+++ b/wiki.hugo/content/tech/gorillaglass.md
@@ -0,0 +1,13 @@
++++
+updated = "2018"
++++
+# Gorilla Glass
+
+Gorilla Glass is a brand of glass made by Corning and frequently used to manufacture smartphones. This page lists some of the details of each generation, such as chemical makeup, durability, scratch resistance, shatter resistance, and changes to these between generations.
+
+## Gorilla Glass 1
+## Gorilla Glass 2
+## Gorilla Glass 3
+## Gorilla Glass 4
+## Gorilla Glass 5
+## Gorilla Glass 6
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/mastodon/_index.md b/wiki.hugo/content/tech/mastodon/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/tech/mastodon/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/mastodon/issue-tracker.md b/wiki.hugo/content/tech/mastodon/issue-tracker.md
new file mode 100644
index 0000000..d8b5a62
--- /dev/null
+++ b/wiki.hugo/content/tech/mastodon/issue-tracker.md
@@ -0,0 +1,498 @@
++++
+toc = true
+autonumbering = true
++++
+
+## (closeable)
+
+### (duplicates)
+
+### (maybe closeable?)
+
+- #813 split docker-compose deployment into "web" and "streaming" [i.e. separate image for streaming API -- is this relevant to current docker strategy?]
+- #1298 add custom entries to Getting Started [the motivation was adding a link to code of conduct, although this could be more generally useful outside that context]
+- #1306 timeline scroll jumps when new posts come in [addressed by slow mode?]
+ - #1774 timeline scroll jumps when posts are deleted
+- #3283 composing a long post with overflow will cause jumping on typing
+- #3369 ctrl+z after posting used to restore the text to the compose box, but now it does not
+- #3858 allow pinning favourites column and user profile columns [half-fixed -- you can pin favs but you still can't pin user profiles]
+- #4701 show private posts in hashtag search if you are authorized to see them [closed as "intentional" in #2440 but idk maybe it could be reconsidered]
+- #4869 filters should apply to emoji [this was filed back when regex filters were a thing, and seems to have been shown to work even back then, so was not reproducable] [small caveat: could extract a feature request out of this for allowing filtering an emoji by its shortcode? but probably not needed]
+- #5403 reblog `url` is sometimes null when it marked non-nullable [i think this isn't happening anymore]
+- #5737 store metadata about relationship changes (when/why) [we have profile notes now so that probably works]
+- #5896 allow mods to force hide all media from an account [is this the same as "force-mark as sensitive" or is it more like "reject media"?]
+- #6033 postgres 10 has a long-running query on public timelines? [is this still relevant]
+- #6064 remote suspensions do not always reach you for followers? [has this been fixed now? issue is from 2017]
+- #6073 hashtag cloud on landing/about page [is this addressed by trending tags on explore page?]
+- #6250 don't send email notifications if a notification is seen in an active session [isn't this done by default now? there's a setting to "always send"]
+- #6321 "quiet hours" mode where notifications are not shown [this is done at the OS level]
+
+---
+
+## (uncategorized)
+
+- #482 [retry limit for failed authentication]
+- #1910 `/#hashtag` is not parsed as a hashtag (also `)#hashtag` and `_#test`) [because it could be a url fragment]
+- #3166 boost/fav counts out of sync (due to being async)
+- #3794 [someone is confused why replies are not fetched]
+- #3964 filter out private posts if you can't see the full context
+
+### (needs verification)
+
+- #2650 disabling a notification type will cause that notification to be missed; re-enabling the notification type does not bring back the missing notifications during that period in which it was disabled
+- #2777 browser notifications do not correctly handle mixed LTR + RTL
+- #2826 drag and drop images from othe browser tab
+- #2865 empty favourite notification
+- #3040 registering an app and getting a user token might return data of previous user token? calling `/api/v1/accounts/verify_credentials` returned wrong user [they seem to be using the password grant, possibly this is related to that?]
+- #3061 on post with multiple GIF attachments, going to next one will cause it to not animate
+- #3473 hard refresh needed to see multiple pages of new posts?
+- #3638 check if post is deleted when clicking reply button; if it is, then remove the post instead of allowing you to compose a reply
+- #3680 support 3gpp media upload for conversion [seems to have started working at some point? or maybe reproduced?]
+- #3703 if a mention cannot be processed, the whole job fails. maybe it shouldn't?
+- #3742 opening a timeline with videos in it can be slow
+- #3809 long-press to boost without confirmation (when confirmation modal is enabled for boosting)
+- #3930 wrong import order for SCSS [maybe closeable? idk, needs clarification as well, what triggers this scss and so on]
+- #3959 rake task `media:remove_remote` should not apply to posts that have been boosted locally
+- #3996 sidekiq deadlocks when `:concurrency` > 1
+- #4118 repeatedly faving/unfaving will generate a ton of notifications
+- #4236 Detect if desktop notifications are supported (hide settings for them if not)
+- #4434 nonbreaking spaces in config/locales are not preserved when rendering HTML [where is this relevant?]
+- #4573 some posts show up on profiles but not on home timeline [possibly related to #2614]
+- #4755 more gender neutral language in i18n german translation
+- #4809 browser notification for favourites does not show text of favourited post if an image is attached. but it does for mentions. so that should be consistent
+- #4838 settings routes / uris are inconsistent with the parts that they link to
+- #4887 Accept-Language header only supports en, not en-US
+- #5468 unicode directional formatting sometimes messes with url linking, causing broken links
+- #5476 importing following.csv sometimes leads to stuck follow requests for unlocked accounts (workaround: a manual unfollow/refollow fixes it)
+- #5527 2fa code should show keypad 0-9 on mobile devices
+- #5528 shortcode gets converted to emoji even without breaking whitespace
+- #5583 skin color emoji sequence not getting emojified
+- #5646 2-frame gifs do not respect delay on final frame
+- #5658 remote gif avatar gets corrupted on docker instances
+- #5707 wrong localization for zh-TW on relative short timestamp
+- #5960 status creation fails on id collision in transaction
+- #6070 discovering a post that wasn't federated can cause the counter to +1 mistakenly
+- #6083 a certain video got stuck on the first frame
+- #6113 favorite/boost counts take a while to update/refresh
+- #6139 old accounts deleted manually should be cleaned up [do we have this as a rake task or tootctl cleanup command?]
+- #6156 hide boosts from someone you follow, and you will not receive boost notifications from them
+- #6208 if the timeline is full of filtered posts, it doesn't load more
+- #6329 atom feeds have a CORS issue
+- #6338 zwsp is wrongly included in URL parser but correctly removed by hashtag parser
+- #6426 audit log breaks when statuses are deleted
+- #6432 custom emojis with long shortcodes can break the emoji list in /admin/custom_emojis
+- #6554 preview opengraph thumbnail for instance
+- #6681 [can't change email more than once?]
+- #6923 admin view of statuses doesn't show privacy scope [idk if this was ever fixed in a redesign]
+- #6938 welcome email has poorly styled username@domain handle
+- #6991 Net::LDAP simple method not supported
+- #7025 german translation of 2fa challenge is unclear
+- #7145 overscroll? [idk what this means]
+- #7170 allow resolving a report "with note" even when no note is included
+- #7174 bad ssl on websockets causes entire application to not render
+
+### (feature requests)
+
+- #34 backfill statuses on follow
+- #116 communal blocklists
+- #139 groups
+- #208 custom nicknames
+- #281 geotagging posts
+- #309 quote + boost
+- #512 stories [really more like twitter moments? or generic collections]
+- #861 local-only posting
+- #928 cryptographic verification of posts (specifically GPG signatures? it should be user-facing like github)
+- #979 timelines/columns for selected instances [bubble timeline?]
+ - #3812 custom timeline with user-defined domains (also apply filters to public timelines)
+ - #3917 let admins define additional timelines including certain domains
+- #983 custom audiences / arbitrary addressing (specifically, decide which servers to send your post to)
+ - #7135 mutuals-only posts
+- #1133 Drafts
+- #1162 Insert picture from URL [assuming this means download and reupload? although it would be more interesting to allow remote storage and simply embed it / use the remote url directly...]
+- #1208 post to category / topic [like google+ collections]
+- #1307 mods should be able to edit posts to add a cw
+- #1353 option to show replies in public timelines
+- #1405 Local account delegation [i.e. posting on behalf of another account? like tweetdeck team accounts?]
+- #1539 mark posts as read (then clear the column)
+- #1593 temporary block (expiring blocks just like expiring mutes)
+- #1608 show timestamp of when post was favourited (in favourites column and in API) [same for bookmarks?]
+- #1685 show status of filed reports or notify them when a report is actioned
+- #1800 browse or show posts within a certain date range
+- #2089 "Daily Digest" feature that shows only a selection or highlight of posts from certain users (instead of overloading your home timeline)
+ - #4451 Discovery / Catch-up timeline that shows posts you may have missed, or perhaps most boosted/faved, etc
+- #2317 keep track of media attachments and allow re-using them in new posts [like misskey drive?]
+- #3265 attach images to reports (in case users delete their statuses or set abusive avatars?)
+- #3546 language filters should use a dropdown instead of checkboxes? should also support more languages
+- #3664 Delete all your posts (or some subsets of your data) without deleting your entire account
+- #3890 users should be able to override silences [perhaps like disabling twitter's "quality filter"?]
+- #3945 mark undelivered mentions / provide feedback when posts are not delivered
+- #4106 Support emoji reacts (reactions) on posts [keywords: EmojiReact, EmojiReaction]
+- #4207 allow admins to set allowed languages in public timeline for logged-out users
+ - #5691 allow users to select their language on the landing page while logged out
+- #4983 [original issue was about making posts unboostable, but was misunderstood to be about filtering out notifications for when a certain post is boosted]
+- #5787 separate preference for "autoplay media" and "animate emoji"
+- #6094 embed profiles or timelines
+- #6122 tell the user when they are impacted by instance domain blocks
+- #6332 show which local users follow a remote user in the moderation UI
+- #6353 admin-configured limits on invites
+- #6379 saved searches
+- #6387 admin panel diagnostics page
+- #6403 option to not convert GIF to video
+- #6603 `media_only` on home timeline
+- #6635 domain mute without hiding notifications
+- #6912 downscale images on upload if they exceed the limit
+- #6942 follow local public timelines from other instances [conceptually should be handled by groups instead?]
+- #6958 tag avatar and/or header as sensitive/nsfw
+- #6982 add accounts to lists without following them [bad idea imo]
+- #7042 "View profile as" someone else
+- #7066 "Force-unlisted" option for moderating profiles
+- #7132 "Bunker mode" to make an account look deleted when it is really not [or possibly just hide the public profile?]
+- #7169 upload subtitles with videos
+
+#### (more niche)
+
+- #547 "secure evidence" when admins ban users (instead of wiping all data)
+- #4108 Notify me when someone I interact with changes their profile picture
+- #5239 Licensing and attribution for custom emoji
+- #5444 "emergency instructions" for when a user dies so they can tell admins what to do with their account
+- #5657 option to show acct above your display name instead of below it
+- #5675 choose the default tab for your profile
+- #5714 maybe your posts should be cached offline in the web app's local storage so that if your instance goes offline you have a backup
+- #5867 Support 360 panaroma photos
+- #6067 notify when a hashtag is used
+- #6084 user analytics
+- #6090 RSS feed for all interactions on a post?
+- #6350 choose the date format localization for timestamps
+- #6569 SVG avatar support
+- #6726 activity graph and/or calendar for browsing profiles' post history
+- #6920 write your own translation of other people's posts
+- #7014 add CSS classes based on hashtags, so admins can style certain tagged posts differently from others
+- #7082 admin-configured hints for avatar/header image policies
+- #7201 show which lists an account is in (from the timeline)
+
+### (meta)
+
+#### (clearly actionable)
+
+- #1404 OpenAPI documentation [but how to generate it?]
+- #1487 show out-of-date warning for old servers [how can you tell?]
+- #2222 require comments/reason on reports [worth mentioning we have categories now which seems partially relevant]
+- #2668 let users point DNS at existing instance, allow multi-tenancy with custom domains
+- #3618 reply filtering should hide posts starting with @mentions (even if it's first post in the thread) [basically mirroring twitter and the `.@reply` notation that was necessary in the past]
+- #3785 silenced users should be able to DM admins and mods
+- #4883 "embed" feature should support informed consent and opt-in to having your posts embedded
+- #5781 refetch avatars (and other media?) after remove instance domain block with "reject media" checked
+- #5797 prevent replying to someone without mentioning them
+- #5883 allow pagination from oldest to newest [or discover the oldest post id somehow]
+- #6136 API request limit should be higher -- 100 statuses?
+- #6412 external "share" service at share.joinmastodon.org that redirects to your existing instance
+- #6474 disable storage of IP addresses
+- #6812 rename "local" timeline to something that makes it clear it is not geographically local
+- #6828 separate "pinned posts" into separate tab on profiles
+ - #19657 combine pinned/featured {posts, hashtags, profiles} into one tab on profiles
+- #6884 media usage numbers should be publicly shown? [or possibly to logged-in users, i would assume?]
+- #6895 domain blocks with "reject media" should be explained clearly to users, because it looks like a bug currently
+- #6899 a way to obtain media attachment cdn links again
+- #6970 sensitive content toggle should be per-timeline instead of all-or-nothing. opting into sensitive content from followed users is not the same as opting into sensitive content from *everyone*
+- #6976 allow logging in with username instead of email
+- #7122 reason should be required on reports
+- #7127 notify users when they are affected by moderation actions or decisions
+- #10743 author and show hashtags outside of `content`
+ - #7250 [alternatively to above:] hide hashtags at the end of a post's `content` [though this can change meaning]
+- #7274 show "post unavailable" placeholders whenever a status exists but is not visible (due to privacy or being deleted)
+
+#### (vague or inactionable)
+
+- #967 unique visual identity for niche instances (better customization or theming)
+- #1049 better handling for unicode urls (punycode, idn, and so on) as well as schemes/protocols (steam: specifically?) and other encoding issues
+- #3782 alternative sorting and aggregation algorithms for timelines (for example, epochs weighted by log(likes) + followers boosting)
+- #3796 account aliases (particularly webfinger redirect?)
+- #3819 better DM system
+- #4870 new user experience
+- #5380 make financial supporters visible [manually? integration with patreon/etc?]
+- #5515 interest separation + account grouping [seems to be a split between "categories" and "unified timeline"?]
+- #5553 urls should not be assumed 23 characters
+- #5686 two stages of following -- unapproved and approved. send public posts to unapproved followers [could be handled with audiences instead?]
+- #5723 granular post privacy (control whether post goes to public timelines, is available unauthenticated, local-only, etc)
+- #5774 ability to change your instance domain (LOCAL_DOMAIN)
+- #6192 scss stylesheets should have more color variables
+- #6892 reserve usage of `#admin` tag for users who are actually admins [i don't think this is feasible, but if it were, you might want to have it be variable and admin-defined? but remote users exist, so...]
+- #6945 disable DMs on an instance level [this makes no sense as-is, unless you have a "public only" mode that rejects anything not addressed to public?]
+- #6957 default to not sending sensitive field when adding a status [idk what this means]
+- #6992 rich preview cards don't have enough options? [idk what this issue is really about]
+- #7114 admins/mods should be able to have a second email for moderation notifications
+- #7155 temporarily cache following/follower lists
+- #7164 `noindex` should apply to statuses even when boosted [but there's no way to apply it to only part of a page...]
+- #7254 some kind of opt-in or out of "bot interactions" [this needs to be more meaningful imo]
+
+---
+
+## Single-category issues
+
+### Admin UI
+
+- #146 admin ui for manually creating user accounts
+
+---
+
+### Backend
+
+- #701 assume http? for bare domains [link `example.com` to `http://example.com`]
+- #981 import posts (from csv, specifically?) [but could be from activitypub archive]
+- #1781 customizable character limit / status max length (instead of hardcoding 500)
+- #2478 allow setting multiple contact/representative accounts for your instance
+- #3139 keep track of which users and domains are being widely blocked by local users
+- #3811 automatically rake/prune inactive accounts and delete them
+- #4296 greylist federation. instances are silenced by default until approved by the admin.
+- #5972 Rename "always mark media as sensitive" to "Mark media as sensitive by default" [TODO: Low hanging fruit]
+- #6007 button to generate archive exports on behalf of the user, then email them with a link to that archive
+- #6031 Full-width japanese period gets included as part of path query in URLs (after the slash). this can break links
+- #6351 URL renderer / linkifier adds empty span.invisible to the end of many links
+- #6701 URL ending with period does not linkify the period, leading to a broken link
+- #6825 empty status with CW should not convert CW to status
+- #7056 automatically rake/prune old account headers
+
+#### specific to media
+
+- #5204 indicate the file size on failed uploads so that you can better tell why something went wrong
+- #5619 Suport Alibaba Object Storage as an alternative to S3
+- #5729 Replace Paperclip with Shrine
+- #6352 invalid PNG upload returns 500 Server Error instead of 400 Bad Request
+- #6377 hfr video (240fps) transcoded to normal video (60fps), maybe there should be an option
+
+#### specific to search
+
+- #6287 search for multiple hashtags
+
+#### specific to signups and new accounts
+
+- #877 captcha, honeypot, ip limit, and other antispam measures for registering new accounts
+- #951 max capacity for registered users (block registration when cap is reached)
+- #2045 autogenerate default avatars per-user (specifically foxes?)
+- #5647 add warning to registration form that username cannot be changed
+
+#### ActivityPub
+
+- #4640 activitypub property to signal when you opt out of search indexing (similar to robots.txt or robots meta tag in html)
+- #4964 use a versioned json-ld @context [currently mastodon just uses the unversioned activitystreams context, but i'm not entirely sure what issues this may cause if any and why]
+- #5500 human-readable errors on trying to post to activitypub inbox endpoint
+- #6262 converted statuses should append Hashtags to the end of the status_content maybe?
+- #6849 deletes are not retried after failure?
+- #6878 do not fetch only the first `attributedTo`
+
+#### REST API
+
+- #2048 support Android Intent URIs when registering a client app [currently failing due to use of `#` in uri; workaround is to register custom scheme in android?]
+- #5273 API response should include Relationship on each Notification, so that you can tell when a notification came from a follower/following/mutual [arguably you could embed the Relationship on the Account but that might be expensive]
+- #5492 API for a client app to update its own registered information (such as `redirect_uris`) using an app token generated from the stored `client_id`+`client_secret`
+- #6040 errors should have a non-localized string key to identify which specific error occurred (can be matched exactly)
+- #6360 get only ids of accounts from followers/following?
+- #6549 API to get ids of deleted statuses without streaming
+- #7020 PATCH update_credentials should be replaced with PATCH settings/profile for more intuitive way of updating profile settings like display name, avatar, header image, etc.
+- #7021 PUT api/v1/preferences to save new preferences, not just GET existing ones
+- #7108 get all admins/mods
+
+#### Streaming API
+
+- #3049 websocket streaming api sometimes encodes payload sometimes doesn't [unlikely to be fixed, due to being a breaking change]
+- #5971 add event for new PreviewCard?
+
+#### Security
+
+- #1149 automatically log you out, add checkbox to "stay logged in"
+- #1181 do not set a cookie on logged-out users
+
+#### Standards and spec compliance
+
+- #673 RSS feed for your notifications
+- #1384 support receiving Webmentions
+- #2234 Support Micropub for authoring posts (as an alternative to `POST /api/v1/statuses`)
+- #3165 Support Mastodon as an OAuth consumer (login by oauth to some other service / single sign-on / SSO?) ["Mastodon includes the omniauth gem ... it should be possible to support sign up through any OAuth service"]
+- #4569 OAuth authorization code OOB flow should allow using an easier-to-type PIN code instead of a 64 digit hex code. twitter and imgur do this apparently
+- #4800 Support Mastodon as an OpenID provider (OpenID Connect / OIDC? RFC 6749? IndieAuth is also mentioned)
+- #5227 Support Atom feeds [previously supported only profiles, but even that was removed in favor of RSS only]
+
+---
+
+### Deployment
+
+- #1068 offer a Snap/snapcraft package
+- #1118 support Terraform from Hashicorp (or chef, or ansible, or puppet, or salt caps)
+- #1328 Scalingo setup form should use human-friendly strings instead of plain AWS region names (e.g. `EU (Frankfurt)` instead of `eu-central-1`)
+- #1528 /tmp directory fills up over time
+- #3576 offer a Debian package
+
+---
+
+### Filters
+
+- #18955 Revamp filters to cover more use cases
+ - #6078 Filters ignore username
+ - #6596 filter yourself in home timeline
+
+---
+
+### Lists
+
+- #5938 backfill lists when adding new accounts to them
+- #5978 Muting a user does not remove old posts from lists
+
+---
+
+### Profiles
+
+- #609 hidden profiles [require auth? "bunker mode"?]
+- #1040 custom backgrounds
+- #2295 Forward chronological mode / sorting
+- #3205 disable or opt out of having a media tab
+- #4823 some languages like persian use different words for countable form and plural form, but only one string is used for both the count and for the "all posts" tab on profiles.
+
+---
+
+### Web app
+
+- #380 multiple account management / account switcher (for tootdeck layout / advanced ui, this implies supporting columns per-account)
+- #873 font size for larger text
+- #1471 show account preview on hover
+- #1955 hash acct/url and pick a distinct color to allow more easily identifying when an account is different or is a homograph and possibly impersonation
+- #4647 when you hide media that isn't marked nsfw, it should stay hidden persistently (currently it is reshown on refresh)
+- #6028 poor contrast on the CW and privacy toggles in the compose form
+- #6034 clarify the difference between "desktop notifications" and "push notifications" toggles
+- #6035 notification settings are messy and poorly laid out
+- #6210 show when a boost was made, not just the original post timestamp
+- #6407 show when there are unresolved reports
+- #7860 show confirmation dialog before more things
+ - #3702 show confirmation dialog before posting
+
+#### specific to advanced UI
+
+- #2054 switching to advanced web UI should load "getting started" instead of a duplicate home/notifications/compose column [this seems to be done only sometimes?]
+- #3771 customize the tab bar in the upper-left corner of advanced ui on desktop layout (currently hardcoded to getting started / local / federated / settings / log out)
+- #4305 allow moving context column instead of having it on the far right
+- #6440 Pin multiple columns of the same type
+- #7017 columns should be drag-and-drop instead of rearranged by left/right buttons
+- #7050 add workspaces to advanced ui, choose sets of columns to be visible together
+
+#### specific to authoring a post
+
+- #1174 empty CW in compose form should prompt for CW or use default text "content warning", instead of silently dropping the cw and posting a normal post
+- #1765 allow replying inline within a column (like tweetdeck or twitter)
+- #1860 Preview your post
+ - #4848 specifically, it is unclear which characters will be included / parsed as a hashtag or mention or URL
+- #2365 copy hashtags on reply
+- #3567 mention the booster when replying to a boost
+- #3903 suggest a CW based on keywords in your post
+- #5108 add a secondary publish button with a different scope (port from glitch-soc)
+
+#### specific to emoji
+
+- #717 option to use system emoji instead of EmojiOne
+- #5592 option to not show emoji
+
+##### specific to authoring emoji
+
+- #1908 disambiguate emoji for country flags (maybe sort flags by continent region or geography?) [nightpool: "this is an upstream issue w/ emoji-data"]
+- #5445 prevent suggesting emoji when typing emoticons (for example, typing `:-)` should not suggest `:slightly_smiling_face:` in emoji-mart)
+- #5498 emoji shortcodes should inherit preferred skin color from emoji-mart
+- #5808 shortcodes should always be converted to emoji, or perhaps only when selected manually
+
+#### specific to media
+
+- #921 `rich` OEmbed (e.g. for soundcloud)
+- #1255 allow wider aspect ratios instead of zoom-cropping thumbnail [auto height instead of `object-fit: cover`?]
+- #2034 when a modal is open, pause all animations in the background
+- #6254 "reduce motion" should disable side-scrolling animation for preview of multiple images
+- #6983 better handling of PeerTube embed/preview
+- #7031 embed remote videos
+
+##### specific to authoring media
+
+- #3860 basic image editing (cropping, rotating, etc) in the web app before posting
+- #6879 focal point is misleading. circled area is not in the center, nor is it fully inside the thumbnail crop. [possibly calculation or rendering of focal point may be bugged?]
+
+#### specific to notifications
+
+- #1483 group similar notifications (consecutive notifications of same type should be collapsed)
+- #1868 collapse boost/fav notifications to one line only (and `text-overflow: ellipsis` for the rest) [TODO: low hanging fruit for trwnh/mastomods? or is the current "max height" mod good enough for this?]
+
+#### specific to onboarding
+
+- #2019 relaunch the onboarding tutorial at any time
+- #3264 show instance info in onboarding tutorial (so that users are aware of rules/etc)
+- #6867 choose your language filters after signup
+
+#### nonspecific
+
+##### accessibility
+
+- #1680 line height should be relative to font size, not absolute [TODO: low hanging fruit?]
+- #3660 better contrast and visibility on button for closing image modals
+- #3875 "edit profile" link should be easier to tap on mobile [TODO: low hanging fruit]
+- #4508 better focus contrast / visibility for status action buttons [currently, there is a slight transparent background on focus but no prominent outline like other focused elements] [TODO: low hanging fruit] [side note: the video player has even worse contrast on focus, i legit could not tell it was focused]
+- #4510 when you focus on a post and expand it, the focus should shift to the detailed status view instead of staying in the column
+- #6152 larger click/touch target for adding account to list
+- #6185 error toast notifications should show up closer to the source of the error, not in the lower left corner
+
+##### performance
+
+- #787 garbage collection for open webUI tabs (react redux / state management)
+- #1379 switching columns on mobile should be optimized
+- #1469 use SVG icons instead of web fonts
+- #5504 components are re-rendered whenever redux state changes, due to `mapStateToProps`
+- #6438 memory usage continues to grow as new items are loaded into timelines
+
+##### architecture
+
+- #4478 reload a single column or conversation without reloading the whole tab
+- #7113 minimize the compose box on mobile
+
+##### bugs
+
+- #5160 fullscreen video on desktop safari doesn't work right [seemingly last reproduced in june 2022 on macos 12.4 + safari 15.5]
+
+##### unimplemented API features
+
+- #1900 clear one notification [i.e. implement `/api/v1/notifications/:id/dismiss`]
+- #6702 role badges
+
+##### staying in-app
+
+- #739 edit profile in webUI instead of settings page
+- #946 "back" button in header should not take you out of the web app (you should remain in-app)
+- #1399 links to activitypub objects (posts/profiles) should stay in-app [i think this specifically calls out links in profile bios? that might be harder]
+ - #2136 links in posts (to other posts) should open those posts in-app
+ - #3185 links in bios (to other profiles) should open those profiles in-app
+ - #3982 links in bios (to hashtags) should open those hashtags in-app
+- #3201 indicate that a language filter is active and allow temporarily activating language filters in-app (without going to settings)
+
+##### meta
+
+- #1249 use an icon for CW instead of literally `CW`
+- #1850 Rename "Getting started" to something else (OP suggested "Home" but gargron instead suggests "menu" or "main menu")
+- #1856 UI mockups for easier switching of columns?
+- #2210 UI mockup for pre-rendering mentions as links, instead of showing the entire address in the compose box
+- #3872 combine Getting Started + Compose into one column, since they're both always open?
+- #4399 CW toggle and sensitive media toggle should be linked such that expanding a post expands the media with it, and collapsing a post should rehide the media
+ - #4689 CW and sensitive media should not be linked at all
+ - #6141 show a media indicator in the CW "show more" toggle
+- #5727 UI mockup for two-column layout on tablets
+- #5736 more layout adjustments. variable column width, variable font size, variable media thumbnail size
+- #5958 quickly switch between lists in a pinned column, or allow pinning the main "Lists" list
+- #6267 use typescript
+
+---
+
+
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/openweb.md b/wiki.hugo/content/tech/openweb.md
new file mode 100644
index 0000000..6d26f66
--- /dev/null
+++ b/wiki.hugo/content/tech/openweb.md
@@ -0,0 +1,26 @@
++++
+updated = "2020"
++++
+# Open Web
+
+The open web is built on multiple technologies recommended by the W3C. This page is dedicated to taking notes about protocols and standards, and basic details of their implementation.
+
+{{}}
+
+## Static content
+
+Technologies that can be included in static HTML files, no backend server needed. Static site generators can generate these if the template supports them.
+
+### Microformats
+
+Microformats are used to define the Semantic Web, which aims to make machine-readable meta-content. http://microformats.org
+
+## Dynamic content
+
+### IndieWeb
+
+The goal of the IndieWeb project is to allow websites to be used as full-fledged substitutes for other services. The ideal indiewebsite would be able to self-host media content in multiple post types, serve as an authentication for logging into other services, and be used as a person's identity. Indieweb strategies include using your domain name as your identity, self-hosting your own data on that domain, syndicating copies of your content to silo services, and maintaining actually permanent permalinks. http://indieweb.org
+
+### ActivityPub
+
+ActivityPub is a federated social networking protocol that defines server-to-server and client-to-server interactions via ActivityStreams 2.0 and the Activity Vocab. It's basically email over JSON. Actors act on Objects that are sent and delivered via an Inbox and Outbox in various Collections. https://www.w3.org/TR/activitypub/
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/social.md b/wiki.hugo/content/tech/social.md
new file mode 100644
index 0000000..4bcf80d
--- /dev/null
+++ b/wiki.hugo/content/tech/social.md
@@ -0,0 +1,57 @@
++++
+updated = "2021"
++++
+## foundational concepts
+- regular grammars, subject-verb-object, and the actor system
+- addressing and identity
+- centralization, authority, and the open-world system
+- fetching vs delivery, and dealing with state
+- authentication and authorization
+
+## real life and prior art
+- physical building/mailing addresses and email
+- phone numbers and sms
+- the many im apps, attempted unification, and current fragmentation
+- spec talk: smtp, irc, xmpp, activitypub, matrix, proprietary ReST APIs, and so on
+
+## introduction to activitypub
+- activitystreams vocabulary
+- web uri
+- as2 serialization and json-ld
+- inbox and outbox GET and POST
+- cryptography, signatures, tokens for validation and access control
+
+## let's design a social network
+- what's wrong with what we have now?
+- what we can do better
+- types of communication: 1-1 (chat or publish), closed/open group (room or wall)
+
+## my ideas
+- mapping resources by uri, not just by https url, but also possibly by a urn resolving service?
+- publish only what the user consents to. assume everything is private by default. including uris, in some cases.
+- contact manager to map addresses to *people*. keep track of not only who has which address, but also *when* they had the address (in case the address changes!)
+ - id assignment should be on its own namespace and you should leave human-readable stuff for the url. url should resolve to id.
+- Join a Group (for arbitrary delivery ingroup or serverside validation) vs Follow a Group (for its public postings, both Announce from group members but also directly authored by the Group actor itself)
+ - Follow a Service that will send you messages like a mailing list?
+ - maybe delivery-by-default isn't the best model for everything? maybe all you really need is cross-domain auth?
+ - n-way delivery is a nightmare anyway. better to deliver to Service then it redistributes to all participants (can use "context" to model rooms). this works like irc but with federated id and richer as2 vocab
+- open registrations are a mistake. you are responsible for everyone that you provide service to, and every page published on your website
+- Accept or Reject more things. let em know when side effects were processed. or use a signed Accept token during validation. or simply have both actors sign off on it.
+
+### other ideas
+
+- no-cost push messages = spam. being able to send you stuff is not something to be taken lightly. generally on the web, you pull stuff you're interested in (sub) that other people have made available (pub). assuming that everyone should be able to push stuff into your inbox is not a good idea. ultimate control for what you receive should be given to you, the recipient -- you should be able to refuse delivery of anything you don't want. with that said... push should be a permission or *capability* that you can grant to others, if you *trust* them.
+
+- related to push, is the ceding of the replies/comments section as out of your ultimate control. twitter for example fucked up when they made @ mentions deliver directly to someone. imo it would have been better to only see @mentions when you explicitly go searching for them (like hashtags).
+
+- another thing twitter did: full-text search. oh god it sucks so much when harassment mobs search for a specific term and then descend on anyone who uses it. rethink the boundaries of what should be considered "public" or "searchable".
+
+- assuming public by default. no. let the user determine what they want to *opt in* to publishing, not what they want to *opt out* of having visible. by default, nothing should be known about the user.
+
+> Copying and pasting made people look at what they shared, and think about it, at least for a moment. When the retweet button debuted, that friction diminished. Impulse superseded the at-least-minimal degree of thoughtfulness once baked into sharing. Before the retweet, Twitter was largely a convivial place. After, all hell broke loose — and spread.
+
+--[The Man Who Built The Retweet: “We Handed A Loaded Weapon To 4-Year-Olds”](https://www.buzzfeednews.com/article/alexkantrowitz/how-the-retweet-ruined-the-internet)
+
+> [S]ocial media has been overtaken by metrics, which are driven in large part by the vicious cycle of advertisers wanting to know which influencers are worth paying; and by toxic fan battles to make your favorite social media accounts gain followers and likes, and to downrank your favorites' rivals.
+
+--[Demetrification: improving social media by removing public like/follower/repost counts](https://boingboing.net/2019/09/12/flickrs-glory-days.html)
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/speakers.md b/wiki.hugo/content/tech/speakers.md
new file mode 100644
index 0000000..e9baeed
--- /dev/null
+++ b/wiki.hugo/content/tech/speakers.md
@@ -0,0 +1,68 @@
++++
+updated = "2024-09-22"
++++
+
+idk if "tech" is the right place to put this but
+
+i was researching affordable-ish upgrades to my current desktop speakers (edifier r1280t which aren't amazing by any stretch but they were decent when i got them)
+
+hard requirement max 6 inches wide. preferably lower, closer to 5.5" or so, this would allow me to lower my pc display height a tiny bit when i place them sideways
+
+## frontrunners
+
+- neumi silk 4 ($150/pair) (5.5" wide) https://amzn.to/4e9iCaE
+- micca rb42 ($149/pair) (4.9" wide) https://amzn.to/3TDztdI
+- nht superzero 2.1 ($125/single so $250/pair?) (also 5.5" wide) https://amzn.to/3zx679R
+
+ has good compiled objective data and comparisons sourced from high quality sources (audiosciencereview and erin's audio corner, mainly)
+
+neumi silk 4 vs micca rb42: https://www.spinorama.org/compare.html?speaker0=Neumi+Silk+4&origin0=ErinsAudioCorner&version0=eac&measurement=CEA2034&speaker1=Micca+RB42&origin1=ASR&version1=asr
+
+neumi silk 4 vs nht superzero 2.1: https://www.spinorama.org/compare.html?speaker0=Neumi+Silk+4&origin0=ErinsAudioCorner&version0=eac&measurement=CEA2034&speaker1=NHT+Super+Zero+2.1&origin1=ASR&version1=asr
+
+neumi silk 4:
+
+- pretty flat, 2.8db deviation
+- (+) 4.7 tonality on a scale from -10 to +10
+ - can be EQ'd to 5.87, add a subwoofer to get 7.39, sub+EQ = 8.28
+- (~) "neutral" response, less "flavorful" or "fun"
+- (-) response drops pretty sharply after about 14k -- can get as low as -6db at 20k
+
+micca rb42:
+- (~) "fun" due to more bass even if it is less clear than neumi silk 4 it generally extends further
+- 4.49 tonality on a scale from -10 to +10
+ - can be eq'd to 6.77 or add a sub for 6.49, or both for 8.63
+ - (+) eq'd it gets better than the neumi silk 4 by almost a whole point
+- also 2.8db deviation but not as flat or neutral throughout
+ - (+) but it also doesn't have the rolloff on the high end?
+ - (-~) somewhat scooped mids but it's like 2db or less once eq'd so not very apparent
+ - sharp highs and bright, will also distort if you go too loud
+
+nht superzero 2.1:
+
+- 3.4db deviation
+ - (+) less flat on average but seems to stay closer to within +-3db once you extend past 5khz
+- 3.37 tonality, 5.0 eq, 6.7 sub, 8.1 eq+sub
+- (-) price. $250/pair compared to neumi silk 4 $150/pair
+
+## other considerations
+
+- micca mb42x g2 has been described as "warm and rich" vs the original mb42x which was "bright and lean". anyway it's 5.8" wide and $100/pair. no data. https://amzn.to/3TykDor
+- kanto yu passive 4" -- $180/pair and about 5.5" wide. https://amzn.to/47yAw4h
+ - 2.9db deviation, 3.37 tonality (5.58 eq, 6.29 sub, 8.2 eq+sub)
+ - wide dip at ~500hz, doesn't look pretty... even when eq'd it has a dip at 4k
+ - in general seems to have boosted mids but that can be eq'd out for something kinda "clear and neutral"
+- psb alpha p3 -- $249/pair, 5.125" wide https://amzn.to/4eaLW0E
+ - supposedly better options for the price. could be good speakers but bad value
+ - (~) somewhat "dark" due to wide scoop in mids between 3.7k and 7.7k?
+ - (-) also SHARP dropoff after 16.5k (like -18db at 20k even when eq'd)
+ - 4.2db deviation, 3.29 tonality, 5.81 sub, 5.34 eq, 7.71 sub+eq
+ - really does seem like other speakers are better in same price range but idk it might have better response if you're into that sort of thing ("dark")
+- dali spektor 1 -- https://amzn.to/3Bi5ba4 $350/pair idk the exact size but it seems to be not worth the price. even eq'd it dips around 4k and can't stay within +-3db very well. big treble boost when not eq'd (like +4.5db)
+- dayton audio b40 -- https://amzn.to/4ewMv4B $50/pair, 5.5" wide, seems like a bargain if it's good but no data available to suggest it actually *is* good. no reviews on amazon, just a reddit post https://www.reddit.com/r/BudgetAudiophile/comments/1e5wjfl/a_quickish_review_of_the_dayton_b40s/ which describes them as "they definitely sound like $50, but like a really good $50". idk, skip.
+- audioengine p4 https://amzn.to/4eQFlZh $249/pair 5.5" wide. random commenters describe it as dull and muddy, others say it's not that bad, the only thing that really stands out to me is that the proper reviews seem to be from 2009/2010 so it's very possible that better stuff has come out since.
+- edifier p17 https://amzn.to/4eccDBV $140/pair 5" wide. no data.
+
+## conclusion
+
+idk i think it comes down to neumi silk 4 or micca rb42. rb42 seems like it could be better with eq+sub, and probably the "fun" sound would possibly be more enjoyable than the "flat"/"neutral" of the silk 4, but the neumi also doesn't distort like the micca. so even with that high-end rolloff i'm still leaning neumi.
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/spec/_index.md b/wiki.hugo/content/tech/spec/_index.md
new file mode 100644
index 0000000..f7ba421
--- /dev/null
+++ b/wiki.hugo/content/tech/spec/_index.md
@@ -0,0 +1,2 @@
++++
++++
\ No newline at end of file
diff --git a/wiki.hugo/content/tech/spec/activitypub/Activity.md b/wiki.hugo/content/tech/spec/activitypub/Activity.md
new file mode 100644
index 0000000..1e8aa4c
--- /dev/null
+++ b/wiki.hugo/content/tech/spec/activitypub/Activity.md
@@ -0,0 +1,420 @@
+# Activity
+
+an Activity is just an object that has an `actor`. it represents an action that was performed.
+
+{{}}
+
+## activities in activitypub
+
+activities are meant to be POSTed to the outbox in C2S (by the Client), then if the Server is also a Federated Server, they get delivered to recipients' inboxes via POST to inbox (by the Federated Server)
+
+for C2S: if it has `actor` then do not wrap it in a Create when it gets POSTed to outbox. otherwise, per [[AP § 6.2.1 "Object creation without a Create Activity"](https://www.w3.org/TR/activitypub/#object-without-create)]:
+- make a new `Create` to wrap the object in `object`
+- copy over `to`/`cc`/`bto`/`bcc`/`audience` from the object to the activity.
+- [not explicitly stated:] set `actor` on the activity equal to the current authorized user, then copy that over to `object.attributedTo`
+- generate an `id` for both the `Create` and the `object`, unless it is transient [[how do we determine this? perhaps a client explicitly specifies `id=null`?]]
+- return the `id` of the activity via the `Location` header
+
+for S2S: check `to`/`cc`/`bto`/`bcc`/`audience` on the activity. dereference any collections with a recursion limit (possibly n=1). add all discovered inboxes to a list. remove `bto`/`bcc`. POST to the list of discovered inboxes.
+
+some activity types have side-effects defined in the activitypub spec, sections 6 (c2S) and 7 (s2s)
+
+### (any Activity)
+
+if it has `actor` then do not wrap it in a Create when it gets POSTed to outbox
+
+- C2S: MUST assign `id` to the activity, ignoring anything that might be set by the Client, unless it is transient [[how to determine this?]]
+- C2S: add it to the current actor's outbox [[if not transient?]]
+- C2S: Return HTTP `201 Created`, `Location: `
+- S2S: warning, if it's an extension activity type then its side effects may not be understood. there may be fallback strategies to display `name`/`summary`/`content`
+
+### Create
+
+### Update
+
+### Delete
+
+### Add
+
+### Remove
+
+### Follow
+
+### Like
+
+### Block (C2S only)
+
+### Announce (S2S only)
+
+### Accept (S2S only)
+
+### Reject (S2S only)
+
+### Undo
+
+## activities in the fediverse
+
+in practice and in actuality, the "fediverse" largely does not conform to any of the 3 activitypub profiles. because c2s is not used, there are basically no Clients or Servers. and even on the s2s side, the side effects described by activitypub are not applied in any meaningful way. the *real* side effects vary per project. it can be argued that the fediverse is actually not built on activitypub, but rather, it is built on activitystreams 2.0 + linked data notifications. (it is a little-known fact that the `inbox` property in activitypub is actually `ldp:inbox` as defined by the linked data platform.)
+
+### mastodon
+
+supported activity types
+
+- Accept (accept a follow request)
+- Add (adds hashtag or status to featured collection)
+- Announce (reblog a status)
+- Block (block an account)
+- Create (create a message or status)
+- Delete (delete account or status)
+- Flag (report accounts and/or statuses)
+- Follow (request to follow a local account)
+- Like (favourite a status)
+- Move (migrate an account's followers)
+- Reject (reject follow request or remove follower)
+- Remove (removes hashtag or status from featured collection)
+- Undo (undoes some activities if possible)
+- Update (update account info or edit a status)
+
+#### extended logic
+
+- **Accept**
+ - **Accept Follow** -- authorize a follow request
+ - (when relay is findable by `object` as follow_activity_id)
+ - (when `object` is uri of existing follow request)
+ - (when `object` is embedded Follow)
+ - **Accept Follow ``**
+- **Add**
+ - (must have `target`)
+ - (`target` must be a `toot:featured` collection)
+ - (`object` must be inlined?)
+ - **Add Hashtag to `target`** -- feature a hashtag
+ - (takes `object.name` and removes prefix `#`)
+ - (creates FeaturedTag entity for the `actor`'s account)
+ - **Add `object` to `target`** -- pin a status
+ - (`object` must be transformable to status)
+ - (status must be authored by `actor`)
+ - (status must not already be pinned)
+- **Announce**
+ - (must be related to local activity)
+ - (i.e. `actor` followed by local accounts)
+ - (or requested through relay)
+ - (or `object` refers to a status whose account is local)
+ - (`object` resolves to a status)
+ - **Announce `object`** -- creates a reblog of a status
+ - (stop if:)
+ - (no status)
+ - (status not boostable)
+ - (requested through relay)
+ - (find existing reblog or create)
+- **Block**
+ - (`object` resolves to an account)
+ - (the resolved account exists and is local)
+ - **Block `object`** -- block an account
+ - (unfollow the `object`)
+ - (force `object` to unfollow you)
+ - (reject any follow requests from `object`)
+ - (create a block asynchronously)
+- **Create**
+ - (dereference the `object`)
+ - **Create EncryptedMessage** -- creates an encrypted message
+ - (tries to find a device id)
+ - (extracts `messageType`, `cipherText`, `digest`, `messageFranking`)
+ - **Create `object`** -- creates a status
+ - (rejected if)
+ - (unsupported object type)
+ - (`object` is a string)
+ - (not in supported types)
+ - Note
+ - Question
+ - (not in converted types)
+ - Image
+ - Audio
+ - Video
+ - Article
+ - Page
+ - Event
+ - (or invalid origin)
+ - (or tombstone exists for `object` uri)
+ - (or not related to local activity)
+- **Delete**
+ - (if `actor` matches `object`)
+ - **Delete `object`** -- delete your own account
+ - **Delete `object`** -- delete a status
+ - (create tombstone unless origin is invalid)
+ - (forward deletion if forwardable)
+ - (remove status from database and timelines)
+- **Flag**
+ - (`object` array is resolved as accounts and statuses)
+ - (then filtered for local)
+ - **Flag `object`** -- report an account and/or statuses
+ - (foreach account get reported statuses)
+ - (create a report against the account w/ optional status ids and content)
+- **Follow**
+ - (`object` must be a local account that exists)
+ - **Follow `object`** -- request to follow a local account
+ - (create or update follow request)
+ - (auto-reject if:)
+ - (`object` is blocking `actor`)
+ - (`object` is domain-blocking `actor`'s domain)
+ - (`object` has moved/redirected)
+ - (`object` is the instance actor)
+ - (send an Accept Follow if a follow already exists)
+ - (otherwise create a follow request)
+ - (if you are silenced or they are locked, send frq notification)
+ - (otherwise send Accept Follow and follow notification)
+- **Like**
+ - (resolve status from `object`)
+ - **Like `object`** -- favourite a status
+ - (stop if:)
+ - (no status resolved)
+ - (status is not from a local account)
+ - (delete arrived first)
+ - (you already favourited this status)
+ - (create a favourite by `actor` for `object`)
+- **Move**
+ - (`actor` must match `object` and resolve to account)
+ - (resolve `target` as account)
+ - **Move `object` to `target`** -- migrate your followers
+ - (stop if:)
+ - (no `target`)
+ - (`target` is suspended)
+ - (`target.alsoKnownAs` doesn't include `object`)
+ - (set a redirect)
+ - (async move followers from `object` to `target`)
+- **Reject**
+ - **Reject Follow** -- reject a follow request or remove follower
+ - (when relay is findable by `object` as follow_activity_id)
+ - (when `object` is uri of existing follow request)
+ - (when `object` is uri of existing follow)
+ - (call UnfollowService for `actor`)
+ - (when `object` is embedded Follow)
+ - **Reject Follow `Follow.object`**
+- **Remove**
+ - (must have `target`)
+ - (`target` must be a `toot:featured` collection)
+ - (`object` must be inlined?)
+ - **Remove Hashtag from `target`** -- unfeature a hashtag
+ - (takes `object.name` and removes prefix `#`)
+ - (deletes FeaturedTag entity for the `actor`'s account)
+ - **Remove `object` from `target`** -- unpin a status
+ - (`object` must be transformable to status)
+ - (status must be authored by `actor`)
+ - (destroy pin if existing pin found)
+- **Undo**
+ - (`object` should be inlined or else it may not be handled)
+ - **Undo Announce** -- unreblog a status
+ - (stop if no `Announce.id`)
+ - (resolve `Announce.id` as status reblog)
+ - (call RemoveStatusService on status)
+ - **Undo Accept** -- unfollow an account [yes this is the assumption]
+ - (find follow by `object.object.id` and revoke it)
+ - **Undo Follow**
+ - (resolve `object.object` as account)
+ - (stop if not exists or not local)
+ - **Undo Follow ``** -- unfollow an account
+ - (`Undo.actor` unfollows `Follow.object` if following)
+ - **Undo Like**
+ - (resolve `object.object` as status)
+ - (stop if no status or if status is not local)
+ - **Undo Like ``** -- unfavourite a status
+ - (if `actor` has favourited the status:)
+ - (find a favourite on that status by that account)
+ - (destroy it)
+ - **Undo Block**
+ - (resolve `object.object` as account)
+ - (stop if not exists or not local)
+ - **Undo Block ``** --unblock an account
+ - (call UnblockService if `actor` is blocking `Block.object`)
+ - **Undo `object`**
+ - (try_undo_announce)
+ - (find reblogged status by `object` uri and `actor`)
+ - (if found, remove reblog and stop, else continue)
+ - (try_undo_accept)
+ - (do nothing, continue) [because Accept uri is not stored]
+ - (try_undo_follow)
+ - (find `actor` follow request/relation by `object` uri)
+ - (if found, destroy it and stop, else continue)
+ - (try_undo_like)
+ - (do nothing, continue) ["too costly", no index by Like uri]
+ - (try_undo_block)
+ - (find `actor` block by `object` uri)
+ - (if found, call UnblockService and stop, else continue)
+- **Update**
+ - (dereference `object`)
+ - (if `object.type` in `Application Group Organization Person Service`)
+ - **Update `object`** -- update an account's info
+ - (stop if `actor.id` does not match `object.id`)
+ - (call ProcessAccountService)
+ - (else if `object.type` in `Note Question`)
+ - **Update `object`** -- edit a status
+ - (stop if invalid origin)
+ - (resolve `object` as status)
+ - (stop if no status)
+ - (call ProcessStatusUpdateService)
+
+### pixelfed
+
+
+
+(seems to require inlining in a lot of places? not 100% sure but that's what it looks like to me)
+
+- Add
+ - (must be inlined?)
+ - Add Story (not final)
+- Create
+ - (requires `to` for some reason, so `cc` only will break)
+ - Create Question
+ - (a single `to` item will create a DM if no `cc`)
+ - Create Note.inReplyTo
+ - Create Note.attachment
+- Follow
+ - Follow `object`
+- Announce
+ - Announce `object`
+- Accept
+ - Accept Follow (anything else will return immediately)
+- Delete
+ - Delete `object` (if `object` == `actor` and is valid string uri)
+ - Delete [Person, Tombstone, Story] (???)
+ - Delete Person
+ - Delete Tombstone (???)
+ - Delete Story (not final)
+- Like
+ - Like `object`
+- Reject
+ - (does nothing)
+- Undo
+ - (must be inlined)
+ - Undo Accept
+ - (does nothing)
+ - Undo Announce
+ - Undo Block
+ - (does nothing)
+ - Undo Follow
+ - Undo Like
+- View
+ - View Story (not final)
+ - (also seems to get story id by whatever is after the last slash?)
+- Story:Reaction (not final; undocumented extension)
+ - (`id` and `actor` must be valid urls)
+ - (`inReplyTo` and `to` must be local)
+ - (`object` must not resolve to Status)
+ - (seems to get story id by whatever is after the last slash?)
+- Story:Reply (not final; undocumented extension)
+ - (`id` and `actor` must be valid urls)
+ - (`inReplyTo` and `to` must be local)
+ - (`object` must not resolve to Status)
+ - (seems to get story id by whatever is after the last slash?)
+- Update (commented out)
+
+### misskey
+
+
+
+- Create
+- Delete
+- Update
+- Read
+- Undo
+- Follow
+- Accept
+- Reject
+- Add
+- Remove
+- Like | EmojiReaction | EmojiReact
+- Announce
+- Block
+- Flag
+
+
+
+### pleroma
+
+ObjectValidator
+
+validate()
+
+- Block
+- Undo
+- Delete
+- Create ChatMessage
+- Create [Question Answer Audio Video Event Article Note Page]
+- [Event Question Audio Video Article Note Page]
+ - Event
+ - Question
+ - Audio
+ - Video
+ - Article
+ - Note
+ - Page
+- Update [Question Answer Audio Video Event Article Note Page]
+- [Accept Reject Follow Update Like EmojiReact Announce]
+ - Accept
+ - Reject
+ - Follow
+ - Update
+ - Like
+ - EmojiReact
+ - Announce
+ - ChatMessage
+ - Answer
+- [Add Remove]
+
+SideEffects
+
+handle()
+
+- Accept
+ - Accept Follow
+- Reject
+ - Reject Follow
+- Follow
+- Block
+- Update
+ - Update `object`
+ - Update `object