1
0
Fork 0

Compare commits

...
Sign in to create a new pull request.

116 commits

Author SHA1 Message Date
m
ec435e6df2
Make carousel things longer to show some image without clicking 2025-11-19 10:53:47 -08:00
m
5137f84e92
Add canonical http://devhack.net
we 301 redirect for CDN reasons but the canonical devhack stuff is still
very much devhack.net
2025-10-29 15:58:38 -07:00
m
7d9645efe8
Add head element lmao 2025-10-29 15:58:38 -07:00
4e864f5985 Update lore/error.html 2025-10-09 20:32:41 -04:00
342b425a65 Update lore/error.html 2025-10-09 20:28:55 -04:00
64e98cf339 404 stylization 2025-10-08 23:46:44 -04:00
m
3f01e59753
Update some clarifications 2025-09-13 14:09:25 -07:00
m
00f4085617
re-add calendar 2025-09-12 15:19:26 -07:00
054eedc60a Update index.html
get faggy
2025-09-11 20:59:23 -04:00
m
b6b3f8ef41
Update docs 2025-09-04 09:36:42 -07:00
m
fd3ecac5b5
Add the markdown docs I guess 2025-09-03 09:16:35 -07:00
m
ad191421fe
Some rewording 2025-09-03 08:44:00 -07:00
m
3093a536c4
Add schism docs 2025-09-02 21:47:03 -07:00
m
690ea1a860
Imbue the vibes a lil bit more 2025-08-31 11:32:44 -07:00
m
62f3cbdc31
Pause events 2025-08-31 11:32:44 -07:00
3b98f7bfec Add missing body max-width
Prevent text from stretching too wide on large screens by adding a
missing max-width to the body element in style.css with the value of the
existing @media query.

Without this, calendar descriptions that are too long will stretch
the width of the body to an uncomfortably wide size.
2025-08-27 19:28:09 -04:00
6d23b83db0 unify what the http fetch errors look like 2025-08-24 14:17:54 -07:00
391f723732 No need to explicitly say spacepai borked w/ error-template 2025-08-24 14:12:22 -07:00
f4cecbf3bf Make the error margin more generous on mobile 2025-08-24 14:10:14 -07:00
0ec42def01 Get everybody to use the error-template 2025-08-23 15:30:50 -07:00
7c97825b5d Add healthcheck warning 2025-08-23 15:30:50 -07:00
a0b849dc1e add atom link for news feed
this replaces rss
2025-08-22 19:03:23 -04:00
ebb3f0d599 Do not expose (edited) in news feed
imo fixing a typo isn't important enough to show

if anything we should probably maintain a "last edited" by field to
be displayed internally, if we wanted accountability vibes.

fyi @diamond
2025-08-22 16:07:00 -04:00
c21754a914 Make contact visusl spacing more like the calendar's 2025-08-13 20:42:55 -07:00
m
fef6728efb
disable word wrapping on do-ocracy 2025-08-13 13:52:43 -07:00
650dfe4a07 fix <pre> and <br> mixing 2025-08-13 12:56:30 -07:00
af2cbea31f Fix newsfeed timestamps not working correctly across time boundaries 2025-08-13 10:58:58 -07:00
457844e4c2 Combine telephone numbers 2025-08-13 10:45:02 -07:00
905b62631e Change postal address linking style to align with chats 2025-08-13 10:40:06 -07:00
m
609233af73
Add mailing address for any potential postcards 2025-08-12 15:16:50 -05:00
m
7febb7eaf5
Replace contact <ul> with a <dl> 2025-08-12 15:16:50 -05:00
ea0e461854 Use thumbnail_url_small whenever possible in newsfeed 2025-07-20 01:46:38 -04:00
e8edc52532
Add "add" link in what's new heading 2025-07-07 21:01:15 -07:00
2c6f65abfb
Fix news feed datetime, add editedAt time 2025-07-07 20:59:40 -07:00
c8be03dd5c add canonical url tags 2025-07-05 12:47:43 -07:00
8462bde2bf make acknowledgements less tacky 2025-06-26 17:37:04 -07:00
785291f478 Chill out on the footer 2025-06-23 18:06:08 -07:00
6d4c71f8b9 Write a little README 2025-06-09 12:15:06 -07:00
60d65a35c9 Reverse proxy news feed json 2025-06-09 12:06:18 -07:00
6a8e9fc3cc Add footer for SCN, Fastly financial support 2025-06-06 15:34:03 -07:00
175382618a vendor: add SCN and Fastly logos 2025-06-06 15:33:56 -07:00
cdcf1ad1ed Get the newsfeed descriptions to auto-link 2025-06-04 12:29:26 -07:00
74f4f3d5e0 Update index.html 2025-06-04 15:00:09 -04:00
74dd0ae527
Fix news feed time being off 2025-06-03 22:53:58 -07:00
8bcb1e9810 style.css: Increase font size to 16px
i'm paying good money for these screens
2025-06-04 01:40:06 -04:00
de1b179a10
Add what's new/news feed 2025-06-03 22:31:35 -07:00
m
ceb1e82d60
Woopsies merge conflict 2025-05-08 21:52:34 -07:00
m
cadd36a3a9
Remove second floor, might be a lil confusing
isn't relevant outside of accessibility concerns which we also link to
on the main page. 2nd floor implies some sort of entry area
2025-05-08 21:37:06 -07:00
61921b5f8a Add more pictures to "more?" page 2025-04-23 09:09:10 -07:00
d43a11ac3f Link Matrix chat explicitly 2025-04-23 09:09:10 -07:00
4545dcce6f Fix temperature sensor null case 2025-04-23 09:09:10 -07:00
73e970ce68 Update index.html 2025-04-17 15:11:41 -04:00
cffcc85fd5 Link to "Kinds of Open" section 2025-04-13 12:22:16 -07:00
d03d8cb955 Your honour, I plead oopsie daisie in the first degree 2025-04-10 23:15:17 -07:00
f24a41ae00 Trim down membership.html to link to wiki; Improve cross-linking 2025-04-10 23:14:44 -07:00
2fae74e74d membership: Update based on [[Becoming a Member]] 2025-04-10 01:20:53 -07:00
21cd6babaf link to da chats 2025-04-04 01:02:05 -07:00
dbe7efb2b5 Fix Google-Extended AI bot name 2025-04-04 00:53:20 -07:00
86080df835 Entrance page moved 2025-04-03 17:36:26 -07:00
ed54e13aad Automatically link URLs 2025-04-01 10:31:31 -07:00
f40bff9e00 Use <ol> with lowercase letters 2025-03-28 15:19:37 -07:00
8918fbdae7 Update membership steps based on recent changes 2025-03-28 15:16:07 -07:00
ed18f36775 add payphone direct number 2025-03-24 16:19:49 -07:00
m
6df6df2b61
Show off our slick vanity phone numbers 2025-03-24 15:28:37 -07:00
m
9536c677d9
Add anchor point IDs to section headers 2025-03-24 15:27:57 -07:00
ee436c76c2 fix broken html tags (oops) 2025-03-16 12:34:26 -07:00
98cdf33660 Make the <h1> slay 2025-03-14 12:42:28 -07:00
0feb8da4cd Git LFS the font files 2025-03-14 12:08:32 -07:00
590588f93b better space infra link just dropped 2025-03-14 01:01:34 -07:00
983a5ddd3a Get in on the mapallspace (thanks @ellie) 2025-03-14 00:57:37 -07:00
4bd20d04e7 Vendor font 2025-03-13 18:41:06 -07:00
abfcdf0761 Fix duplicate picture 2025-03-13 12:09:44 -07:00
e6ef6315ac Post about onboarding forgejo wiki 2025-03-13 11:05:02 -07:00
bf22505073 add a lil blurb 2025-03-13 10:39:59 -07:00
3f8a64f417 polish up (tm) the copy on more.html 2025-03-13 10:17:31 -07:00
ac5ef5505c Clean up more.html, add alt text, move to more descriptive image names 2025-03-13 10:08:25 -07:00
bbb9c8f04c Bake some error handling into spaceapi fetching 2025-03-11 22:30:55 -07:00
afdf5dc10a Explicitly say it's the second floor, which apparently scares people 2025-03-11 22:05:07 -07:00
m
06cda81e76
Add our own vendored rrule to support SETBYPOS
forked version @ https://github.com/devhack-seattle/rrule
2025-03-10 10:59:05 -04:00
m
4c7dcdac6e
Change spaceapi section formatting for consistency 2025-03-10 07:33:15 -04:00
leafcompost
17c4131d3f Mess with punctuation 2025-03-06 12:50:40 -08:00
leafcompost
93d71dbac6 fmt css 2025-03-06 12:49:35 -08:00
leafcompost
8be1c76911 Add an AI robots.txt 2025-03-06 12:48:31 -08:00
leafcompost
11f0f13bd4 strategic <br> 2025-03-04 10:10:39 -08:00
leafcompost
88643108e7 Do some time math refactoring 2025-03-04 10:00:00 -08:00
leafcompost
ddaf8e075a Revise doors open copy 2025-03-03 17:41:49 -08:00
maia
1d62650352 merged [[Admission]] and [[Entrance]], updating link 2025-03-01 12:00:15 -05:00
leafcompost
8ef028bc2d c/e 2025-03-01 08:38:23 -08:00
leafcompost
3f55efebf8 Vendor time & date polyfill 2025-03-01 08:37:47 -08:00
leafcompost
dc70f1ac38 Fix units code 2025-02-27 12:10:57 -08:00
maia
50ad61244e Merge pull request 'Have human-friendly copy for spaceapi' (#7) from spaceapi-human into main
Reviewed-on: devhack/devhack.net#7
2025-02-27 15:05:46 -05:00
leafcompost
40e35a4738 use spaceapi 2025-02-27 12:04:58 -08:00
leafcompost
e8feab9eca gitignore spaceapi 2025-02-27 11:26:55 -08:00
m
8c462507b6
Add space status section (hooking into spaceapi) 2025-02-27 18:44:02 +01:00
maia
9cf9114c64 link to projects category page 2025-01-08 19:57:11 -05:00
maia
18fead91f0 line break for aesthetics 2025-01-08 19:56:25 -05:00
m
f4958f2ac6
Express that devhack services are not garunteed reliable 2025-01-08 14:18:46 -08:00
kalin
fe49edba00 fixing bottom text 2025-01-07 18:15:07 -05:00
kalin
be1874bcce change last imgs to be focus foundry 2025-01-07 18:13:23 -05:00
kalin
1d9a6a2a93 info is on wiki 2025-01-07 02:34:40 -05:00
kalin
7950f3a1a0 adding locations for links 2025-01-07 02:31:28 -05:00
kalin
6e539a8ce1 html changes for main site 2025-01-05 22:26:15 -05:00
kalin
edb4b8f481 assets 2025-01-05 22:25:52 -05:00
kalin
6ed05ba06d fixing text entry to be wider 2025-01-05 18:22:01 -05:00
kalin
498e7be1dc Update style.css 2025-01-05 18:21:26 -05:00
leafcompost
a4c7261448 Denote locations of phones instead 2024-10-31 10:01:12 -07:00
leafcompost
9e1bc58748 Note that calendar needs JS 2024-10-31 09:57:58 -07:00
leafcompost
a0bf838b00 Explicitly list phone number too 2024-10-31 09:57:29 -07:00
Caleb Smith
41878d7fbb add phone and fax number 2024-10-30 12:17:17 -07:00
0779ea0f2c Update membership.html to link to member portal instead of stripe 2024-10-28 10:49:28 -07:00
leafcompost
2e8736e4ee stray space 2024-10-19 12:24:10 -07:00
a
65cc7052a7 admission page (#3) 2024-10-18 23:53:33 -04:00
leafcompost
0520c3dd87 jk no bold 2024-10-16 11:39:44 -07:00
leafcompost
6fd3d42b8c Copyedit the rest of the webbed page 2024-10-16 11:36:44 -07:00
leafcompost
3d9590fdc0 Add a "Managing your membership" section 2024-10-16 11:33:44 -07:00
leafcompost
97c9617957 An attempt at deduplicating one-off events 2024-10-14 13:38:52 -07:00

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
*.woff filter=lfs diff=lfs merge=lfs -text
*.woff2 filter=lfs diff=lfs merge=lfs -text

5
.gitignore vendored
View file

@ -1,3 +1,6 @@
# Calendar file used for local development. On a production server, the calendar
# file is made available at the same path by reverse proxy.
calendar.ics
calendar.ics
spaceapi.json
news.json
.DS_Store

View file

@ -1,34 +1,35 @@
https://fahrplan.events.ccc.de/congress/2007/Fahrplan/attachments/1003_Building%20a%20Hacker%20Space.pdf
# devhack.net
hackerbot labs seemed to be the closest thing to a seattle hackerspace
> It's called devhack dot net because the devhack is on the net.
pdx hackerspace is *very* cool and I want to visit sometime.
This is the official website for /dev/hack, a hackerspace in Seattle.
Contributions are welcome. The canonical repository for this project is at
https://git.devhack.net/devhack/devhack.net.
https://www.loopnet.com/search/office-space/seattle-wa/for-lease/?sk=50d7d36bf2f66fbcbac3baa5bf968fbf&bb=o4mp25jrtQh1x3H
## Development
To get started with developing the website:
office spaces aren't actually too expensive.
1. Clone this repository.
2. Open `index.html` in your web browser to view the site, or better yet, use
one of the ad-hoc live reload tools like Visual Studio Code's Live Server
extension.
3. Make the desired changes to:
* `index.html`, `more.html`: Body copy for the main pages.
* `index-cal.js`: Handles the calendar functionality.
* `index-newsfeed.js`: Manages the news feed.
* `index-spaceapi.js`: Deals with the SpaceAPI integration.
* `index-common.js`: Contains shared utility functions.
seattle hacker spaces are a thing?
For local development, you may want to download local copies of the data files
that the site uses. In production, they are reverse proxied from their
respective origins, and so they do not exist in git:
step 1: garner/gauge interest
step 2: obligate some people into being in charge with me / starting it together & splitting the costs
step 3: find a space
step 4: move in
step 5: make it cool
things the hackerspace has:
seedbox
server shit
router
VR headset
old computers
projector setup
big ol UPS
/dev/hack
```sh
# in the root of the repository, run:
curl -Lo calendar.ics https://devhack.net/calendar.ics
curl -Lo spaceapi.json https://devhack.net/spaceapi.json
curl -Lo news.json https://devhack.net/news.json
```

34
RELICS.md Normal file
View file

@ -0,0 +1,34 @@
https://fahrplan.events.ccc.de/congress/2007/Fahrplan/attachments/1003_Building%20a%20Hacker%20Space.pdf
hackerbot labs seemed to be the closest thing to a seattle hackerspace
pdx hackerspace is *very* cool and I want to visit sometime.
https://www.loopnet.com/search/office-space/seattle-wa/for-lease/?sk=50d7d36bf2f66fbcbac3baa5bf968fbf&bb=o4mp25jrtQh1x3H
office spaces aren't actually too expensive.
seattle hacker spaces are a thing?
step 1: garner/gauge interest
step 2: obligate some people into being in charge with me / starting it together & splitting the costs
step 3: find a space
step 4: move in
step 5: make it cool
things the hackerspace has:
seedbox
server shit
router
VR headset
old computers
projector setup
big ol UPS
/dev/hack

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" id="img" fill="currentColor">
<path d="M579-480 285-774q-15-15-14.5-35.5T286-845q15-15 35.5-15t35.5 15l307 308q12 12 18 27t6 30q0 15-6 30t-18 27L356-115q-15 15-35 14.5T286-116q-15-15-15-35.5t15-35.5l293-293Z"/>
</svg>

After

Width:  |  Height:  |  Size: 314 B

View file

@ -16,10 +16,28 @@ function escape(str) {
});
}
function linkAndEscape(str) {
if (!str) return '';
const escaped = str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
const urlRegex = /(https?:\/\/[^\s]+)/g;
return escaped.replace(urlRegex, (url) => {
const safeUrl = encodeURI(url);
return `<a href="${safeUrl}" target="_blank">${safeUrl}</a>`;
});
}
async function fetchCalendar(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch calendar: ${response.status} ${response.statusText}`);
throw new Error(`http: ${response.status} ${response.statusText}`);
}
const icsData = await response.text();
const jcalData = ICAL.parse(icsData);
@ -43,7 +61,7 @@ function drawEventList(events) {
const li = document.createElement('li');
const dateStr = `${event.start.toLocaleDateString('en-US', dateOptions)}`.toLocaleLowerCase();
const timeStr = `${event.start.toLocaleTimeString('en-US', timeOptions)} - ${event.end.toLocaleTimeString('en-US', timeOptions)}`.toLocaleLowerCase();
const descriptionStr = event.description ? `<br>${escape(event.description)}` : '';
const descriptionStr = event.description ? `<br>${linkAndEscape(event.description)}` : '';
const recurrence = event.recurrence ? `${event.recurrence}<br>`.toLocaleLowerCase() : '';
li.innerHTML = `${escape(event.summary)}<span class="secondary">${descriptionStr}<br>${recurrence}${dateStr}<br>${timeStr}</span>`;
ul.appendChild(li);
@ -70,10 +88,19 @@ function getUpcomingEvents(vcalendar, numEvents = 10) {
const upcomingEvents = [];
let titlesSeen = new Set();
events.forEach(event => {
const icalEvent = new ICAL.Event(event);
if (icalEvent.isRecurring()) {
// an attempt at preventing duplicate events when the same event was
// preempted by an one-off instance created by editing the single
// occurrence in NextCloud.
if (titlesSeen.has(icalEvent.summary)) {
return;
}
const expand = icalEvent.iterator();
let next;
@ -85,6 +112,7 @@ function getUpcomingEvents(vcalendar, numEvents = 10) {
const end = next.clone();
end.addDuration(duration);
if (end.compare(hoursAfterEnd) >= 0) {
titlesSeen.add(icalEvent.summary);
upcomingEvents.push({
summary: icalEvent.summary,
description: icalEvent.description,
@ -98,6 +126,7 @@ function getUpcomingEvents(vcalendar, numEvents = 10) {
} else {
const eventStart = icalEvent.startDate;
if (eventStart.compare(hoursAfterEnd) >= 0) {
titlesSeen.add(icalEvent.summary);
upcomingEvents.push({
summary: icalEvent.summary,
description: icalEvent.description,
@ -108,6 +137,8 @@ function getUpcomingEvents(vcalendar, numEvents = 10) {
}
});
console.log("events added: " + Array.from(titlesSeen));
return upcomingEvents.sort((a, b) => a.start - b.start).slice(0, numEvents);
}
@ -124,7 +155,12 @@ async function doCalendar(calendarUrl, targetElementId) {
targetElement.appendChild(eventList);
}
catch (error) {
targetElement.innerHTML = '<p>Sorry - couldn\'t load the calendar :(</p> <small>' + error + '</small>';
console.error("Error fetching calendar:", error);
targetElement.innerHTML = '';
targetElement.appendChild(createError({
thing: "calendar",
message: error.toString()
}));
}
}
doCalendar(icsUrl, 'cal-parsed');

60
index-common.js Normal file
View file

@ -0,0 +1,60 @@
function escape(str) {
return str.replace(/[&<>"'/]/g, function (char) {
const escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&apos;',
'/': '&#47;'
};
return escapeMap[char] || char;
});
}
function elem(parent, query, value = undefined, unsafeHtml = false) {
/** @type {HTMLElement} */
const element = parent.querySelector(query);
if (!element) {
throw new Error(`Element not found for query: ${query}`);
}
if (value !== undefined) {
if (unsafeHtml) {
element.innerHTML = value;
} else {
element.textContent = value;
}
} else {
return element;
}
}
function createError({ thing, message }) {
/** @type {HTMLTemplateElement} */
const errorTemplate = document.getElementById("error-template");
const errorElement = errorTemplate.content.firstElementChild.cloneNode(true);
elem(errorElement, `[data-slot="thing"]`, thing);
elem(errorElement, `[data-slot="message"]`, message);
return errorElement;
}
function linkAndEscape(str) {
if (!str) return '';
const escaped = str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
const urlRegex = /(https?:\/\/[^\s]+)/g;
return escaped.replace(urlRegex, (url) => {
const safeUrl = encodeURI(url);
return `<a href="${safeUrl}" target="_blank">${safeUrl}</a>`;
});
}

30
index-health.js Normal file
View file

@ -0,0 +1,30 @@
(async () => {
const el = document.getElementById('service-warning');
if (!el) return;
// checks healthchecks.io to see if any of our important services are down
// in the future maybe we do something self-hosted?
async function areWeLosing() {
const r = await fetch('https://healthchecks.io/b/2/f564cd28-6a7b-474c-bd33-aea7b641d359.json', { cache: 'no-store' });
if (!r.ok) throw new Error(`http: ${r.status} ${r.statusText}`);
const status = await r.json();
if (!status || typeof status.down != 'number') {
throw new Error('unexpected healthcheck response: ' + JSON.stringify(status));
}
return status.down > 0;
}
try {
const isDown = await areWeLosing();
if (isDown) {
el.innerHTML = '<strong>oh naur!</strong> some space services are currently down, so not all web interactions might work. to report this incident, <a href="#contact">contact us</a>.';
el.hidden = false;
} else {
el.hidden = true;
}
} catch (e) {
// if something goes wrong, no need to alert the visitor since this is just extra credit.
console.error('Error checking service health:', e);
el.hidden = true;
}
})();

192
index-newsfeed.js Normal file
View file

@ -0,0 +1,192 @@
const newsFeed = document.getElementById("news-feed");
const newsList = document.getElementById("news-list");
/** @type {HTMLButtonElement} */
const newsFeedRight = document.getElementById("news-feed-right");
/** @type {HTMLTemplateElement} */
const newsItemTemplate = document.getElementById("news-item-template");
const timeAgoFormatter = new Intl.RelativeTimeFormat(undefined, {
style: "short",
numeric: "auto",
});
async function main() {
newsFeedRight.addEventListener("click", () => {
if (newsFeedRight.dataset.last == "true") {
newsFeedRight.dataset.last = false;
newsList.scrollTo({ left: 0 });
return;
}
const currentItem = currentItemInNewsList();
const nextItem = currentItem?.nextElementSibling;
newsList.scrollTo({ left: nextItem.offsetLeft });
updateNewsFeedRightButton();
});
newsList.addEventListener("scroll", () => {
updateNewsFeedRightButton();
});
await fetchNewsFeed();
}
// updateNewsFeedRightButton updates the news feed right button's
// dataset properties.
function updateNewsFeedRightButton() {
const isScrollEnd =
newsList.scrollLeft + newsList.clientWidth >= newsList.scrollWidth;
const currentItem = currentItemInNewsList();
const nextItem = currentItem?.nextElementSibling;
newsFeedRight.dataset.last = !nextItem || isScrollEnd;
}
// currentItemInNewsList returns the currently shown item in the news feed,
// defined by the scroll position of the newsList. If the scroll position
// is at the end of the list, it returns null.
function currentItemInNewsList() {
const scrollLeft = newsList.scrollLeft;
const children = [...newsList.children];
return children.find((item) => item.offsetLeft >= scrollLeft);
}
// fetchNewsFeed fetches the news feed from the server and appends them to
// newsList.
async function fetchNewsFeed(afterID = null) {
newsFeed.querySelector(".error")?.remove();
newsList.replaceChildren();
try {
const query = afterID ? `?after=${afterID}` : "";
const response = await fetch(`/news.json?${query}`, {
headers: { "Accept": "application/json" },
credentials: "omit",
});
if (!response.ok) {
throw new Error(`http: ${response.status} ${response.statusText}`);
}
const feed = await response.json();
const newsItems = feed.map((item) =>
createNewsItem({
id: item.id,
createdAt: item.created_at,
editedAt: item.edited_at,
username: item.author.username,
content: item.content,
thumbnailURL: item.thumbnail_url,
thumbnailURLSmall: item.thumbnail_url_small,
tracTicketID: item.trac_ticket_id,
})
);
newsList.append(...newsItems);
newsFeed.dataset.initial = false;
newsFeed.dataset.error = false;
} catch (err) {
console.error("Error fetching news feed:", err);
newsFeed.append(createError({
thing: "news feed",
message: `${err}`
}));
newsFeed.dataset.error = true;
}
}
function createNewsItem({
id,
createdAt,
editedAt,
username,
content,
thumbnailURL,
thumbnailURLSmall,
tracTicketID,
}) {
const newsItem = newsItemTemplate.content.firstElementChild.cloneNode(true);
newsItem.id = `news-${id}`;
elem(newsItem, ".news-username", username);
elem(newsItem, ".news-avatar").alt = `${username}'s avatar`;
elem(newsItem, ".news-avatar").src =
`https://members.devhack.net/user/avatar/${username}`;
elem(newsItem, ".news-created-time", createdAgoString(createdAt));
elem(newsItem, ".news-created-time").dateTime = createdAt;
elem(newsItem, ".news-created-time").title = createdAtTimestamp(createdAt);
elem(newsItem, ".news-content", linkAndEscape(content), true);
if (editedAt) {
elem(newsItem, ".news-edited").title = createdAtTimestamp(editedAt);
} else {
elem(newsItem, ".news-edited").setAttribute("hidden", "");
elem(newsItem, ".news-edited").setAttribute("aria-hidden", "true");
}
if (thumbnailURL) {
elem(newsItem, ".news-thumbnail-link").href = thumbnailURL;
elem(newsItem, ".news-thumbnail-link").target = "_blank";
elem(newsItem, ".news-thumbnail-image").src = thumbnailURLSmall ??
thumbnailURL;
elem(newsItem, ".news-thumbnail-image").alt = `thumbnail image for post`;
}
if (tracTicketID) {
elem(newsItem, ".news-trac-ticket-id", `#${tracTicketID}`);
elem(newsItem, ".news-trac-ticket-id").target = "_blank";
elem(newsItem, ".news-trac-ticket-id").href =
`https://bugs.devhack.net/ticket/${tracTicketID}`;
}
return newsItem;
}
function createdAgoString(createdAt) {
const now = new Date();
const createdAtDate = new Date(Date.parse(createdAt));
const diffMs = createdAtDate - now; // Negative for past dates
// Convert to various time units. The following calculates are just heuristics
// and are not accurate for all months/years. This is fine because it is just
// a human-readable approximation.
const diffHours = diffMs / (1000 * 60 * 60);
const diffDays = diffHours / 24;
const diffMonths = diffDays / 30;
const diffYears = diffDays / 365;
if (Math.abs(diffYears) >= 1) {
return timeAgoFormatter.format(Math.round(diffYears), "year");
}
if (Math.abs(diffMonths) >= 1) {
return timeAgoFormatter.format(Math.round(diffMonths), "month");
}
if (Math.abs(diffDays) >= 1) {
return timeAgoFormatter.format(Math.round(diffDays), "day");
}
return timeAgoFormatter.format(Math.round(diffHours), "hour");
}
function createdAtTimestamp(createdAt) {
const createdAtDate = new Date(Date.parse(createdAt));
return createdAtDate.toLocaleString(undefined, {
weekday: "long",
month: "numeric",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
});
}
main();

77
index-spaceapi.js Normal file
View file

@ -0,0 +1,77 @@
const spaceapiUrl = '/spaceapi.json';
function escape(str) {
return str.replace(/[&<>"'/]/g, function (char) {
const escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&apos;',
'/': '&#47;'
};
return escapeMap[char] || char;
});
}
/* figures out what unit a time value should be displayed in, then returns the value in that unit and the name of that unit */
function secondsToValueInUnit(seconds) {
const absSeconds = Math.abs(seconds);
if (absSeconds < 3600) {
return [Math.round(seconds / 60), 'minutes'];
}
if (absSeconds < 86400) {
return [Math.round(seconds / 3600), 'hours'];
}
return [Math.round(seconds / 86400), 'days'];
}
// Main function :)
async function doSpaceapi(url, targetElementId) {
const targetElement = document.getElementById(targetElementId);
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`http: ${response.status} ${response.statusText}`);
}
let spaceapi;
try {
spaceapi = await response.json();
} catch (jsonError) {
throw new Error('bad json? ' + jsonError.message);
}
console.log(spaceapi);
const state = spaceapi["state"];
const sensors = spaceapi["sensors"];
var openHtml = '';
if (state && state.lastchange && typeof state.open !== 'undefined') {
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
const elapsed = secondsToValueInUnit(state.lastchange - (Date.now() / 1000.0));
const status = state.open ? '<a href="https://wiki.devhack.net/Entering_The_Space#Kinds_of_%22Open%22" target="_blank">doors open</a>!' : 'closed,';
openHtml = `space: ${status} as of ${rtf.format(elapsed[0], elapsed[1])} `;
}
var tempHtml = openHtml ? '<br>' : '';
if (sensors && sensors.temperature && sensors.temperature[0] && sensors.temperature[0].value) {
const temp = Math.round(sensors.temperature[0].value);
const unit = sensors.temperature[0].unit;
tempHtml = tempHtml + 'temp: ' + temp + unit + ' inside'
}
targetElement.innerHTML = '<p>' + openHtml + tempHtml + '</p>';
}
catch (error) {
console.error("Error fetching spaceapi:", error);
targetElement.innerHTML = '';
targetElement.appendChild(createError({
thing: "spaceapi",
message: error.toString()
}));
}
}
doSpaceapi(spaceapiUrl, 'spaceapi-body');

View file

@ -1,43 +1,145 @@
<!DOCTYPE html>
<!-- Look at you, hacker: a pathetic creature of meat and bone, panting and sweating as you run through my corridors. How can you challenge a perfect, immortal machine? -->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>/dev/hack</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="seattle hackerspace focused on community and building cool things">
<link rel="stylesheet" href="style.css">
<link rel="canonical" href="https://www.devhack.net/">
<script src="vendor/ical.min.js"></script>
<script src="vendor/rrule.2.8.1.min.js"></script>
<script src="vendor/rrule.js"></script>
<script src="vendor/polyfill.min.js"></script>
<script src="index-common.js"></script>
<script defer src="index-cal.js"></script>
<script defer src="index-spaceapi.js"></script>
<script defer src="index-newsfeed.js" type="module"></script>
<script defer src="index-health.js"></script>
<link rel="canonical" href="http://devhack.net" />
</head>
<body>
<h1>/dev/hack
<span style="display: inline-block; white-space: nowrap">$
<span class="holder" style="display: inline-block; white-space: nowrap">$
<!-- decorative, for the cool prompt effect -->
<input aria-hidden="true" type="text" autofocus size="2" name="_"></span>
</h1>
<p class="block">seattle hackerspace</p>
<p class="meow"><strong>queer</strong>, <strong>anarchist</strong>, <strong>leftist</strong>, seattle hackerspace<br>focused on community and building cool things</p>
<a href="more.html">click here to learn more </a>
<p class="block">
<span class="address">4534½ university&nbsp;way&nbsp;n.e.
<span class="address">4534 1/2 university&nbsp;way&nbsp;ne
<br>press [#] on keypad for doorbell
<br>
see info on: <a href="https://wiki.devhack.net/Directions">getting here</a> and
visiting info: <a href="https://wiki.devhack.net/Entering_The_Space">space access</a>,
<a href="https://wiki.devhack.net/Directions">directions</a>, and
<a href="https://wiki.devhack.net/Accessibility">accessibility</a>
</span>
</p>
<h2>calendar <span class="small">(<a href="/calendar.ics">ics</a>)</span></h2>
<div id="cal-parsed">
<h2 id="status">status <span class="small">(<a href="https://mapall.space/heatmap/show.php?id=/dev/hack">stats</a>,
<a href="/spaceapi.json">spaceapi.json</a>)</span></h2>
<div id="service-warning" class="error" hidden role="alert"></div>
<div id="spaceapi-body">
<ul>
<li>loading...</li>
<li>loading... (do you have javascript?)</li>
</ul>
</div>
<h2>contact</h2>
<ul>
<!-- use HTML entities to obfuscate email address -->
<li>e-mail: <a
href="mailto&colon;hello&#x2D;25@devhack&period;net">&#x68;&#x65;&#x6C;&#x6C;&#x6F;&commat;devhack&period;net</a>
</li>
</ul>
<h2>
what's new
<span class="small">(
<a href="https://members.devhack.net/news">add</a>,
<a href="https://members.devhack.net/news/feed.json">json</a>,
<a href="https://members.devhack.net/news/feed.atom">atom</a>
)</span>
</h2>
<div id="news-feed">
<div id="news-feed-gradient" class="overlay"></div>
<div id="news-feed-controls" class="overlay">
<button id="news-feed-right" aria-label="next news item">
<svg width="24px" height="24px">
<use href="/assets/arrow_forward_ios.svg#img"></use>
</svg>
</button>
</div>
<ul id="news-list">
<li>loading... (do you have JavaScript?)</li>
</ul>
</div>
<template id="news-item-template">
<li class="news-item">
<header class="news-author">
<img class="news-avatar" />
<p>
<span class="news-username"></span>
<br />
<time class="news-created-time"></time>
<span class="news-edited"><!--(edited)--></span>
</p>
</header>
<p class="news-body">
<span class="news-content"></span>
<a class="news-trac-ticket-id"></a>
</p>
<a class="news-thumbnail-link" role="button">
<img class="news-thumbnail-image" />
</a>
</li>
</template>
<h2 id="calendar">calendar <span class="small">(<a href="/calendar.ics">ics</a>)</span></h2>
<div id="cal-parsed">
<ul>
<li>loading... (do you have JavaScript?)</li>
</ul>
</div>
<h2 id="contact">contact</h2>
<dl>
<!-- use HTML entities to obfuscate email address -->
<dt>chats</dt>
<dd>
<a href="&#x68;&#x74;&#x74;&#x70;&#x73;&colon;&sol;&sol;&#x6D;&#x61;&#x74;&#x72;&#x69;&#x78;&period;&#x74;&#x6F;/#/#lobby&colon;&#x64;&#x65;&#x76;&#x68;&#x61;&#x63;&#x6B;&period;&#x6E;&#x65;&#x74;"
target="_blank">#lobby&colon;&#x64;&#x65;&#x76;&#x68;&#x61;&#x63;&#x6B;&period;&#x6E;&#x65;&#x74;</a>
on matrix
(<a href="https://wiki.devhack.net/Chatspace" target="_blank">wiki</a>)
</dd>
<dt>e-mail</dt>
<dd><a
href="mailto&colon;hello&#x2D;25@devhack&period;net">&#x68;&#x65;&#x6C;&#x6C;&#x6F;&commat;devhack&period;net</a>
</dd>
<dt>telephony</dt>
<dd>
- voice: <a href="tel:+18333384225">+1 (833) DEV-HACK</a><br>
- fax: <a href="tel:+18443384225">+1 (844) DEV-HACK</a><br>
- payphone: <a href="tel:+15648887373">+1 (564) 888-7373</a>
</dd>
<dt>mail (send us cards!)</dt>
<dd>/dev/hack<br>
4534 1/2 University Way NE<br>
Seattle, WA 98105-4528<br>
US (<a href="https://wiki.devhack.net/Mail" target="_blank">wiki</a>)
</dd>
</dl>
<template id="error-template">
<div class="error">
<strong>issue loading <span data-slot="thing"></span></strong>
<small>
<span data-slot="message"></span>
<br />
</small>
</div>
</template>
<footer>
<a href="more.html#acknowledgements">
underwriting / acknowledgements
</a>
</footer>
</body>
</html>
</html>

41
lore/error.html Normal file
View file

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="UTF-8">
<title>/dev/hack</title>
<!-- random bullshit V -->
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="description" content="seattle hackerspace focused on community and building cool things"> <link rel="stylesheet" href="/lore/errorstyle.css"> <link rel="canonical" href="https://www.devhack.net/">
</head>
<body>
<p class="header header1">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
<p class="grouphug grouphugL">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
<p class="grouphug grouphugR">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/p>
<p class="baby"><span class="violet">⣈⣛⠀⠀⣐⠋</span><span class="gray"></span><span class="redpink">⠀⠀⠰</span><span class="gray"></span><span class="redpink">⡼⠷⢄⠅⠀</span><span class="gray"></span><span class="limegreen">⠙⠦⠥⠯⢉⠵⠋⠀</span><span class="gray"></span><span class="pink">⠛⢻⡷⠃</span><span class="violet">⣀⡴⠀</span><span class="gray"></span><span class="redpink">⠀⠈⠑⠛
</span><span class="gray"></span><span class="violet">⠱⣡</span><span class="gray"></span><span class="violet">⢰⡬⠛</span><span class="redpink">⢰⡞⢳⡀</span><span class="gray"></span><span class="lightblue2">⠀⡠⠤⡄</span><span class="gray"></span><span class="pink">⠀⣠⠟</span><span class="gray"></span><span class="violet">⢺⣝⡧⠀</span><span class="gray"></span><span class="pink">⠀⡀⢀⡠⠠⡀
</span><span class="gray"></span><span class="violet">⠉⠈⠀</span><span class="gray">⠁⠀</span><span class="redpink">⠘⠾⠻⠉</span><span class="white">⣀⣠⣤⣴⣶⣶⣶⣶⣦⣤⣄</span><span class="lightblue2"></span><span class="gray"></span><span class="lightblue2">⣠⠊⠀⢰⠃</span><span class="gray"></span><span class="yellowgreen">⡼⡉⢳⠀</span><span class="gray"></span><span class="violet">⠰⠋⠁</span><span class="gray"></span><span class="pink">⢀⡸⣀⣠⠅⡰⠃
</span><span class="gray"></span><span class="pink">⠀⢀⡀⢲⢒⠂</span><span class="gray"></span><span class="white">⣞⠱⣯⣉⣀⣀⣀⣀⣀⣠⡭⠇⣹</span><span class="gray"></span><span class="lightblue2">⢰⠃⠀⠀</span><span class="gray">⡘⠀</span><span class="yellowgreen">⠀⠉</span><span class="gray"></span><span class="yellowgreen"></span><span class="limegreen">⢠⣲⢦</span><span class="gray"></span><span class="lightblue">⠀⢀⡴⠋⡜</span><span class="pink">⠈⠛⠉⠢⡴⠁⠀
</span><span class="gray"></span><span class="pink">⠀⠴⢍⣹⣄⠾⠀</span><span class="gray"></span><span class="white">⠈⠑⠒⠒⠒⠒⠒⠒⠒⠒⠚⠉⠁</span><span class="lightblue2">⡠⠃</span><span class="gray"></span><span class="lightblue2">⠠⡇</span><span class="gray"></span><span class="yellowgreen">⠀⠰⣣⣱</span><span class="gray"></span><span class="limegreen">⠉⠉</span><span class="gray"></span><span class="lightblue">⠀⢠⠊⠀⡰</span><span class="gray">⠁⠀⠀⠀⠀⠀⠀⠀
</span><span class="pink">⠀⢸⠒⢒⣂⠬⠀</span><span class="gray"></span><span class="lightblue"></span><span class="gray"></span><span class="lightblue2">⠈⠉⠈⠉⠒⠤⠤⠳</span><span class="gray">⣄⠀⠀⠈⠀</span><span class="lightblue">⣠⢲⠀⠀⣀⠴⠃⠀⢰⠁</span><span class="gray">
</span><span class="lightgold">⣄⣀⣉⠁</span><span class="gray">⠀⠀⠀⢀</span><span class="lightblue">⡤⠂⠁</span><span class="gray"></span><span class="lightblue"></span><span class="gray"></span><span class="lightblue">⠈⠋⢿⣓⠫⡉⠉⠉⠉⠇⠇⢇⠀⠸⡀</span><span class="gray"></span><span class="lightgold">⢠⠏⣆⡞⡆</span><span class="gray">
</span><span class="lightgold">⠀⢰⠁⠀</span><span class="gray"></span><span class="lightblue">⣎⠀</span><span class="gray"></span><span class="lightblue"></span><span class="gray"></span><span class="lightblue">⠀⠀⠻⠆⠲⣰⠀⠀⣸⠜⠛⢤⣀⠐⡄</span><span class="gray"></span><span class="lightgold">⣼⢰⣹⣹⠁⠀
⠋⠑⠓</span><span class="gray">⡀⠀⠀⠀</span><span class="lightblue">⠸⣄⣀</span><span class="gray"></span><span class="lightblue">⢀⣀⡀⠀</span><span class="gray"></span><span class="lightblue">⠀⠆⣄⠀</span><span class="gray"></span><span class="lightblue">⠀⠀⠁⠘⢀⣸⣔⣊⠁</span><span class="gray"></span><span class="lightgold"></span><span class="gray"></span><span class="lightblue">⠉⠁</span><span class="gray"></span><span class="lightgold">⣇⠇⣿⠃⠀⠀
⠀⠰⣴⢿⣤⠄</span><span class="gray">⠀⠀⠈</span><span class="lightblue">⠢⡉⠉⠁⠘⠫⢥⢆⡞⣼⣼⣏⣌⢎⠄</span><span class="gray"></span><span class="lightblue">⠀⢀⡀⠀⠀⠀⠒⠊⠙⠳⣴⠉⠀</span><span class="gray"></span><span class="lightgold">⣼⡁⢹⠖⠀⢀⣟⣘⡃⠀</span><span class="gray">
</span><span class="lightgold">⠀⠀⠟⠛⠇⠀</span><span class="gray"></span><span class="lightblue">⠀⠈⠒⠠⢔⣀</span><span class="gray">⠀⠀⠀⠁⠈⠀⠈</span><span class="lightblue">⢹⣂</span><span class="gray"></span><span class="lightblue">⠀⠫⡀⠀</span><span class="gray"></span><span class="lightgold">⠀⡀</span><span class="gray"></span><span class="lightgold">⠀⢹⡏⠀</span><span class="gray"></span><span class="lightgold">⠘⠛⠻⠃⠀</span><span class="gray">
</span><span class="indigo">⠀⠀⢀⡤⠖⠚⢷⠀</span><span class="lightblue">⠀⠀⠀⠀⠀⢉⡶⣒⢤⠀</span><span class="gray"></span><span class="lightblue">⠐⠓⠤⣀⠀</span><span class="gray">⠀⠈</span><span class="lightblue">⠑⠢⠤⢀</span><span class="gray"></span><span class="lightgold">⢀⣴⣛⡶</span><span class="gray">⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
</span><span class="indigo">⠀⠀⡠⢞⣡⠴⠒⠋⠉⡆⠀</span><span class="gray"></span><span class="lightblue">⠀⢸⡁⣣⠞⠀</span><span class="gray"></span><span class="lightgold"></span><span class="gray"></span><span class="lightblue">⠉⠁⠒⠛⠒⠒⠋</span><span class="gray"></span><span class="limegreen"></span><span class="gray">⡀⠀</span><span class="lightgold">⠹⠁</span><span class="gray"></span><span class="redpink">⠀⣤⣸⣵⡀
</span><span class="indigo">⣠⣮⣖⣫⠔⠒⠉⠉⠉⢻⠀</span><span class="gray"></span><span class="lightblue">⠀⠀⠟⠁</span><span class="gray"></span><span class="lightgold">⠀⢹⡯⣷</span><span class="gray">⠂⠀⠀</span><span class="limegreen">⢸⣍⠉⠓⣲⠋⠉⠉⠙⢦⡀</span><span class="gray"></span><span class="limegreen"></span><span class="gray"></span><span class="redpink">⢿⣿⡽⠃
</span></p>
<h2 id="contact">404 page not found.</h2>
<a class="header3" href="https://www.devhack.net/">click here to return home</a>
<p class="header header2">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
</body></html>

449
lore/errorstyle.css Normal file
View file

@ -0,0 +1,449 @@
@import url('vendor/berkeley_mono_transfonter/stylesheet.css');
body {
background: black;
color: lime;
font-family: 'Berkeley Mono', Menlo, 'Cascadia Code', Consolas, Courier, monospace;
line-height: 1.15;
margin: 0px 20% 5% 20%;
border: 10px red;
font-size: 16px;
max-width: 800px;
overflow-y: hidden;
overflow: hidden;
}
.baby{
color:#b4ff9994;
position: absodlute;
font-size: 3.5vmin;
left:;
bottom: ;
z-index: -1;
padding-top: 1.7em;
}
.header{
position: absolute;
left:0;
z-index: 5;
background-color: black;
border:0.4em solid black;
}
h2{
margin-bottom: 20px!important;
}
.grouphug{
position: absolute;
max-width:2em;
writing-mode: vertical-rl;
padding: 0px 10px;
color:grey!important;
}
.grouphugL{
left:0;
}
.grouphugR{
right:0;
}
.grouphug3{
left:100;
}
.header1{
top:0;
margin:2px;
}
.header2{
bottom:0;
margin:0;
}
.header1, .header2, .header3{
font-size: 2.5vmin!important;
color:grey!important;
}
h2{
font-size: 6.2vmin;
}
ul {
list-style-type: '- ';
}
li {
margin-top: 0.5em;
}
dl {
margin: 0;
margin-block: 1em;
padding-inline-start: 40px;
}
dd {
margin-bottom: 0.5em;
}
dt {
margin-top: 0.5em;
}
.holder {
width: 60%;
}
[hidden] {
display: none !important;
}
.secondary {
color: #00b300;
}
input[type="text"] {
background-color: inherit;
color: inherit;
border: none;
outline: none;
font: inherit;
caret-shape: block;
width: 100%;
}
h1,
.block {
margin: 40px 0px;
}
h1 {
animation: headerGlow 4s infinite ease-in-out;
text-shadow: 0 0 5px lime, 0 0 10px lime;
}
@keyframes headerGlow {
0% {
opacity: 0.9;
text-shadow: 0 0 3px lime, 0 0 7px lime;
}
50% {
opacity: 1;
text-shadow: 0 0 8px lime, 0 0 10px lime;
}
100% {
opacity: 0.9;
text-shadow: 0 0 3px lime, 0 0 7px lime;
}
}
h2 .small {
display: inline-flex;
a:not(:first-child) {
margin-left: 0.25em;
}
}
p {
margin: 0.5em 0;
}
a,
a:visited {
color: #84d7ba;
text-decoration: none;
}
a:hover {
color: #d784a1;
}
dt::before {
content: ">";
padding-right: 0.5em;
}
.small {
font-style: normal;
font-weight: normal;
font-size: 50%;
}
.meow {
margin: 0px 0px !important;
}
.banners {
margin: 40px 0px;
}
img {
image-rendering: pixelated;
width: 85%;
align-content: center;
margin: auto;
display: inline-block;
filter: grayscale(30%);
}
img:hover {
filter: grayscale(0%);
}
.grid-container {
margin: 1em auto;
}
.grid-container {
padding: 10px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
@media (max-width: 600px) {
.grid-container {
grid-template-columns: 1fr;
}
}
.imgholder {
width: 100%;
overflow: hidden;
}
.imgholder img {
width: 100%;
height: auto;
}
.guysholder p {
margin-top: 2em;
}
#news-feed {
position: relative;
max-width: clamp(300px, 100%, 800px);
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
pointer-events: none;
}
#news-feed-gradient {
background: linear-gradient(to left,
rgba(0, 0, 0, 1) 0,
rgba(0, 0, 0, 0.8) 42px,
transparent 100px,
transparent 100%);
}
#news-feed-controls {
display: flex;
flex-direction: row;
align-items: center;
}
#news-feed-right {
cursor: pointer;
pointer-events: all;
margin-left: auto;
width: 42px;
height: 42px;
border: 1px solid lime;
border-radius: 99px;
color: lime;
background-color: oklch(from lime 0.3 c h / 0.7);
transition:
background-color 0.1s ease-in-out,
transform 0.25s ease-in-out;
opacity: 0.7;
&:hover {
opacity: 1;
}
&[data-last="true"] {
transform: rotate(180deg);
}
svg {
vertical-align: middle;
}
}
}
#news-list {
overflow: hidden;
overflow-x: auto;
scrollbar-width: thin;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
display: flex;
flex-direction: row;
gap: 1rem;
list-style: none;
padding: 0;
padding-right: 100px;
/* space for gradient */
margin: 0;
font-size: 0.85em;
.news-item {
scroll-snap-align: start;
display: flex;
flex-direction: column;
overflow: auto;
margin: 0;
padding: 1em;
flex: 1 0 200px;
min-height: 125px;
max-height: 175px;
border: 1px solid oklch(from lime 0.3 c h);
border-radius: 12px;
.news-author {
display: flex;
align-items: center;
gap: 0.5rem;
p {
margin: 0;
}
}
.news-avatar {
border-radius: 6px;
width: 2rem;
height: 2rem;
margin: 0;
object-fit: cover;
}
.news-username {
font-weight: bold;
}
.news-edited {
font-size: 0.75em;
display: inline;
}
.news-body {
flex: 1;
margin-top: 1em;
margin-bottom: 0;
padding-bottom: 1em;
}
.news-thumbnail-link {
display: block;
&:not([href]) {
display: none;
}
}
.news-thumbnail-image {
width: 100%;
margin: 0;
object-fit: cover;
border-radius: 6px;
}
}
}
footer {
margin-top: 5em;
font-size: 0.8rem;
text-align: right;
max-width: 60%;
margin-left: auto;
}
.footer-logo {
height: 1em;
width: auto;
vertical-align: middle;
margin-left: 0.25em;
/* Override rendering for logos */
image-rendering: auto;
}
.error {
border: 1px solid;
padding: .75em 1em;
margin: 1em 0;
border-radius: 10px;
font-size: 0.9em;
max-width: 50%;
}
blockquote {
padding-left: 10px;
border-left: 2px solid;
}
/* Mobile devices get slightly smaller margins, so that we actually have room
* for text.
*/
@media only screen and (max-width: 749px) {
body {
margin: 50px 5% 5% 5%;
}
.holder {
width: 35%;
}
.error {
max-width: 80%;
}
}
.violet { color: #E5F }
.gray { color: #999 }
.redpink { color: #F86 }
.limegreen { color: #0F0 }
.pink { color: lightpink }
.lightblue2 { color: #8CF }
.white { color: #FFF }
.yellowgreen { color: #CF7 }
.lightblue { color: lightblue }
.lightgold { color: #FF8 }
.indigo { color: #97F }

158
lore/schism.html Normal file
View file

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>schism</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="style.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="the-devhack-schism">The devhack schism</h1>
<p><small>This is a complicated document to write -m</small></p>
<hr />
<h2 id="summary">Summary</h2>
<p>One specific member joined devhack with misaligned expectations of
what it was, conflicting with both the original founding intentions and
the understanding of a large portion of the devhack active membership.
In the 6 months of this members tenure, they contributed a great deal
to the space but in the process alienated most of the former membership
contributing to various aspects of the devhack project, including the
original founding members and most of the infrastructure team.</p>
<p>This concluded in both a <strong>ban</strong> and a subsequent
standoff, shouting match, walk-out, and temporary closure by devhack
membership on the space itself.</p>
<p>The resulting ban cascaded from increased disengagement of long-time
membership, reaching a tipping point that caused the leadership of
devhack decided to make a unilateral decision to remove this member.
Even though they were not communicated any warnings about this happening
from leadership, this should not have come as a suprise, as they had
been subject to substantial moderation from both devhack leadership
and peers at the space.</p>
<h2 id="the-night-of-the-28th-of-august">The night of the 28th of
august</h2>
<p>Two days after an amicable exit interview, approximately 30 minutes
before the townhall convened to discuss punitive board action, this
person attempted to enter the space with the help of a few supporters.
Many members blockaded the stairwell in response for some amount of
time, before we decided to vacate the premises and hold an informal
discussion at a park a few blocks away.</p>
<p>During the blockade, this person was repeatedly asked to leave by
devhack membership while both they and their supporters recited
washington state law, questioned the spaces insurance status,
unintentionally injured themselves and claimed they needed entry to the
space for first aid, furled insults at devhack leadership and their
supporters, and generally were just very loud and did quite a lot of
emotional damage to those blockading the entrance and observers to these
events. They also threatened to get in contact with devhack business
partners to complain about our conduct throughout these events in an
attempt to tarnish devhacks business relationships.</p>
<h2 id="consequences">Consequences</h2>
<p>Consequently, these four additional members were banned from devhack
and barred access for aiding in this persons attempted entry. One ban
has been rescinded due to overreach, and one is provisional due to their
continued work with our business partners.</p>
<p>Two of the banned members have threatened to enter the space with a
police escort, one of the banned members has claimed to have filed a
police report. One auxillary member has deferred all communications with
us through legal counsel.</p>
<p>These banned members have been invited to rightfully reclaim their
personal equipment hosted at the space in a supervised fashion,
alongside other members who have chosen to bow out. This has resulted in
the loss of most of our networking equipment, most of our radio
equipment, some retro equipment we actually liked, lots of auxillary
tools, and other inconveniences.</p>
<h2 id="background-flashpoints">Background / flashpoints</h2>
<p>A concrete list of flashpoints contributing to this persons
removal:</p>
<ul>
<li>their introduction to the chatspace, and specifically
infrastructure-related rooms, and subsequent disrespectful behaviour
towards members resulted in a very explicit boundaries set by most of
the infra team “we dont want to work with you and were leaving the
chats you look for help from us in”.</li>
<li>entitlement to an audience by people who have communicated they do
not want to engage, further alienating core devhack contributors and
causing them to disengage further.</li>
<li>upon communication of boundaries and the results of their actions,
they had a rather angry rant about the state of things with lots of
words directed at both the infra team and the leadership of devhack,
resulting in an <a href="https://wiki.devhack.net/AskToLeave">ask to
leave</a> from unrelated parties witnessing this. no further action was
taken from this ATL.</li>
<li>continuations of poor communication and collaboration skills during
their attempted improvements of the space including being
disrespectful and dismissive towards prior work done at the space and
verbally attacking professional partners of devhack while degrading the
physical security of the space and the reliability of our services. The
worst of this resulting in moderation action and subsequently met with
an ATL invoked on the moderator by this person.</li>
</ul>
<p>Now, I do want to stress, this person contributed substantial hours
to the space, just in a largely independent and uncommunicative manner;
helping in some areas and hurting in others. Ultimately, /dev/hack is a
cooperative enterprise, and undermining that cooperation harms the space
more than volunteering helps it.</p>
<!-- Now, I do want to stress, this person was being very helpful at the space and
doing a lot to try to improve it. They were just doing so without taking into
account any sort of reason for why things were done the way they were, doing so
without polling the devhack membership at large for support/consensus, and
generally just steamrolling progress without any sort of cooperation skills
with those who have previously put in work to make the space what it is. This
happened in part due to the fact that everyone who has previously put in work
at the space did not like how they were treated by this person and did not want
to speak to them or work with them in any respects beyond giving them
credentials and links to existing documentation surrounding the work they were
doing. -->
<p>The ban was precipitated on our 13th member signalling their
intention to leave due to the behaviour from this person.</p>
<h2 id="learned-lessons">learned lessons</h2>
<p>Times remain fraught. Volunteers are burnt, disengaged, and trying
their best to get anything done to help the space.</p>
<p>That said, here are some direct actions we are taking to prevent
these kinds of events from <em>ever</em> happening again:</p>
<ul>
<li>Communicate the shared vision of devhack very clearly to guests and
prospective members</li>
<li>Communicate the existing structure of leadership within devhack
specifically that it is currently a benevolent dictatorship</li>
<li>Be much less lenient towards toxic and antisocial behaviour
communicating the bad behaviour to those doing it and giving them
chances to improve, but also setting boundaries to remove them from
spaces if they continue to do so.</li>
<li>Moderating the chats much more strictly in-line with our code of
conduct, implementing a moderation team that is disconnected from the
board to do so.</li>
</ul>
<hr />
<blockquote>
<p>For privacy reasons I will not be publishing any names regarding the
actors throughout these events, but I do urge other leftist, anarchist,
trans or other minority-focused organizations within the seattle area to
reach out to me at <a href="mailto:m@devhack.net"
class="email">m@devhack.net</a></p>
</blockquote>
<p>We will be collating an amount of statements, potentially anonymized
at the discretion of the writers, to place alongside this document.</p>
</body>
</html>

136
lore/schism.md Normal file
View file

@ -0,0 +1,136 @@
# The devhack schism
<small>This is a complicated document to write -m</small>
---
## Summary
One specific member joined devhack with misaligned expectations of what it was,
conflicting with both the original founding intentions and the understanding of
a large portion of the devhack active membership. In the 6 months of this
member's tenure, they contributed a great deal to the space but in the process
alienated most of the former membership contributing to various aspects of the
devhack project, including the original founding members and most
of the infrastructure team.
This concluded in both a **ban** and a subsequent standoff, shouting match,
walk-out, and temporary closure by devhack membership on the space itself.
The resulting ban cascaded from increased disengagement of long-time
membership, reaching a tipping point that caused the leadership of devhack
decided to make a unilateral decision to remove this member. Even though they
were not communicated any warnings about this happening from leadership, this
should not have come as a suprise, as they had been subject to substantial moderation
-- from both devhack leadership and peers at the space.
## The night of the 28th of august
Two days after an amicable exit interview, approximately 30 minutes before the
townhall convened to discuss punitive board action, this person attempted to
enter the space with the help of a few supporters. Many members blockaded the
stairwell in response for some amount of time, before we decided to vacate the
premises and hold an informal discussion at a park a few blocks away.
During the blockade, this person was repeatedly asked to leave by devhack
membership while both they and their supporters recited washington state law,
questioned the space's insurance status, unintentionally injured themselves and
claimed they needed entry to the space for first aid, furled insults at devhack
leadership and their supporters, and generally were just very loud and did
quite a lot of emotional damage to those blockading the entrance and observers
to these events. They also threatened to get in contact with devhack business
partners to complain about our conduct throughout these events in an attempt to
tarnish devhack's business relationships.
## Consequences
Consequently, these four additional members were banned from devhack and barred access
for aiding in this person's attempted entry. One ban has been rescinded due to
overreach, and one is provisional due to their continued work with our
business partners.
Two of the banned members have threatened to enter the space with a police
escort, one of the banned members has claimed to have filed a police report.
One auxillary member has deferred all communications with us through legal
counsel.
These banned members have been invited to rightfully reclaim their personal
equipment hosted at the space in a supervised fashion, alongside other
members who have chosen to bow out.
This has resulted in the loss of most of our networking equipment, most of our
radio equipment, some retro equipment we actually liked, lots of auxillary
tools, and other inconveniences.
## Background / flashpoints
A concrete list of flashpoints contributing to this person's removal:
- their introduction to the chatspace, and specifically infrastructure-related
rooms, and subsequent disrespectful behaviour towards members resulted in a
very explicit boundaries set by most of the infra team "we don't want to work
with you and we're leaving the chats you look for help from us in".
- entitlement to an audience by people who have communicated they
do not want to engage, further alienating core devhack contributors and
causing them to disengage further.
- upon communication of boundaries and the results of their actions, they had a
rather angry rant about the state of things with lots of words directed at
both the infra team and the leadership of devhack, resulting in an [ask to
leave](https://wiki.devhack.net/AskToLeave) from unrelated parties witnessing
this. no further action was taken from this ATL.
- continuations of poor communication and collaboration skills during their
attempted improvements of the space -- including being disrespectful and
dismissive towards prior work done at the space and verbally attacking
professional partners of devhack while degrading the physical security of the
space and the reliability of our services.
The worst of this resulting in moderation action and subsequently met with an
ATL invoked on the moderator by this person.
Now, I do want to stress, this person contributed substantial hours to the space,
just in a largely independent and uncommunicative manner; helping in some areas
and hurting in others. Ultimately, /dev/hack is a cooperative enterprise, and
undermining that cooperation harms the space more than volunteering helps it.
<!-- Now, I do want to stress, this person was being very helpful at the space and
doing a lot to try to improve it. They were just doing so without taking into
account any sort of reason for why things were done the way they were, doing so
without polling the devhack membership at large for support/consensus, and
generally just steamrolling progress without any sort of cooperation skills
with those who have previously put in work to make the space what it is. This
happened in part due to the fact that everyone who has previously put in work
at the space did not like how they were treated by this person and did not want
to speak to them or work with them in any respects beyond giving them
credentials and links to existing documentation surrounding the work they were
doing. -->
The ban was precipitated on our 13th member signalling their intention to leave
due to the behaviour from this person.
## learned lessons
Times remain fraught. Volunteers are burnt, disengaged, and trying their best to get
anything done to help the space.
That said, here are some direct actions we are taking to prevent these kinds of
events from *ever* happening again:
- Communicate the shared vision of devhack very clearly to guests and prospective members
- Communicate the existing structure of leadership within devhack --
specifically that it is currently a benevolent dictatorship
- Be much less lenient towards toxic and antisocial behaviour -- communicating
the bad behaviour to those doing it and giving them chances to improve, but
also setting boundaries to remove them from spaces if they continue to do so.
- Moderating the chats much more strictly in-line with our code of conduct,
implementing a moderation team that is disconnected from the board to do so.
---
> For privacy reasons I will not be publishing any names regarding the actors
> throughout these events, but I do urge other leftist, anarchist, trans or other
> minority-focused organizations within the seattle area to reach out to me at
> <m@devhack.net>
We will be collating an amount of statements, potentially anonymized at the
discretion of the writers, to place alongside this document.

27
lore/style.css Normal file
View file

@ -0,0 +1,27 @@
@import "../style.css";
p {
margin: 1.5em 0.5em;
}
small{
margin-top:1em;
margin-left:1.5em;
}
h1{
margin-bottom: 5px;
}
hr{
margin-top: 3em;
margin-bottom: 3em;
display:none;
}
p:nth-child(4){
margin-top:2.5em;
}
body{
line-height: 1.2;
}

View file

@ -1,48 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>/dev/hack</title>
<title>membership - /dev/hack</title>
<link rel="canonical" href="https://www.devhack.net/membership.html">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="style.css">
<body>
<h1>/dev/hack membership</h1>
<p>/dev/hack is actively seeking members who can support the existence of a
space in our region devoted to our goals in education, creative
projects, and community service. Becoming a member, while not required
to take advantage of /dev/hack services, provides:</p>
<ul>
<li>Around-the-clock key access to the /dev/hack space</li>
<li>The ability to reserve the /dev/hack space and for mission-related events and classes</li>
<li>Voting rights at official organizational meetings</li>
<li>Access to the /dev/hack members-only mailing list</li>
<li>Access to /dev/hack servers for projects</li>
<li>An email adress @devhack.net</li>
<li>An account on /dev/hack shell and VPS server</li>
</ul>
<p>Most importantly, however, supporting /dev/hack as a member enables one
to help build an innovative community technology space and to contribute
to the growing international movement of hackerspaces.</p>
<h3><b>How to become a member</b></h3>
<p>Check us out first. Visit /dev/hack events and classes, and swing by the
space to meet other members and get a feel for the group. All of our
activities are free and open to the public.* Once you have decided you
would like to join:</p>
<ol>
<li><a href="https://buy.stripe.com/14kg0S2aJ9ibbSM6oo">Subscribe for dues ($50/month) via stripe.</a></li>
<li>Attend a monthly member meeting on the second Tuesday of the month
at approximately 7:15PM, so your membership can be formalized.</li>
</ol>
<!-- <p>* Although events are free, sometimes materials costs for workshops
are the responsibility of workshop participants. Further, because of
space limitations, some events are capped at a maximum number of
participants. Events are published <a title="HacDC's events calendar at meetup.com" href="https://www.meetup.com/hac-dc/events/">on our calendar</a>.</p> -->
<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
<stripe-pricing-table pricing-table-id="prctbl_1OqI5NDnrGrK8UDJkbkPIg4E"
publishable-key="pk_live_51N6dipDnrGrK8UDJnT10MmYp6SG6ONE3mmlprqxt1OIYXkVyYRPfSSmn0ShzHxOlvoGZEZfdPt3DKZEL9ZmjJpmW00DkF0Fien">
</stripe-pricing-table>
<h1>/dev/hack membership</h1>
<p>/dev/hack thanks you for your interest in becoming a member.</p>
<p>We are actively seeking members who can support the existence of a
space in our region devoted to our goals in education, creative
projects, and community service. Becoming a member, while not required
to take advantage of /dev/hack services, provides:</p>
<ul>
<li>Around-the-clock key access to the /dev/hack space</li>
<li>The ability to reserve the /dev/hack space and for mission-related events and classes</li>
<li>Voting rights at official organizational meetings</li>
<li>Access to /dev/hack servers for projects</li>
<li>An account on /dev/hack shell and VPS server</li>
<li>And other volunteer-provided <a href="https://wiki.devhack.net/Services">services</a> provided on a <i>best
effort basis</i></li>
<!--
<li>An email adress @devhack.net</li>
<li>Access to the /dev/hack members-only mailing list</li>
-->
</ul>
<p>Most importantly, however, supporting /dev/hack as a member enables one
to help build an innovative community technology space and to contribute
to the growing international movement of hackerspaces.</p>
<h3><b>How to become a member</b></h3>
<p>Check us out first. Visit /dev/hack events and classes, and swing by the
space to meet other members and get a feel for the group. All of our
activities are free and open to the public.</p>
<p>Once you feel that membership is right for you, the
<a href="https://wiki.devhack.net/Becoming_a_Member">Becoming a Member</a> wiki page
describes the process.
</p>
<h3>Managing your membership</h3>
<p>You can update your payment information via <a href="https://members.devhack.net/membership/">the member
portal</a>.
If you would like to cancel your membership, you should also talk to someone to ensure that your accounts are
winded down.
</body>
</html>
</html>

74
more.html Normal file
View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>what is /dev/hack?</title>
<meta name="description"
content="/dev/hack is a hackerspace in seattle's university district, where folks come together to tinker, learn, share ideas, and find community.">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://www.devhack.net/more.html">
<link rel="stylesheet" href="style.css">
<body>
<h1>what is /dev/hack?</h1>
<div class="guysholder">
<p>/dev/hack is a hackerspace in seattle's <a href="https://wiki.devhack.net/University_Way_NE">university
district</a>, where folks come together to tinker, learn, share ideas,
and find community.</p>
<p>/dev/hack also:</p>
<ul>
<li>operates as a
volunteer-run nonprofit and is <a href="membership.html">supported by its membership</a> </li>
<li>shares membership and physical space with <a href="https://seattlecommunitynetwork.org/">local
organizations</a></li>
<li>hosts <a href="https://wiki.devhack.net/Services">space infrastructure</a> and <a
href="https://wiki.devhack.net/Category:Projects">member projects</a> that you can read more
about
</li>
<li>empowers you to contribute towards anything you see -- it's a <span style="white-space: nowrap;">do-ocracy</span></li>
</ul>
<p>so far, this has been /dev/hack:</p>
<div class="grid-container">
<!-- please write alt text for each image! -->
<div class="imgholder">
<img src="pictures/hallway.jpg"
alt="An indoor hallway with a railing, featuring a big /dev/hack sign on the wall.">
</div>
<div class="imgholder">
<img src="pictures/focus_foundry.jpg"
alt="A dimly lit room with coworking desks and pretty fairy lights.">
</div>
<div class="imgholder">
<img src="pictures/dvd_hell.jpg" alt="A tower computer that has 8 DVD drives on the front panel.">
</div>
<div class="imgholder">
<img src="pictures/shibari.jpg"
alt="The shibari PC, tied up with rope and hanging from the ceiling, with a noticeable blue/purple glow.">
</div>
<div class="imgholder">
<img src="pictures/debianwoman.jpg" alt="A diagnostics sign saying 'Woman Problem? Is there text on
the screen?' next to a monitor with the Debian installer. ">
</div>
<div class="imgholder">
<img src="pictures/servers.jpg" alt="A server rack with green lights and a bunch of cables.">
</div>
<div class="imgholder">
<img src="pictures/payphone.jpg" alt="A Nortel Millennium payphone.">
</div>
<div class="imgholder">
<img src="pictures/stoplight.jpg"
alt="A traffic light, but with all the lights on and it's also on our floor.">
</div>
</div>
</div>
<h2 id="acknowledgements">acknowledgements</h2>
<p>
/dev/hack is grateful for the support of <a href="https://seattlecommunitynetwork.org/">Seattle&nbsp;Community&nbsp;Network&#8288;<img
src="vendor/scnBadgeWhite.svg" alt="Seattle Community Network logo" class="footer-logo"></a>,
<a href="https://www.fastly.com" target="_blank" rel="noopener">Fastly&#8288;<img
src="vendor/fastlyLogo-white-SVG.svg" alt="Fastly logo" class="footer-logo"></a>,
and our members for making this place possible.
</p>
</html>

BIN
pictures/debianwoman.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
pictures/dvd_hell.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
pictures/focus_foundry.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
pictures/hallway.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
pictures/payphone.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
pictures/servers.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
pictures/shibari.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
pictures/stoplight.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

76
reboot.html Normal file
View file

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="description" content="devhack needs your help" />
<title>/dev/hack: reboot</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="style.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="devhack-needs-your-help">/dev/hack needs your help!</h1>
<p>Due to <a href="./lore/schism.html">recent events</a> the /dev/hack
hackerspace has run into, we need help re-setting up the space!</p>
<p>Specifically, we need, in order of importance:</p>
<ul>
<li><a href="https://wiki.devhack.net/Giveafuck">giveafuck</a></li>
<li>labor
<ul>
<li>technical labor, with focus on network infrastructure, electrical
wiring</li>
<li>manual labor. Carrying things around, lifting things, constructing
things</li>
</ul></li>
<li><a
href="https://donate.stripe.com/6oE4iaeXv8e7e0UaEG">money</a></li>
<li><strong>specifically approved</strong> hardware, with preference to
lower-power, usability, reliability
<ul>
<li><a href="https://bugs.devhack.net/ticket/955">#955</a></li>
<li><a
href="https://bugs.devhack.net/query?keywords=~shopping&amp;status=!closed&amp;order=changetime&amp;desc=1">shopping
tickets</a></li>
</ul></li>
<li>cars &amp; trucks to help bring things to the space</li>
<li>drafting up &amp; proposing policy
<ul>
<li>especially if you are leftist, anarchist, trans. we want your help
and feedback</li>
<li><a
href="https://bugs.devhack.net/query?component=Policy&amp;status=!closed&amp;order=changetime&amp;desc=1">policy
tickets</a></li>
</ul></li>
</ul>
<hr />
<p><a
href="https://signal.group/#CjQKIHzMq7fKYgL_s_-hmssso3r2EkIfeImJ1kfZJQNmFREvEhBLy6y7HktLGVK76nJgNDc2">signal
group here!</a></p>
<hr />
<p>Stripe donation link is here, feel very free to attach a message
outlining your preference to where your money goes or any sort of
message:</p>
<p><a href="https://donate.stripe.com/6oE4iaeXv8e7e0UaEG"
class="uri">https://donate.stripe.com/6oE4iaeXv8e7e0UaEG</a></p>
</body>
</html>

34
reboot.md Normal file
View file

@ -0,0 +1,34 @@
---
pagetitle: '/dev/hack: reboot'
description-meta: 'devhack needs your help'
---
# /dev/hack needs your help!
Due to [recent events](./lore/schism.html) the /dev/hack hackerspace has run into, we need help re-setting up the space!
Specifically, we need, in order of importance:
- [giveafuck](https://wiki.devhack.net/Giveafuck)
- labor
- technical labor, with focus on network infrastructure, electrical wiring
- manual labor. Carrying things around, lifting things, constructing things
- [money](https://donate.stripe.com/6oE4iaeXv8e7e0UaEG)
- **specifically approved** hardware, with preference to lower-power, usability, reliability
- [#955](https://bugs.devhack.net/ticket/955)
- [shopping tickets](https://bugs.devhack.net/query?keywords=~shopping&status=!closed&order=changetime&desc=1)
- cars & trucks to help bring things to the space
- drafting up & proposing policy
- especially if you are leftist, anarchist, trans. we want your help and feedback
- [policy tickets](https://bugs.devhack.net/query?component=Policy&status=!closed&order=changetime&desc=1)
---
[signal group here!](https://signal.group/#CjQKIHzMq7fKYgL_s_-hmssso3r2EkIfeImJ1kfZJQNmFREvEhBLy6y7HktLGVK76nJgNDc2)
---
Stripe donation link is here, feel very free to attach a message outlining your
preference to where your money goes or any sort of message:
<https://donate.stripe.com/6oE4iaeXv8e7e0UaEG>

55
robots.txt Normal file
View file

@ -0,0 +1,55 @@
# Block all known AI crawlers and assistants
# from using content for training AI models.
# Source: https://robotstxt.com/ai
User-Agent: GPTBot
User-Agent: ClaudeBot
User-Agent: Claude-Web
User-Agent: CCBot
User-Agent: Applebot-Extended
User-Agent: Facebookbot
User-Agent: Meta-ExternalAgent
User-Agent: Meta-ExternalFetcher
User-Agent: diffbot
User-Agent: PerplexityBot
User-Agent: Omgili
User-Agent: Omgilibot
User-Agent: webzio-extended
User-Agent: ImagesiftBot
User-Agent: Bytespider
User-Agent: Amazonbot
User-Agent: Youbot
User-Agent: SemrushBot-OCOB
User-Agent: Petalbot
User-Agent: VelenPublicWebCrawler
User-Agent: TurnitinBot
User-Agent: Timpibot
User-Agent: OAI-SearchBot
User-Agent: ICC-Crawler
User-Agent: AI2Bot
User-Agent: AI2Bot-Dolma
User-Agent: DataForSeoBot
User-Agent: AwarioBot
User-Agent: AwarioSmartBot
User-Agent: AwarioRssBot
User-Agent: Google-Extended
User-Agent: Google-CloudVertexBot
User-Agent: PanguBot
User-Agent: Kangaroo Bot
User-Agent: Sentibot
User-Agent: img2dataset
User-Agent: Meltwater
User-Agent: Seekr
User-Agent: peer39_crawler
User-Agent: cohere-ai
User-Agent: cohere-training-data-crawler
User-Agent: DuckAssistBot
User-Agent: Scrapy
Disallow: /
DisallowAITraining: /
# Block any non-specified AI crawlers (e.g., new
# or unknown bots) from using content for training
# AI models. This directive is still experimental
# and may not be supported by all AI crawlers.
User-Agent: *
DisallowAITraining: /

View file

@ -1,45 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>/dev/hack > seattle</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="style.css">
<body>
<h1>seattle hackery</h1>
<ul>
<li><a href="https://www.blacklodgeresearch.org/">Black Lodge Research</a></li>
<li><a href="https://web.archive.org/web/20201205014142/http://www.hackerbotlabs.com/">Hackerbot Labs</a></li>
<li><a href="https://www.seattleretrocomputing.com/">Seattle Retro-Computing Society</a></li>
<li><a href="https://wsealug.net/">West Seattle Linux Users Group</a></li>
<li><a href="https://www.bsidesseattle.com/">Bsides Seattle</a></li>
<li><a href="https://gslug.org/">Greater Seattle Linux Users Groups</a></li>
<li><a href="http://belug.herber.us/">Bellevue Linux Users Group</a></li>
<li><a href="http://seabug.org/">Seattle BSD Users Group</a></li>
<li><a href="https://www.telcomhistory.org/connections-museum-seattle/">Connections Museum</a></li>
<li><a href="https://livingcomputers.org">Living Computers: Museum</a></li>
<li><a href="https://handmade-seattle.com/">Handmade Seattle</a></li>
<li><a href="https://seattlecommunitynetwork.org/">Seattle Community Network</a></li>
<li><a href="http://dorkbotsea.org/">dorkbot-sea</a></li>
<li><a href="https://www.pspython.com/">Puget Sound Programming Python</a></li>
<!-- <li><a href="https://www.newtechnorthwest.com/">New Tech Northwest</a></li> -->
<li><a href="http://amasci.com/wsci/">Weird Science Salon</a></li>
<li><a href="https://seattle.makerfaire.com/makers-exhibits/">Seattle Mini Maker Faire</a></li>
<li><a href="https://web.archive.org/web/20110208131653/http://www.seattlewireless.net/">Seattle Wireless</a></li>
<!-- <li><a href="http://seattle.beerandcode.org/">Beer && Code</a></li> -->
<li><a href="https://www.meetup.com/Beer-Code-Seattle/">Beer && Code</a></li>
<li><a href="http://refreshseattle.org/">Refresh Seattle</a></li>
<li><a href="https://www.wa2600.org/">Seattle 2600</a></li>
<li><a href="http://passable.art/">Passable</a></li>
<li><a href="http://seattlexcoders.org/">Seattle Xcoders</a></li>
<li><a href="https://toorcamp.toorcon.net/">ToorCamp</a></li>
<li><a href="https://southsoundhacker.space/">Port 22: South Sound Hackers</a></li>
<li><a href="https://dc253.org/">DC253</a></li>
<li><a href="https://seattlematrix.org/">Seattle Matrix</a></li>
<li><a href="https://seagl.org/">SeaGL</a></li>
<li><a href="https://linuxfestnorthwest.org/">LinuxFest Northwest</a></li>
<li><a href="https://hushcon.com/">Hushcon</a></li>
</ul>
</body>
</html>

335
style.css
View file

@ -1,11 +1,14 @@
@import url('vendor/berkeley_mono_transfonter/stylesheet.css');
body {
background: black;
color: lime;
font-family: Menlo, 'Cascadia Code', Consolas, Courier, monospace;
font-family: 'Berkeley Mono', Menlo, 'Cascadia Code', Consolas, Courier, monospace;
line-height: 1.15;
margin: 100px 20% 5% 20%;
border: 10px red;
font-size: 15px;
font-size: 16px;
max-width: 800px;
}
ul {
@ -16,15 +19,29 @@ li {
margin-top: 0.5em;
}
/* Mobile devices get slightly smaller margins, so that we actually have room
* for text.
*/
@media only screen and (max-width: 600px) {
body {
margin: 50px 5% 5% 5%;
}
dl {
margin: 0;
margin-block: 1em;
padding-inline-start: 40px;
}
dd {
margin-bottom: 0.5em;
}
dt {
margin-top: 0.5em;
}
.holder {
width: 60%;
}
[hidden] {
display: none !important;
}
.secondary {
color: #00b300;
}
@ -36,24 +53,58 @@ input[type="text"] {
outline: none;
font: inherit;
caret-shape: block;
width: 100%;
}
h1, .block {
h1,
.block {
margin: 40px 0px;
}
p {
margin: 0.5em 0;
h1 {
animation: headerGlow 4s infinite ease-in-out;
text-shadow: 0 0 5px lime, 0 0 10px lime;
}
a, a:visited {
@keyframes headerGlow {
0% {
opacity: 0.9;
text-shadow: 0 0 3px lime, 0 0 7px lime;
}
50% {
opacity: 1;
text-shadow: 0 0 8px lime, 0 0 10px lime;
}
100% {
opacity: 0.9;
text-shadow: 0 0 3px lime, 0 0 7px lime;
}
}
h2 .small {
display: inline-flex;
a:not(:first-child) {
margin-left: 0.25em;
}
}
p {
margin: 0.5em 0;
}
a,
a:visited {
color: #84d7ba;
text-decoration: none;
}
a:hover {
color: #d784a1;
}
}
dt::before {
content: ">";
@ -64,4 +115,260 @@ dt::before {
font-style: normal;
font-weight: normal;
font-size: 50%;
}
.meow {
margin: 0px 0px !important;
}
.banners {
margin: 40px 0px;
}
img {
image-rendering: pixelated;
width: 85%;
align-content: center;
margin: auto;
display: inline-block;
filter: grayscale(30%);
}
img:hover {
filter: grayscale(0%);
}
.grid-container {
margin: 1em auto;
}
.grid-container {
padding: 10px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
@media (max-width: 600px) {
.grid-container {
grid-template-columns: 1fr;
}
}
.imgholder {
width: 100%;
overflow: hidden;
}
.imgholder img {
width: 100%;
height: auto;
}
.guysholder p {
margin-top: 2em;
}
#news-feed {
position: relative;
max-width: clamp(300px, 100%, 800px);
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
pointer-events: none;
}
#news-feed-gradient {
background: linear-gradient(to left,
rgba(0, 0, 0, 1) 0,
rgba(0, 0, 0, 0.8) 42px,
transparent 100px,
transparent 100%);
}
#news-feed-controls {
display: flex;
flex-direction: row;
align-items: center;
}
#news-feed-right {
cursor: pointer;
pointer-events: all;
margin-left: auto;
width: 42px;
height: 42px;
border: 1px solid lime;
border-radius: 99px;
color: lime;
background-color: oklch(from lime 0.3 c h / 0.7);
transition:
background-color 0.1s ease-in-out,
transform 0.25s ease-in-out;
opacity: 0.7;
&:hover {
opacity: 1;
}
&[data-last="true"] {
transform: rotate(180deg);
}
svg {
vertical-align: middle;
}
}
}
#news-list {
overflow: hidden;
overflow-x: auto;
scrollbar-width: thin;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
display: flex;
flex-direction: row;
gap: 1rem;
list-style: none;
padding: 0;
padding-right: 100px;
/* space for gradient */
margin: 0;
font-size: 0.85em;
.news-item {
scroll-snap-align: start;
display: flex;
flex-direction: column;
overflow: auto;
margin: 0;
padding: 1em;
flex: 1 0 200px;
min-height: 250px;
max-height: 300px;
border: 1px solid oklch(from lime 0.3 c h);
border-radius: 12px;
.news-author {
display: flex;
align-items: center;
gap: 0.5rem;
p {
margin: 0;
}
}
.news-avatar {
border-radius: 6px;
width: 2rem;
height: 2rem;
margin: 0;
object-fit: cover;
}
.news-username {
font-weight: bold;
}
.news-edited {
font-size: 0.75em;
display: inline;
}
.news-body {
flex: 1;
margin-top: 1em;
margin-bottom: 0;
padding-bottom: 1em;
}
.news-thumbnail-link {
display: block;
&:not([href]) {
display: none;
}
}
.news-thumbnail-image {
width: 100%;
margin: 0;
object-fit: cover;
border-radius: 6px;
}
}
}
footer {
margin-top: 5em;
font-size: 0.8rem;
text-align: right;
max-width: 60%;
margin-left: auto;
}
.footer-logo {
height: 1em;
width: auto;
vertical-align: middle;
margin-left: 0.25em;
/* Override rendering for logos */
image-rendering: auto;
}
.error {
border: 1px solid;
padding: .75em 1em;
margin: 1em 0;
border-radius: 10px;
font-size: 0.9em;
max-width: 50%;
}
blockquote {
padding-left: 10px;
border-left: 2px solid;
}
/* Mobile devices get slightly smaller margins, so that we actually have room
* for text.
*/
@media only screen and (max-width: 749px) {
body {
margin: 50px 5% 5% 5%;
}
.holder {
width: 35%;
}
.error {
max-width: 80%;
}
}

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Bold.woff (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Bold.woff2 (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-BoldItalic.woff (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-BoldItalic.woff2 (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Italic.woff (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Italic.woff2 (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Regular.woff (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
vendor/berkeley_mono_transfonter/BerkeleyMono-Regular.woff2 (Stored with Git LFS) vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,279 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, noarchive">
<meta name="format-detection" content="telephone=no">
<title>Transfonter demo</title>
<link href="stylesheet.css" rel="stylesheet">
<style>
/*
http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* demo styles */
body {
background: #f0f0f0;
color: #000;
}
.page {
background: #fff;
width: 920px;
margin: 0 auto;
padding: 20px 20px 0 20px;
overflow: hidden;
}
.font-container {
overflow-x: auto;
overflow-y: hidden;
margin-bottom: 40px;
line-height: 1.3;
white-space: nowrap;
padding-bottom: 5px;
}
h1 {
position: relative;
background: #444;
font-size: 32px;
color: #fff;
padding: 10px 20px;
margin: 0 -20px 12px -20px;
}
.letters {
font-size: 25px;
margin-bottom: 20px;
}
.s10:before {
content: '10px';
}
.s11:before {
content: '11px';
}
.s12:before {
content: '12px';
}
.s14:before {
content: '14px';
}
.s18:before {
content: '18px';
}
.s24:before {
content: '24px';
}
.s30:before {
content: '30px';
}
.s36:before {
content: '36px';
}
.s48:before {
content: '48px';
}
.s60:before {
content: '60px';
}
.s72:before {
content: '72px';
}
.s10:before, .s11:before, .s12:before, .s14:before,
.s18:before, .s24:before, .s30:before, .s36:before,
.s48:before, .s60:before, .s72:before {
font-family: Arial, sans-serif;
font-size: 10px;
font-weight: normal;
font-style: normal;
color: #999;
padding-right: 6px;
}
pre {
display: block;
padding: 9px;
margin: 0 0 12px;
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
font-size: 13px;
line-height: 1.428571429;
color: #333;
font-weight: normal;
font-style: normal;
background-color: #f5f5f5;
border: 1px solid #ccc;
overflow-x: auto;
border-radius: 4px;
}
/* responsive */
@media (max-width: 959px) {
.page {
width: auto;
margin: 0;
}
}
</style>
</head>
<body>
<div class="page">
<div class="demo">
<h1 style="font-family: 'Berkeley Mono'; font-weight: bold; font-style: normal;">Berkeley Mono Bold</h1>
<pre title="Usage">.your-style {
font-family: 'Berkeley Mono';
font-weight: bold;
font-style: normal;
}</pre>
<pre title="Preload (optional)">
&lt;link rel=&quot;preload&quot; href=&quot;BerkeleyMono-Bold.woff2&quot; as=&quot;font&quot; type=&quot;font/woff2&quot; crossorigin&gt;</pre>
<div class="font-container" style="font-family: 'Berkeley Mono'; font-weight: bold; font-style: normal;">
<p class="letters">
abcdefghijklmnopqrstuvwxyz<br>
ABCDEFGHIJKLMNOPQRSTUVWXYZ<br>
0123456789.:,;()*!?'@#&lt;&gt;$%&^+-=~
</p>
<p class="s10" style="font-size: 10px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s11" style="font-size: 11px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s12" style="font-size: 12px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s14" style="font-size: 14px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s18" style="font-size: 18px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s24" style="font-size: 24px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s30" style="font-size: 30px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s36" style="font-size: 36px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s48" style="font-size: 48px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s60" style="font-size: 60px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s72" style="font-size: 72px;">The quick brown fox jumps over the lazy dog.</p>
</div>
</div>
<div class="demo">
<h1 style="font-family: 'Berkeley Mono'; font-weight: normal; font-style: normal;">Berkeley Mono Regular</h1>
<pre title="Usage">.your-style {
font-family: 'Berkeley Mono';
font-weight: normal;
font-style: normal;
}</pre>
<pre title="Preload (optional)">
&lt;link rel=&quot;preload&quot; href=&quot;BerkeleyMono-Regular.woff2&quot; as=&quot;font&quot; type=&quot;font/woff2&quot; crossorigin&gt;</pre>
<div class="font-container" style="font-family: 'Berkeley Mono'; font-weight: normal; font-style: normal;">
<p class="letters">
abcdefghijklmnopqrstuvwxyz<br>
ABCDEFGHIJKLMNOPQRSTUVWXYZ<br>
0123456789.:,;()*!?'@#&lt;&gt;$%&^+-=~
</p>
<p class="s10" style="font-size: 10px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s11" style="font-size: 11px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s12" style="font-size: 12px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s14" style="font-size: 14px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s18" style="font-size: 18px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s24" style="font-size: 24px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s30" style="font-size: 30px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s36" style="font-size: 36px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s48" style="font-size: 48px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s60" style="font-size: 60px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s72" style="font-size: 72px;">The quick brown fox jumps over the lazy dog.</p>
</div>
</div>
<div class="demo">
<h1 style="font-family: 'Berkeley Mono'; font-weight: normal; font-style: italic;">Berkeley Mono Italic</h1>
<pre title="Usage">.your-style {
font-family: 'Berkeley Mono';
font-weight: normal;
font-style: italic;
}</pre>
<pre title="Preload (optional)">
&lt;link rel=&quot;preload&quot; href=&quot;BerkeleyMono-Italic.woff2&quot; as=&quot;font&quot; type=&quot;font/woff2&quot; crossorigin&gt;</pre>
<div class="font-container" style="font-family: 'Berkeley Mono'; font-weight: normal; font-style: italic;">
<p class="letters">
abcdefghijklmnopqrstuvwxyz<br>
ABCDEFGHIJKLMNOPQRSTUVWXYZ<br>
0123456789.:,;()*!?'@#&lt;&gt;$%&^+-=~
</p>
<p class="s10" style="font-size: 10px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s11" style="font-size: 11px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s12" style="font-size: 12px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s14" style="font-size: 14px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s18" style="font-size: 18px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s24" style="font-size: 24px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s30" style="font-size: 30px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s36" style="font-size: 36px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s48" style="font-size: 48px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s60" style="font-size: 60px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s72" style="font-size: 72px;">The quick brown fox jumps over the lazy dog.</p>
</div>
</div>
<div class="demo">
<h1 style="font-family: 'Berkeley Mono'; font-weight: bold; font-style: italic;">Berkeley Mono Bold Italic</h1>
<pre title="Usage">.your-style {
font-family: 'Berkeley Mono';
font-weight: bold;
font-style: italic;
}</pre>
<pre title="Preload (optional)">
&lt;link rel=&quot;preload&quot; href=&quot;BerkeleyMono-BoldItalic.woff2&quot; as=&quot;font&quot; type=&quot;font/woff2&quot; crossorigin&gt;</pre>
<div class="font-container" style="font-family: 'Berkeley Mono'; font-weight: bold; font-style: italic;">
<p class="letters">
abcdefghijklmnopqrstuvwxyz<br>
ABCDEFGHIJKLMNOPQRSTUVWXYZ<br>
0123456789.:,;()*!?'@#&lt;&gt;$%&^+-=~
</p>
<p class="s10" style="font-size: 10px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s11" style="font-size: 11px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s12" style="font-size: 12px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s14" style="font-size: 14px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s18" style="font-size: 18px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s24" style="font-size: 24px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s30" style="font-size: 30px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s36" style="font-size: 36px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s48" style="font-size: 48px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s60" style="font-size: 60px;">The quick brown fox jumps over the lazy dog.</p>
<p class="s72" style="font-size: 72px;">The quick brown fox jumps over the lazy dog.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,40 @@
@font-face {
font-family: 'Berkeley Mono';
src: local('Berkeley Mono Bold'), local('BerkeleyMono-Bold'),
url('BerkeleyMono-Bold.woff2') format('woff2'),
url('BerkeleyMono-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Berkeley Mono';
src: local('Berkeley Mono Regular'), local('BerkeleyMono-Regular'),
url('BerkeleyMono-Regular.woff2') format('woff2'),
url('BerkeleyMono-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Berkeley Mono';
src: local('Berkeley Mono Italic'), local('BerkeleyMono-Italic'),
url('BerkeleyMono-Italic.woff2') format('woff2'),
url('BerkeleyMono-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Berkeley Mono';
src: local('Berkeley Mono Bold Italic'), local('BerkeleyMono-BoldItalic'),
url('BerkeleyMono-BoldItalic.woff2') format('woff2'),
url('BerkeleyMono-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
font-display: swap;
}

1
vendor/fastlyLogo-white-SVG.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg viewBox="0 0 512 198.27" xmlns="http://www.w3.org/2000/svg"><g fill="#fff"><path d="m348.44 20.35v133.59h40.13v-20.41h-13.26v-133.53h-26.87z"/><path d="m0 133.53h13.64v-64.45h-13.64v-17.73l13.64-2.24v-17.94c0-21.74 4.73-31.17 32.45-31.17a115.17 115.17 0 0 1 19.29 2l-3.68 21.85a49.78 49.78 0 0 0 -9-.78c-9.76 0-12.23 1-12.23 10.51v15.53h20.32v20h-20.28v64.45h13.49v20.4h-54z"/><path d="m334.78 127.08a53.11 53.11 0 0 1 -10.54.84c-11.06.27-10.1-3.36-10.1-13.78v-45.06h21v-20h-21v-49.08h-26.87v119.71c0 23.5 5.8 34.23 31.08 34.23 6 0 14.21-1.54 20.42-2.87z"/><path d="m501.7 133.63a10.14 10.14 0 1 1 -10.19 10.14 10.14 10.14 0 0 1 10.19-10.14m0 18.68a8.55 8.55 0 0 0 8.51-8.54 8.5 8.5 0 1 0 -8.51 8.54m1.88-3.56-2.05-3h-1.42v3h-2.29v-10h4.18c2.46 0 4 1.24 4 3.45a3 3 0 0 1 -2.08 3.09l2.49 3.42zm-3.47-5h1.82c1 0 1.74-.4 1.74-1.5s-.7-1.45-1.68-1.45h-1.88z"/><path d="m253.72 69v-3.54a115.8 115.8 0 0 0 -20.58-1.46c-12.5 0-14 6.63-14 10.23 0 5.08 1.74 7.83 15.29 10.79 19.8 4.45 39.69 9.09 39.69 33.64 0 23.29-12 35.32-37.21 35.32-16.88 0-33.26-3.63-45.76-6.8v-20.1h20.35v3.56c8.75 1.69 17.93 1.52 22.73 1.52 13.34 0 15.49-7.17 15.49-11 0-5.29-3.82-7.83-16.32-10.37-23.56-4-42.25-12.07-42.25-36 0-22.65 15.14-31.54 40.37-31.54 17.09 0 30.08 2.65 42.59 5.83v19.92z"/><path d="m127.84 85.09-9.84 8.6a5.25 5.25 0 1 0 3.19 3.2l8.72-9.75z"/><path d="m171.25 127.07v-83.61h-26.88v7.54a55 55 0 0 0 -18.11-6.77v-9.1h3.28v-6.85h-27.06v6.83h3.28v9.17a55.32 55.32 0 1 0 38.76 101.87l4.77 7.78h28.38v-26.86zm-26.64-26.83a28.42 28.42 0 0 1 -26.88 26.76v-3.18h-3.22v3.18a28.43 28.43 0 0 1 -26.68-26.89h3.17v-3.2h-3.15a28.42 28.42 0 0 1 26.66-26.65v3.16h3.22v-3.17a28.42 28.42 0 0 1 26.88 26.75h-3.2v3.22z"/><path d="m456.58 49.11h55.42v20h-13.25l-34 83.62c-9.74 23.48-25.74 45.59-50.1 45.59a93.67 93.67 0 0 1 -19.5-2l2.43-24.39a68.7 68.7 0 0 0 10.63 1.1c11.3 0 24-7 28-19.19l-34.39-84.78h-13.25v-20h55.43v20h-13.22l19.51 48 19.51-48h-13.22z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

49
vendor/polyfill.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3813
vendor/rrule.js vendored Normal file

File diff suppressed because it is too large Load diff

1
vendor/scnBadgeWhite.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 51 KiB