This commit is contained in:
Moheeb Zara
2025-12-05 23:51:51 -07:00
commit 9c89e1883c
50 changed files with 8001 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}
+5
View File
@@ -0,0 +1,5 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
+13
View File
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>governance-site</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+2107
View File
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
{
"name": "governance-site",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"lucide-vue-next": "^0.556.0",
"pinia": "^3.0.4",
"vue": "^3.5.24",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@types/node": "^24.10.1",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"sass": "^1.94.2",
"typescript": "~5.9.3",
"vite": "^7.2.4",
"vue-tsc": "^3.1.6"
}
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+17
View File
@@ -0,0 +1,17 @@
<template>
<AppLayout>
<router-view />
</AppLayout>
</template>
<script setup lang="ts">
import AppLayout from '@/components/layout/AppLayout.vue'
</script>
<style lang="scss">
@import '@/styles/main.scss';
#app {
min-height: 100vh;
}
</style>
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

@@ -0,0 +1,41 @@
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
>create-vue</a
>, the official Vue + Vite starter
</p>
<p>
Learn more about IDE Support for Vue in the
<a
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
target="_blank"
>Vue Docs Scaling up Guide</a
>.
</p>
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
@@ -0,0 +1,73 @@
<template>
<header class="document-header">
<h1 class="document-title">{{ title }}</h1>
<p v-if="description" class="document-description lead">
{{ description }}
</p>
<div v-if="showMeta" class="document-meta">
<span v-if="lastUpdated" class="meta-item">
<Calendar :size="16" />
Last updated: {{ formatDate(lastUpdated) }}
</span>
<span v-if="readingTime" class="meta-item">
<Clock :size="16" />
{{ readingTime }} min read
</span>
</div>
</header>
</template>
<script setup lang="ts">
import { Calendar, Clock } from 'lucide-vue-next'
interface Props {
title: string
description?: string
lastUpdated?: Date
readingTime?: number
showMeta?: boolean
}
withDefaults(defineProps<Props>(), {
showMeta: true
})
const formatDate = (date: Date): string => {
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date)
}
</script>
<style lang="scss" scoped>
.document-header {
margin-bottom: $space-7;
padding-bottom: $space-5;
border-bottom: 2px solid $color-border;
}
.document-title {
margin-bottom: $space-4;
}
.document-description {
margin-bottom: $space-4;
color: $color-text-muted;
}
.document-meta {
display: flex;
flex-wrap: wrap;
gap: $space-4;
font-size: $font-size-sm;
color: $color-text-muted;
}
.meta-item {
display: flex;
align-items: center;
gap: $space-2;
}
</style>
@@ -0,0 +1,103 @@
<template>
<section class="document-section" :id="section.id">
<component :is="headingTag" class="section-title">
{{ section.title }}
</component>
<div class="section-content" v-html="renderedContent"></div>
<div v-if="section.subsections && section.subsections.length > 0" class="subsections">
<DocumentSection
v-for="subsection in section.subsections"
:key="subsection.id"
:section="subsection"
:level="level + 1"
/>
</div>
</section>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { DocumentSection as IDocumentSection } from '@/types'
interface Props {
section: IDocumentSection
level?: number
}
const props = withDefaults(defineProps<Props>(), {
level: 2
})
const headingTag = computed(() => {
const tag = `h${Math.min(props.level, 6)}`
return tag
})
const renderedContent = computed(() => {
// Basic markdown-like rendering
let html = props.section.content
// Convert bold text
html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
// Convert italic text
html = html.replace(/\*(.*?)\*/g, '<em>$1</em>')
// Convert line breaks to paragraphs
html = html.split('\n\n').map(p => `<p>${p}</p>`).join('')
return html
})
</script>
<style lang="scss" scoped>
.document-section {
margin-bottom: $space-6;
&:last-child {
margin-bottom: 0;
}
}
.section-title {
margin-top: $space-6;
margin-bottom: $space-4;
&:first-child {
margin-top: 0;
}
}
.section-content {
:deep(p) {
margin-bottom: $space-4;
&:last-child {
margin-bottom: 0;
}
}
:deep(ul), :deep(ol) {
margin-bottom: $space-4;
padding-left: $space-5;
}
:deep(li) {
margin-bottom: $space-2;
}
:deep(blockquote) {
margin: $space-4 0;
padding-left: $space-4;
border-left: 4px solid $color-border;
color: $color-text-muted;
}
}
.subsections {
margin-top: $space-5;
padding-left: $space-4;
border-left: 2px solid $color-border;
}
</style>
@@ -0,0 +1,181 @@
<template>
<header class="app-header">
<div class="container">
<div class="header-content">
<button
class="menu-toggle lg:d-none"
@click="navigationStore.toggleMenu()"
:aria-label="navigationStore.isMenuOpen ? 'Close menu' : 'Open menu'"
aria-controls="navigation-menu"
>
<Menu v-if="!navigationStore.isMenuOpen" :size="24" />
<X v-else :size="24" />
</button>
<router-link to="/" class="logo-link">
<h1 class="logo">{{ hackerspaceStore.hackerspace.name }}</h1>
</router-link>
<nav class="header-nav d-none lg:d-flex">
<router-link
v-for="item in mainNavItems"
:key="item.id"
:to="item.path"
class="nav-link"
:class="{ active: $route.path === item.path }"
>
{{ item.title }}
</router-link>
</nav>
<div class="header-actions">
<button
class="icon-button"
@click="toggleTheme"
aria-label="Toggle theme"
>
<Sun v-if="isDark" :size="20" />
<Moon v-else :size="20" />
</button>
<button
class="icon-button"
@click="printPage"
aria-label="Print page"
>
<Printer :size="20" />
</button>
</div>
</div>
</div>
</header>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'
import { useNavigationStore } from '@/stores/navigation'
import { useHackerspaceStore } from '@/stores/hackerspace'
import { Menu, X, Sun, Moon, Printer } from 'lucide-vue-next'
const route = useRoute()
const navigationStore = useNavigationStore()
const hackerspaceStore = useHackerspaceStore()
const isDark = ref(false)
const mainNavItems = computed(() =>
navigationStore.navItems.slice(0, 5)
)
const toggleTheme = () => {
isDark.value = !isDark.value
document.documentElement.classList.toggle('dark-theme')
}
const printPage = () => {
window.print()
}
</script>
<style lang="scss" scoped>
.app-header {
position: sticky;
top: 0;
z-index: 100;
background-color: $color-paper;
border-bottom: 1px solid $color-border;
height: $header-height;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
height: $header-height;
gap: $space-4;
}
.menu-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: $radius-md;
transition: background-color $transition-fast;
&:hover {
background-color: $color-paper-light;
}
}
.logo-link {
text-decoration: none;
color: inherit;
&:hover {
text-decoration: none;
}
}
.logo {
font-size: $font-size-lg;
font-weight: 700;
margin: 0;
color: $color-text;
}
.header-nav {
display: flex;
align-items: center;
gap: $space-2;
flex-grow: 1;
justify-content: center;
}
.nav-link {
padding: $space-2 $space-3;
border-radius: $radius-md;
font-size: $font-size-sm;
font-weight: 500;
transition: all $transition-fast;
&:hover {
background-color: $color-paper-light;
text-decoration: none;
}
&.active {
background-color: $color-paper-light;
color: $color-accent;
}
}
.header-actions {
display: flex;
align-items: center;
gap: $space-2;
}
.icon-button {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: $radius-md;
transition: background-color $transition-fast;
color: $color-text-muted;
&:hover {
background-color: $color-paper-light;
color: $color-text;
}
}
@media (max-width: $breakpoint-lg) {
.header-nav {
display: none;
}
}
</style>
@@ -0,0 +1,49 @@
<template>
<div class="app-layout">
<AppHeader />
<AppSidebar />
<main class="app-main">
<div class="main-content">
<slot />
</div>
</main>
</div>
</template>
<script setup lang="ts">
import AppHeader from './AppHeader.vue'
import AppSidebar from './AppSidebar.vue'
</script>
<style lang="scss" scoped>
.app-layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.app-main {
flex: 1;
padding-top: $header-height;
margin-left: 0;
transition: margin-left $transition-base;
@media (min-width: $breakpoint-lg) {
margin-left: $sidebar-width;
}
}
.main-content {
padding: $space-6 $space-4;
max-width: 900px;
margin: 0 auto;
@media (min-width: $breakpoint-md) {
padding: $space-7 $space-5;
}
@media (min-width: $breakpoint-lg) {
padding: $space-8 $space-6;
}
}
</style>
@@ -0,0 +1,114 @@
<template>
<aside
class="app-sidebar"
:class="{ open: navigationStore.isMenuOpen }"
id="navigation-menu"
>
<nav class="sidebar-nav" role="navigation">
<router-link
v-for="item in navigationStore.navItems"
:key="item.id"
:to="item.path"
class="sidebar-link"
:class="{ active: $route.path === item.path }"
@click="navigationStore.closeMenu()"
>
<span class="sidebar-link-text">{{ item.title }}</span>
</router-link>
</nav>
<div class="sidebar-footer">
<p class="text-small text-muted">
Governance in a Box
</p>
<p class="text-xs text-muted">
Adapt for your hackerspace
</p>
</div>
</aside>
<div
v-if="navigationStore.isMenuOpen"
class="sidebar-backdrop lg:d-none"
@click="navigationStore.closeMenu()"
></div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { useNavigationStore } from '@/stores/navigation'
const route = useRoute()
const navigationStore = useNavigationStore()
</script>
<style lang="scss" scoped>
.app-sidebar {
position: fixed;
top: $header-height;
left: 0;
bottom: 0;
width: $sidebar-width;
background-color: $color-paper-light;
border-right: 1px solid $color-border;
transform: translateX(-100%);
transition: transform $transition-base;
z-index: 90;
display: flex;
flex-direction: column;
&.open {
transform: translateX(0);
}
@media (min-width: $breakpoint-lg) {
transform: translateX(0);
}
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: $space-4;
}
.sidebar-link {
display: block;
padding: $space-3 $space-4;
margin-bottom: $space-2;
border-radius: $radius-md;
font-size: $font-size-sm;
color: $color-text;
transition: all $transition-fast;
&:hover {
background-color: $color-paper;
text-decoration: none;
}
&.active {
background-color: $color-paper;
color: $color-accent;
font-weight: 600;
}
}
.sidebar-link-text {
display: block;
}
.sidebar-footer {
padding: $space-4;
border-top: 1px solid $color-border;
}
.sidebar-backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 80;
}
</style>
@@ -0,0 +1,103 @@
<template>
<div class="callout-box" :class="[`callout-${type}`]">
<div class="callout-icon">
<component :is="iconComponent" :size="20" />
</div>
<div class="callout-content">
<h4 v-if="title" class="callout-title">{{ title }}</h4>
<slot />
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Info, AlertTriangle, CheckCircle, XCircle, Lightbulb } from 'lucide-vue-next'
interface Props {
type?: 'info' | 'warning' | 'success' | 'error' | 'tip'
title?: string
}
const props = withDefaults(defineProps<Props>(), {
type: 'info'
})
const iconComponent = computed(() => {
const icons = {
info: Info,
warning: AlertTriangle,
success: CheckCircle,
error: XCircle,
tip: Lightbulb
}
return icons[props.type]
})
</script>
<style lang="scss" scoped>
.callout-box {
display: flex;
gap: $space-3;
padding: $space-4;
margin: $space-5 0;
border-radius: $radius-md;
border-left: 4px solid;
&.callout-info {
background-color: rgba($color-accent, 0.05);
border-color: $color-accent;
color: darken($color-accent, 10%);
}
&.callout-warning {
background-color: rgba($color-warning, 0.05);
border-color: $color-warning;
color: darken($color-warning, 10%);
}
&.callout-success {
background-color: rgba($color-success, 0.05);
border-color: $color-success;
color: darken($color-success, 10%);
}
&.callout-error {
background-color: rgba($color-error, 0.05);
border-color: $color-error;
color: darken($color-error, 10%);
}
&.callout-tip {
background-color: $color-paper-light;
border-color: $color-text-muted;
color: $color-text;
}
}
.callout-icon {
flex-shrink: 0;
display: flex;
align-items: flex-start;
padding-top: 2px;
}
.callout-content {
flex: 1;
color: $color-text;
:deep(p) {
margin-bottom: $space-2;
&:last-child {
margin-bottom: 0;
}
}
}
.callout-title {
margin-bottom: $space-2;
font-size: $font-size-md;
font-weight: 600;
}
</style>
+12
View File
@@ -0,0 +1,12 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.mount('#app')
+453
View File
@@ -0,0 +1,453 @@
<template>
<div class="adapt-this-page">
<DocumentHeader
title="Adapt This for Your Hackerspace"
description="How to customize this governance framework for your own community."
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="tip" title="License">
<p>
This entire framework is released under Creative Commons BY-SA 4.0.
You're free to use, modify, and share it. We only ask that you share
your improvements back to the community.
</p>
</CalloutBox>
<section id="quick-start">
<h2>Quick Start Guide</h2>
<div class="step-list">
<div class="step-card">
<h3>Step 1: Download Everything</h3>
<p>Get all the documents and source code:</p>
<ul>
<li>Download the complete package from Resources</li>
<li>Clone the GitHub repository</li>
<li>Fork for your own modifications</li>
</ul>
</div>
<div class="step-card">
<h3>Step 2: Find & Replace Basics</h3>
<p>Global replacements to make:</p>
<ul>
<li>"HeatSync Labs" → Your hackerspace name</li>
<li>"Mesa, Arizona" → Your location</li>
<li>"heatsynclabs.org" → Your domain</li>
<li>Contact emails → Your addresses</li>
</ul>
</div>
<div class="step-card">
<h3>Step 3: Customize Key Numbers</h3>
<p>Adjust these to match your needs:</p>
<ul>
<li>Membership dues amounts</li>
<li>Spending authority limits</li>
<li>Meeting schedules</li>
<li>Proposal timelines (we use 9-14 days)</li>
<li>Board size and structure</li>
</ul>
</div>
<div class="step-card">
<h3>Step 4: Legal Alignment</h3>
<p>Match your local requirements:</p>
<ul>
<li>State/country nonprofit laws</li>
<li>Required officer positions</li>
<li>Tax-exempt requirements</li>
<li>Insurance minimums</li>
<li>Liability considerations</li>
</ul>
</div>
</div>
</section>
<section id="what-to-keep">
<h2>What to Keep vs What to Change</h2>
<div class="comparison-grid">
<div class="keep-card">
<h3>Keep These Core Elements</h3>
<ul>
<li><strong>Do-ocracy principles</strong> - They work universally</li>
<li><strong>Conflict resolution process</strong> - Time-tested approach</li>
<li><strong>Decision framework</strong> - Clear paths for action</li>
<li><strong>Board limitations</strong> - Prevents power accumulation</li>
<li><strong>Documentation culture</strong> - Essential for continuity</li>
<li><strong>"Be excellent"</strong> - Simple, effective principle</li>
</ul>
</div>
<div class="change-card">
<h3>Customize These Elements</h3>
<ul>
<li><strong>Membership tiers</strong> - Match your economics</li>
<li><strong>Officer roles</strong> - Per legal requirements</li>
<li><strong>Meeting frequency</strong> - Based on activity level</li>
<li><strong>Tool policies</strong> - Depends on equipment</li>
<li><strong>Space-specific rules</strong> - Your layout matters</li>
<li><strong>Cultural references</strong> - Make it yours</li>
</ul>
</div>
</div>
</section>
<section id="cultural-adaptation">
<h2>Cultural Adaptation</h2>
<p>
Every hackerspace has its own culture. Here's how to preserve yours
while adopting this framework:
</p>
<h3>Language and Tone</h3>
<ul>
<li>Adjust formality level to match your community</li>
<li>Translate to your primary language(s)</li>
<li>Use local idioms and references</li>
<li>Match your existing communication style</li>
</ul>
<h3>Values Emphasis</h3>
<ul>
<li>Highlight what matters most to your community</li>
<li>Add sections for unique priorities</li>
<li>Adjust the balance between structure and flexibility</li>
<li>Include your origin story and mission</li>
</ul>
<h3>Community Norms</h3>
<ul>
<li>Incorporate existing unwritten rules</li>
<li>Respect established traditions</li>
<li>Acknowledge founding members' contributions</li>
<li>Build on what already works</li>
</ul>
</section>
<section id="technical-setup">
<h2>Technical Setup</h2>
<h3>Website Deployment</h3>
<p>To deploy your own version of this site:</p>
<pre><code>1. Clone the repository:
git clone https://github.com/yourusername/governance-site
cd governance-site
2. Install dependencies:
npm install
3. Customize content:
- Edit pages in src/pages/
- Update store in src/stores/hackerspace.ts
- Modify styles in src/styles/
4. Build for production:
npm run build
5. Deploy to your host:
- Static hosting (Netlify, Vercel, GitHub Pages)
- Your own server (nginx, Apache)
- CDN (CloudFlare Pages)</code></pre>
<h3>Alternative Formats</h3>
<ul>
<li><strong>Wiki:</strong> Convert markdown to MediaWiki format</li>
<li><strong>Google Docs:</strong> Import and share with comments enabled</li>
<li><strong>PDF:</strong> Print from browser or use pandoc</li>
<li><strong>Physical:</strong> Print and bind for the space</li>
</ul>
</section>
<section id="common-modifications">
<h2>Common Modifications</h2>
<h3>For Smaller Spaces (under 20 members)</h3>
<ul>
<li>Simplify board to 3 positions</li>
<li>Combine roles (Champion/Secretary)</li>
<li>Reduce meeting frequency to quarterly</li>
<li>Lower quorum requirements</li>
<li>Informal documentation acceptable</li>
</ul>
<h3>For Larger Spaces (100+ members)</h3>
<ul>
<li>Add committee structure</li>
<li>Implement area captains</li>
<li>Create member tiers</li>
<li>Formalize training programs</li>
<li>Add staff positions</li>
</ul>
<h3>For Non-US Spaces</h3>
<ul>
<li>Replace 501(c)(3) with local equivalent</li>
<li>Adjust to local nonprofit law</li>
<li>Convert measurements and currency</li>
<li>Update legal references</li>
<li>Consider language translations</li>
</ul>
</section>
<section id="implementation">
<h2>Implementation Strategy</h2>
<h3>For New Hackerspaces</h3>
<ol>
<li>Use this as your starting framework</li>
<li>Customize before opening</li>
<li>Get founding member buy-in</li>
<li>File legal paperwork with adapted bylaws</li>
<li>Iterate based on early experience</li>
</ol>
<h3>For Existing Hackerspaces</h3>
<ol>
<li>Compare with current governance</li>
<li>Identify gaps and improvements</li>
<li>Propose changes gradually</li>
<li>Get member feedback</li>
<li>Vote on adoption at meeting</li>
<li>Phase in over time</li>
</ol>
<CalloutBox type="warning">
<p>
<strong>Don't break what works!</strong> If your current system is
functioning, cherry-pick improvements rather than wholesale replacement.
</p>
</CalloutBox>
</section>
<section id="share-back">
<h2>Share Your Improvements</h2>
<p>
The hackerspace community thrives on sharing. When you adapt this framework:
</p>
<ul>
<li><strong>Document your changes</strong> - Others can learn from them</li>
<li><strong>Share your templates</strong> - Upload to the community repo</li>
<li><strong>Report what worked</strong> - Success stories help others</li>
<li><strong>Share what didn't</strong> - Failures are valuable too</li>
<li><strong>Contribute translations</strong> - Help non-English spaces</li>
</ul>
<h3>How to Contribute</h3>
<ul>
<li>Submit pull requests to the main repository</li>
<li>Share in hackerspace forums</li>
<li>Present at hackerspace conferences</li>
<li>Write blog posts about your experience</li>
<li>Add to hackerspace.org wiki</li>
</ul>
</section>
<section id="help">
<h2>Getting Help</h2>
<p>
Adapting governance can be challenging. Here's where to get help:
</p>
<h3>Community Resources</h3>
<ul>
<li><strong>Hackerspace Forums:</strong> discuss.hackerspaces.org</li>
<li><strong>Slack/Discord:</strong> Join hackerspace channels</li>
<li><strong>Regional Networks:</strong> Connect with nearby spaces</li>
<li><strong>Conferences:</strong> Meet others who've done this</li>
</ul>
<h3>Direct Support</h3>
<ul>
<li><strong>Email us:</strong> governance@heatsynclabs.org</li>
<li><strong>Video call:</strong> Schedule a consultation</li>
<li><strong>Visit:</strong> Come see how we do things</li>
<li><strong>Mentorship:</strong> We'll pair you with an experienced space</li>
</ul>
</section>
<section id="checklist">
<h2>Final Checklist</h2>
<p>Before launching with your adapted framework:</p>
<div class="checklist">
<label><input type="checkbox"> All names and locations updated</label>
<label><input type="checkbox"> Legal requirements verified</label>
<label><input type="checkbox"> Financial amounts appropriate</label>
<label><input type="checkbox"> Contact information current</label>
<label><input type="checkbox"> Processes match your culture</label>
<label><input type="checkbox"> Members have reviewed drafts</label>
<label><input type="checkbox"> Legal counsel consulted if needed</label>
<label><input type="checkbox"> Documentation accessible to all</label>
<label><input type="checkbox"> Training plan for rollout</label>
<label><input type="checkbox"> Feedback mechanism in place</label>
</div>
</section>
<CalloutBox type="tip">
<p>
<strong>Remember:</strong> Perfect is the enemy of done. Start with
something workable and improve it over time. Your governance will
evolve with your community.
</p>
</CalloutBox>
<section id="acknowledgments">
<h2>Acknowledgments</h2>
<p>
This framework builds on the work of hundreds of hackerspaces worldwide.
Special thanks to:
</p>
<ul>
<li>Mitch Altman and the hackerspace founders</li>
<li>Hackerspace Gent for the Blueprint</li>
<li>Noisebridge for radical inclusion</li>
<li>Pumping Station: One for governance innovation</li>
<li>All spaces that shared their documents openly</li>
<li>The entire hackerspace community</li>
</ul>
<p class="text-center mt-7">
<strong>Now go forth and make things!</strong>
</p>
</section>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.adapt-this-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
.step-list {
display: grid;
gap: $space-4;
margin: $space-5 0;
.step-card {
padding: $space-4;
background-color: $color-paper-light;
border-left: 4px solid $color-accent;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-3;
}
p {
margin-bottom: $space-3;
font-style: italic;
}
ul {
font-size: $font-size-sm;
}
}
}
.comparison-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: $space-4;
margin: $space-5 0;
@media (max-width: $breakpoint-md) {
grid-template-columns: 1fr;
}
.keep-card, .change-card {
padding: $space-4;
border-radius: $radius-md;
h3 {
margin-bottom: $space-3;
}
ul {
font-size: $font-size-sm;
}
}
.keep-card {
background-color: rgba($color-success, 0.05);
border: 2px solid $color-success;
h3 {
color: $color-success;
}
}
.change-card {
background-color: rgba($color-warning, 0.05);
border: 2px solid $color-warning;
h3 {
color: $color-warning;
}
}
}
pre {
background-color: $color-paper-light;
padding: $space-4;
border-radius: $radius-md;
overflow-x: auto;
font-size: $font-size-sm;
code {
background: transparent;
padding: 0;
}
}
.checklist {
display: flex;
flex-direction: column;
gap: $space-3;
margin: $space-4 0;
padding: $space-4;
background-color: $color-paper-light;
border-radius: $radius-md;
label {
display: flex;
align-items: center;
gap: $space-2;
cursor: pointer;
font-size: $font-size-sm;
input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
}
}
}
.text-center {
text-align: center;
}
.mt-7 {
margin-top: $space-7;
}
}</style>
+286
View File
@@ -0,0 +1,286 @@
<template>
<div class="board-page">
<DocumentHeader
title="The Board of Directors"
description="Infrastructure maintainers and conflict resolvers - not leaders. The board exists to handle what members can't do individually."
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="info" title="Key Principle">
<p>
<strong>Board members are wardens, not rulers.</strong> They maintain the infrastructure,
handle legal requirements, and resolve conflicts the community can't handle directly.
They should be indistinguishable from normal members in day-to-day operations.
</p>
</CalloutBox>
<section id="legal-reality">
<h2>Legal Requirements vs Actual Roles</h2>
<p>
Arizona law requires certain corporate officer positions for our 501(c)(3) status.
Here's how we map legal requirements to our actual flat hierarchy:
</p>
<table>
<thead>
<tr>
<th>Legal Title (On Paper)</th>
<th>Actual Role at HeatSync</th>
<th>Real Responsibilities</th>
</tr>
</thead>
<tbody>
<tr>
<td>President</td>
<td>Champion</td>
<td>Coordination between offices, membership support, bylaw enforcement</td>
</tr>
<tr>
<td>Vice President</td>
<td>Co-Champion</td>
<td>Shares Champion duties, provides backup and balance</td>
</tr>
<tr>
<td>Treasurer</td>
<td>Treasurer</td>
<td>Financial management, dues collection, budget oversight</td>
</tr>
<tr>
<td>Secretary</td>
<td>Secretary</td>
<td>Meeting records, documentation, official correspondence</td>
</tr>
</tbody>
</table>
<p class="text-muted mt-4">
<em>Note: We use functional titles internally but file legal paperwork with
traditional titles to meet state requirements.</em>
</p>
</section>
<section id="board-offices">
<h2>Board Offices</h2>
<h3>Champion (1-2 officers)</h3>
<p>The Champion coordinates between board offices and assists members. Responsibilities:</p>
<ul>
<li>Coordinate tasks between board offices</li>
<li>Assist members with membership-related tasks</li>
<li>Ensure bylaws are followed (not enforce with an iron fist)</li>
<li>Be the "face" of the board when needed for external relations</li>
<li>Call and facilitate board meetings</li>
</ul>
<p class="text-small text-muted">
Maximum 2 officers. Each gets a full vote. If two Champions, they should
coordinate to avoid duplication.
</p>
<h3>Treasurer (1-2 officers)</h3>
<p>The Treasurer manages finances and ensures bills get paid. Responsibilities:</p>
<ul>
<li>Manage bank accounts and financial assets</li>
<li>Collect membership dues and donations</li>
<li>Pay bills and manage expenses</li>
<li>Provide monthly financial reports</li>
<li>File required tax documents</li>
<li>Manage reimbursements for do-ocracy projects</li>
</ul>
<p class="text-small text-muted">
Maximum 2 officers. Dual signatures required for expenses over $50.
</p>
<h3>Secretary (1 officer)</h3>
<p>The Secretary documents what happens. Responsibilities:</p>
<ul>
<li>Record meeting minutes (board and membership meetings)</li>
<li>Maintain official records and documents</li>
<li>Handle official correspondence</li>
<li>Manage membership roster</li>
<li>Post public notices as required</li>
<li>Maintain corporate records for legal compliance</li>
</ul>
<h3>Operations (1+ officers)</h3>
<p>Operations keeps the space running. Responsibilities:</p>
<ul>
<li>Coordinate space maintenance and improvements</li>
<li>Delegate operational tasks to volunteers</li>
<li>Ensure safety procedures are followed</li>
<li>Manage relationships with landlord</li>
<li>Coordinate tool maintenance and certification</li>
</ul>
<p class="text-small text-muted">
No maximum. Can create committees for specific operational areas.
</p>
</section>
<section id="limitations">
<h2>What the Board CANNOT Do</h2>
<CalloutBox type="warning">
<p>The board's power is intentionally limited to prevent power accumulation:</p>
</CalloutBox>
<ul>
<li><strong>Cannot control space direction:</strong> Members decide what HeatSync becomes</li>
<li><strong>Cannot override do-ocracy:</strong> If someone's doing the work, they make decisions</li>
<li><strong>Cannot act unilaterally:</strong> Major decisions need member input</li>
<li><strong>Cannot self-perpetuate:</strong> All positions are elected annually</li>
<li><strong>Cannot hide proceedings:</strong> All meetings are open except sensitive legal/personnel matters</li>
</ul>
</section>
<section id="elections">
<h2>Elections and Terms</h2>
<h3>Regular Elections</h3>
<ul>
<li>Held at first membership meeting in October</li>
<li>One-year terms for all positions</li>
<li>No term limits - officers can serve multiple terms</li>
<li>Candidates must be dues-paying members in good standing</li>
<li>Majority vote of present members wins</li>
</ul>
<h3>Interim Officers</h3>
<p>If an officer leaves mid-term:</p>
<ol>
<li>Board appoints interim replacement at next board meeting</li>
<li>Interim serves remainder of original term</li>
<li>If board can't agree, special election within 60 days</li>
</ol>
<h3>Removal from Office</h3>
<p>An officer can be removed by:</p>
<ul>
<li>Unanimous vote of other board members, OR</li>
<li>Majority vote of all dues-paying members</li>
<li>Missing 2 board meetings without 24-hour notice</li>
</ul>
</section>
<section id="operations">
<h2>How the Board Operates</h2>
<h3>Meetings</h3>
<ul>
<li><strong>Frequency:</strong> At least quarterly</li>
<li><strong>Annual Meeting:</strong> First member meeting in April</li>
<li><strong>Quorum:</strong> 2/3 of elected officers</li>
<li><strong>Openness:</strong> All members can observe (except executive session)</li>
<li><strong>Minutes:</strong> Posted publicly within 7 days</li>
</ul>
<h3>Decision Making</h3>
<ul>
<li>Consensus preferred, majority vote when needed</li>
<li>Each officer gets one vote (even if sharing an office)</li>
<li>Purchases over $50 need board approval</li>
<li>All expenditures need 2 board signatures</li>
</ul>
<h3>Committees</h3>
<p>
Any board office can create committees for their area. For example:
</p>
<ul>
<li>Operations might create a Safety Committee</li>
<li>Treasurer might create a Fundraising Committee</li>
<li>Champion might create a Membership Committee</li>
</ul>
<p>
Committees are advisory and report to their creating office.
</p>
</section>
<section id="conflict-resolution">
<h2>Board as Conflict Resolvers</h2>
<p>
When the do-ocracy can't resolve something, the board steps in as mediators:
</p>
<h3>The Process</h3>
<ol>
<li><strong>Private Talk:</strong> Board member talks privately with each party</li>
<li><strong>Mediation:</strong> Bring parties together to find resolution</li>
<li><strong>Decision if Needed:</strong> Board decides if mediation fails</li>
<li><strong>Temporary Measures:</strong> Can restrict access if safety is at risk</li>
<li><strong>Community Communication:</strong> Inform members appropriately</li>
</ol>
<h3>Principles</h3>
<ul>
<li>Protect the space's ability to function</li>
<li>Be transparent about interventions</li>
<li>Focus on resolution, not punishment</li>
<li>Document decisions for consistency</li>
</ul>
</section>
<section id="accountability">
<h2>Board Accountability</h2>
<p>
The board is accountable to members through:
</p>
<ul>
<li><strong>Open Meetings:</strong> Members can observe and speak</li>
<li><strong>Posted Minutes:</strong> All decisions are documented</li>
<li><strong>Financial Reports:</strong> Monthly treasurer reports</li>
<li><strong>Annual Elections:</strong> Members choose who serves</li>
<li><strong>Removal Process:</strong> Members can remove officers</li>
<li><strong>Limited Authority:</strong> Can't override member initiatives</li>
</ul>
<CalloutBox type="tip">
<p>
<strong>Remember:</strong> Board members should be contributing members first,
officers second. The best board members are barely distinguishable from
active members except when their specific duties are needed.
</p>
</CalloutBox>
</section>
<section id="current-board">
<h2>Current Board</h2>
<p>
See the wiki or bulletin board for current board members and contact information.
Board emails:
</p>
<ul>
<li><strong>All board members:</strong> board@heatsynclabs.org</li>
<li><strong>Champions:</strong> champion@heatsynclabs.org</li>
<li><strong>Treasurer:</strong> treasurer@heatsynclabs.org</li>
<li><strong>Secretary:</strong> secretary@heatsynclabs.org</li>
<li><strong>Operations:</strong> operations@heatsynclabs.org</li>
</ul>
</section>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.board-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
h3 {
margin-top: $space-5;
color: $color-accent;
}
table {
margin: $space-5 0;
}
}</style>
+309
View File
@@ -0,0 +1,309 @@
<template>
<div class="bylaws-page">
<DocumentHeader
title="Bylaws of HeatSync Labs"
description="The legal foundation for our 501(c)(3) nonprofit hackerspace, designed to meet legal requirements while maximizing member autonomy through do-ocracy principles."
:last-updated="new Date('2024-12-05')"
/>
<section id="article-1">
<h2>Article I: Name, Purpose, and Status</h2>
<h3>Section 1.1: Name</h3>
<p>
The name of the organization shall be HeatSync Labs, Inc., doing business as
HeatSync Labs (hereinafter, the "Corporation").
</p>
<h3>Section 1.2: Purpose</h3>
<p>
The Corporation is organized exclusively for charitable, educational, and
scientific purposes within the meaning of Section 501(c)(3) of the Internal
Revenue Code. Its mission is to:
</p>
<ul>
<li>Provide a collaborative physical workspace, tools, and resources for making,
learning, exploring, and sharing technology and creative projects.</li>
<li>Promote education in technology, science, art, and craftsmanship through
workshops, classes, and public outreach.</li>
<li>Foster a community of innovation and shared knowledge, operating on the
principles of open access, inclusivity, and <strong>do-ocracy</strong>.</li>
</ul>
<h3>Section 1.3: 501(c)(3) Status</h3>
<p>
The Corporation shall operate exclusively for its stated charitable purposes.
No part of its net earnings shall benefit any private shareholder or individual.
The Corporation shall not engage in substantial lobbying or any political
campaign activities.
</p>
</section>
<section id="article-2">
<h2>Article II: Membership</h2>
<h3>Section 2.1: Eligibility</h3>
<p>
Membership is open to any individual who supports the Corporation's mission,
agrees to abide by its Code of Conduct and Safety Policies, and pays the
established dues (if any). The Corporation shall not discriminate on any
unlawful basis.
</p>
<h3>Section 2.2: Classes of Membership</h3>
<p>The Corporation shall have <strong>Voting Members</strong>.</p>
<ul>
<li><strong>Voting Member:</strong> An individual who has completed an orientation,
is in good standing (current on dues, if applicable, and adherence to policies),
and has actively contributed to the space's maintenance or projects within the
last 6 months. Contribution is self-documented and recognized (see Do-ocracy,
Article VI).</li>
</ul>
<h3>Section 2.3: Rights of Voting Members</h3>
<p>
Each Voting Member shall have one vote on matters put before the membership,
including the election of the Board of Directors and amendments to these Bylaws.
</p>
<h3>Section 2.4: Termination</h3>
<p>
Membership may be terminated for cause, including non-payment of dues or
violation of the Code of Conduct, upon fair review as defined in the
Corporation's policies.
</p>
</section>
<section id="article-3">
<h2>Article III: Board of Directors</h2>
<h3>Section 3.1: Role and Powers</h3>
<p>
The Board of Directors ("Board") is responsible for the legal, financial, and
fiduciary oversight of the Corporation. It shall ensure compliance with all laws
and the 501(c)(3) mission. The Board shall adopt policies but shall <strong>empower
the membership and do-ocracy model</strong> for daily operations and project execution.
</p>
<h3>Section 3.2: Composition</h3>
<ul>
<li>The Board shall consist of no fewer than three (3) and no more than seven (7) Directors.</li>
<li>At least one-third of the Board must be elected from and by the Voting Membership.</li>
<li>The remainder may be elected from the membership or appointed for specific expertise
(legal, financial, etc.).</li>
</ul>
<h3>Section 3.3: Election & Terms</h3>
<p>
Elected Directors shall serve staggered terms of two (2) years. Elections shall
be held annually at the Membership Meeting. A Director may serve no more than
four consecutive terms.
</p>
<h3>Section 3.4: Officers</h3>
<p>
The Board shall elect from its members a Chair, Secretary, and Treasurer.
Officers shall have duties as prescribed by the Board and consistent with state law.
</p>
<h3>Section 3.5: Meetings</h3>
<p>
The Board shall meet at least quarterly. Meetings shall be open for observation
by any Voting Member, except during executive sessions for sensitive matters
(personnel, legal).
</p>
</section>
<section id="article-4">
<h2>Article IV: Membership Meetings</h2>
<h3>Section 4.1: Annual Meeting</h3>
<p>
An Annual Membership Meeting shall be held for electing Directors, presenting
annual reports, and addressing major strategic issues.
</p>
<h3>Section 4.2: Special Meetings</h3>
<p>
Special Meetings may be called by the Board or by a petition of at least 20%
of Voting Members.
</p>
<h3>Section 4.3: Quorum & Decision Making</h3>
<p>
For annual meetings, a quorum shall be 20% of Voting Members. For special meetings,
30%. Whenever possible, the Corporation shall operate by <strong>consensus</strong>.
When a vote is required, a simple majority of members present shall decide, except
for Bylaws amendments (see Article VIII).
</p>
</section>
<section id="article-5">
<h2>Article V: Committees</h2>
<h3>Section 5.1: Standing Committees</h3>
<p>
The Board may establish Standing Committees for ongoing functions (Finance, Safety).
Committee chairs shall report to the Board.
</p>
<h3>Section 5.2: Do-ocracy Working Groups</h3>
<p>
These are <strong>self-forming, project-oriented groups</strong> established by
members under the principles of Article VI. They are not committees of the Board
and operate autonomously within the scope of approved budgets and space policies.
They must report their activities and use of resources to the membership via a
public log/wiki.
</p>
</section>
<section id="article-6">
<h2>Article VI: Principle of Do-ocracy</h2>
<CalloutBox type="tip" title="Core Principle">
<p>
A "do-ocracy" is an organizational structure in which individuals have the
authority and responsibility to self-initiate and execute projects, tasks,
and improvements for the Corporation. <strong>The authority to make a decision
and take action lies with those who do the work.</strong>
</p>
</CalloutBox>
<h3>Section 6.1: Definition</h3>
<p>
A "do-ocracy" is an organizational structure in which individuals have the
authority and responsibility to self-initiate and execute projects, tasks, and
improvements for the Corporation. <strong>The authority to make a decision and
take action lies with those who do the work.</strong>
</p>
<h3>Section 6.2: Scope</h3>
<h4>Empowered Actions:</h4>
<p>Members are empowered to:</p>
<ul>
<li>Fix broken equipment</li>
<li>Organize workshops</li>
<li>Improve infrastructure</li>
<li>Create art for the space</li>
<li>Develop software tools</li>
<li>Manage day-to-day operations within established safety and financial guidelines</li>
</ul>
<h4>Limitations:</h4>
<p>Do-ocracy does not authorize actions that:</p>
<ul>
<li>Violate law or the Code of Conduct</li>
<li>Create significant legal/financial risk</li>
<li>Commit the Corporation to major contracts</li>
<li>Spend beyond a pre-set budget cap for autonomous projects ($200)</li>
<li>Alter core governance</li>
</ul>
<h3>Section 6.3: Process & Accountability</h3>
<ol>
<li><strong>Proposal & Notification:</strong> A member wishing to undertake a
significant action shall document their intent (via wiki, mailing list, or
physical board) to allow for feedback.</li>
<li><strong>Seeking Feedback:</strong> The proposing member shall actively seek
feedback, especially from those affected. <strong>Constructive objection must
be addressed.</strong></li>
<li><strong>Execution:</strong> If no unresolvable objection is raised within
<strong>9-14 days</strong>, the member may proceed, using resources responsibly.</li>
<li><strong>Documentation:</strong> All actions must be documented (what was done,
cost, who did it).</li>
</ol>
<h3>Section 6.4: Conflict Resolution</h3>
<p>
Disputes arising from do-ocratic actions shall first be addressed through direct,
respectful dialogue. Unresolved disputes shall be mediated per the Corporation's
Conflict Resolution Policy, ultimately appealable to the Board.
</p>
</section>
<section id="article-7">
<h2>Article VII: Finances</h2>
<h3>Section 7.1: Fiscal Year</h3>
<p>The fiscal year shall be January 1 to December 31.</p>
<h3>Section 7.2: Budget</h3>
<p>
The Board, with input from the membership, shall approve an annual budget.
The budget shall include a <strong>Do-ocracy Project Fund</strong> to be
allocated by members for small, autonomous projects.
</p>
<h3>Section 7.3: Disbursements</h3>
<p>
Disbursements under the Do-ocracy Project Fund cap may be reimbursed upon
presentation of receipts and documentation. Larger expenditures require prior
approval per the Financial Policy.
</p>
<h3>Section 7.4: Financial Review</h3>
<p>
The Board shall ensure an annual financial review or audit as required by law
or best practices.
</p>
</section>
<section id="article-8">
<h2>Article VIII: Amendments</h2>
<p>
These Bylaws may be amended by a <strong>two-thirds (2/3) supermajority vote</strong>
of the Voting Members present at a duly called Membership Meeting, provided written
notice of the proposed amendment has been provided to all members at least
<strong>14 days</strong> in advance.
</p>
</section>
<section id="article-9">
<h2>Article IX: Dissolution</h2>
<p>
Upon dissolution of the Corporation, after paying all debts and obligations, its
remaining assets shall be distributed to one or more 501(c)(3) organizations with
a similar mission, as determined by the Board. No assets shall be distributed to
any member, director, or officer.
</p>
</section>
<div class="signature-block mt-8">
<p><strong>Adopted on:</strong> _______________</p>
<p><strong>Secretary:</strong> _________________________</p>
<p class="text-small text-muted">(Printed Name & Signature)</p>
</div>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.bylaws-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
h3 {
margin-top: $space-5;
margin-bottom: $space-3;
}
h4 {
margin-top: $space-4;
margin-bottom: $space-2;
}
.signature-block {
padding: $space-5;
background-color: $color-paper-light;
border-radius: $radius-md;
page-break-inside: avoid;
}
}</style>
@@ -0,0 +1,319 @@
<template>
<div class="community-standards-page">
<DocumentHeader
title="Community Standards & Accountability Process"
description="HeatSync Labs exists so people can make things. These standards protect that mission by ensuring everyone can participate safely."
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="info">
<p>
<strong>We're a do-ocracy:</strong> if you see a problem, you can address it.
But some problems need backup. This document tells you when to act, when to
escalate, and what happens next.
</p>
</CalloutBox>
<section id="core-principle">
<h2>1. The Core Principle</h2>
<p class="lead"><strong>Be excellent to each other.</strong></p>
<p>This means:</p>
<ol>
<li><strong>Respect people's right to exist and make things here,</strong> regardless of who they are.</li>
<li><strong>Take care of the space</strong> so others can use it too.</li>
<li><strong>Handle conflicts directly when you can,</strong> and ask for help when you can't.</li>
<li><strong>Support the community's ability to enforce its norms,</strong> even when it's uncomfortable.</li>
</ol>
</section>
<section id="who-applies">
<h2>2. Who This Applies To</h2>
<p>
Everyone in HeatSync spaces—physical or digital—including members, guests,
visitors, board members, and anyone at HSL-sponsored events. No one is exempt.
</p>
</section>
<section id="protected-groups">
<h2>3. Who We Protect</h2>
<p>HeatSync Labs does not tolerate discrimination or harassment based on:</p>
<ul>
<li>Race or ethnicity</li>
<li>Gender identity or expression</li>
<li>Sexual orientation</li>
<li>Disability (visible or invisible)</li>
<li>Age</li>
<li>Religion (or lack thereof)</li>
<li>National origin</li>
<li>Socioeconomic status</li>
<li>Body size or appearance</li>
<li>Neurodivergence</li>
</ul>
<p class="text-muted">
<em>This list is not exhaustive.</em> If you're being targeted for who you are, that's covered.
</p>
</section>
<section id="behaviors">
<h2>4. Behavior That Isn't Tolerated</h2>
<h3>4.1 Immediate Removal Behaviors</h3>
<p>These result in immediate removal from the space. No warnings.</p>
<ol>
<li><strong>Violence or credible threats of violence</strong></li>
<li><strong>Sexual harassment or assault</strong></li>
<li><strong>Stalking or deliberate intimidation</strong></li>
<li><strong>Doxxing</strong> (publishing someone's private information)</li>
<li><strong>Theft or intentional destruction of property</strong></li>
<li><strong>Grossly unsafe tool use</strong> that endangers others</li>
</ol>
<h3>4.2 Escalating Behaviors</h3>
<p>These may result in warnings, then escalating consequences if they continue.</p>
<ul>
<li>Slurs, discriminatory jokes, or derogatory language targeting protected characteristics</li>
<li>Unwelcome physical contact (you need consent before touching someone)</li>
<li>Sustained disruption of events, meetings, or others' work</li>
<li>Refusing to stop behavior when asked</li>
<li>Repeated boundary violations after being informed</li>
<li>Creating a hostile environment through patterns of microaggressions</li>
<li>Retaliation against someone who made a report</li>
</ul>
<h3>4.3 Space & Tool Violations</h3>
<ul>
<li>Using tools you're not certified for</li>
<li>Leaving messes for others to clean up</li>
<li>Ignoring posted safety procedures</li>
<li>Using more space than you need during busy times</li>
<li>Taking or using others' property without permission</li>
</ul>
</section>
<section id="do-ocracy-response">
<h2>5. The Do-ocracy Response</h2>
<CalloutBox type="tip">
<p>
<strong>We're a do-ocracy.</strong> That means you have standing to address
problems directly. You don't need permission to say "hey, that's not cool"
or "please clean up after yourself." Most issues should be handled this way.
</p>
</CalloutBox>
<h3>5.1 When to Handle It Yourself</h3>
<ul>
<li>Someone forgot safety glasses remind them</li>
<li>Someone left a mess ask them to clean it up</li>
<li>Someone's being loud during your work → politely ask them to keep it down</li>
<li>Someone said something mildly off → call it in ("hey, that came across weird")</li>
<li>A tool needs maintenance → fix it if you can, report it if you can't</li>
</ul>
<h3>5.2 When to Escalate</h3>
<ul>
<li>The behavior is in the "Immediate Removal" category</li>
<li>You've addressed it directly and it continues</li>
<li>You don't feel safe addressing it directly</li>
<li>The person becomes hostile when confronted</li>
<li>It's a pattern, not a one-time thing</li>
<li>You witness something happening to someone else who seems distressed</li>
</ul>
</section>
<section id="reporting">
<h2>6. Reporting & Response Process</h2>
<h3>6.1 How to Report</h3>
<p>Choose the method that works for you:</p>
<ul>
<li><strong>Email:</strong> conduct@heatsynclabs.org (goes to all board members)</li>
<li><strong>In person:</strong> Any board member or host present at the space</li>
<li><strong>Anonymous:</strong> Drop box at [LOCATION] or anonymous form at [URL]</li>
<li><strong>Direct to specific board member:</strong> If you're not comfortable with full board seeing the report</li>
</ul>
<h3>6.2 What Happens Next</h3>
<table>
<thead>
<tr>
<th>Timeline</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>48 hours</strong></td>
<td>Acknowledgment sent to reporter (unless anonymous)</td>
</tr>
<tr>
<td><strong>7 days</strong></td>
<td>Initial investigation complete; interim measures if needed</td>
</tr>
<tr>
<td><strong>21 days</strong></td>
<td>Final decision communicated to all parties</td>
</tr>
</tbody>
</table>
<p class="text-muted">
<em>Exceptions:</em> Complex situations may take longer. If so, you'll be told why and given an updated timeline.
</p>
<h3>6.3 Investigation Process</h3>
<ol>
<li><strong>Intake:</strong> At least two board members review the report</li>
<li><strong>Gathering information:</strong> We talk to the reporter, the respondent, and any witnesses</li>
<li><strong>Interim measures:</strong> If someone's safety is at risk, we may restrict access during investigation</li>
<li><strong>Decision:</strong> Board determines what happened and what response is appropriate</li>
<li><strong>Communication:</strong> Both parties are informed of the outcome</li>
</ol>
<CalloutBox type="info">
<p>
<strong>Conflict of Interest:</strong> If a board member is involved in the
incident (as reporter, respondent, or close relation), they recuse themselves
from the process.
</p>
</CalloutBox>
</section>
<section id="consequences">
<h2>7. Consequences</h2>
<p>Responses are proportional to the severity and pattern of behavior.</p>
<h3>Tier A: Verbal or Written Warning</h3>
<p>For first-time minor violations where the person seems unaware or immediately corrects.</p>
<ul>
<li>Documented internally but not announced publicly</li>
</ul>
<h3>Tier B: Required Action</h3>
<p>For repeated minor violations or moderate violations. May include:</p>
<ul>
<li>Apology to affected parties</li>
<li>Cleaning duty or other community service</li>
<li>Temporary restriction from specific areas or tools</li>
<li>Required re-certification for safety training</li>
</ul>
<h3>Tier C: Temporary Suspension</h3>
<p>For serious violations or continued problems after warnings. 30-180 days.</p>
<ul>
<li>No access to space during suspension</li>
<li>Card access revoked</li>
<li>Reinstatement may require conditions (e.g., meeting with board)</li>
</ul>
<h3>Tier D: Permanent Ban</h3>
<p>For severe violations or repeated serious problems. Reserved for:</p>
<ul>
<li>Violence, sexual assault, stalking, or credible threats</li>
<li>Pattern of harassment despite previous consequences</li>
<li>Actions that seriously endanger others</li>
</ul>
<CalloutBox type="warning">
<p>
<strong>No waiting for multiple complaints:</strong> The board is not required
to wait for a specific number of reports before taking action. A single credible
report of serious behavior is sufficient to investigate and act.
</p>
</CalloutBox>
</section>
<section id="appeals">
<h2>8. Appeals</h2>
<p>If you believe a decision was unfair, you may appeal.</p>
<h3>8.1 Grounds for Appeal</h3>
<ul>
<li>New evidence that wasn't available during the investigation</li>
<li>Procedural errors that affected the outcome</li>
<li>Consequence is disproportionate to the violation</li>
</ul>
<h3>8.2 Appeal Process</h3>
<ul>
<li>Submit written appeal to conduct@heatsynclabs.org within 14 days of decision</li>
<li>Appeal is reviewed by board members not involved in original decision</li>
<li>If all board members were involved, appeal goes to membership vote at HYH</li>
<li>Decision on appeal is final</li>
</ul>
</section>
<section id="confidentiality">
<h2>9. Confidentiality & Documentation</h2>
<ul>
<li>Reports are kept confidential to those involved in the investigation</li>
<li>The board maintains records of all reports and outcomes</li>
<li>Consequences may be shared with the community without naming individuals</li>
<li>Deliberately making consequences public when the board chose privacy is itself a violation</li>
<li>If the community needs to know for safety reasons, the board will communicate appropriately</li>
</ul>
</section>
<section id="amendments">
<h2>10. Amendments</h2>
<p>
This document may be amended through the standard HSL proposal process.
Amendments require a majority vote at HYH followed by board ratification.
</p>
</section>
<CalloutBox type="tip">
<p>
<strong>The goal isn't punishmentit's a space where people can make things
without worrying about being harassed, endangered, or excluded.</strong>
When we hold each other accountable, we're protecting what makes HeatSync worth having.
</p>
</CalloutBox>
<section id="contact" class="mt-7">
<h2>Contact</h2>
<ul>
<li><strong>Report a concern:</strong> conduct@heatsynclabs.org</li>
<li><strong>General board inquiries:</strong> board@heatsynclabs.org</li>
<li><strong>Physical drop box:</strong> [LOCATION TBD]</li>
</ul>
</section>
<p class="text-small text-muted mt-7">
<em>This document is adapted from the Geek Feminism Anti-Harassment Policy and distributed under CC BY-SA 3.0.</em>
</p>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.community-standards-page {
max-width: $max-content-width;
section {
margin-bottom: $space-6;
}
h3 {
margin-top: $space-5;
}
table {
margin: $space-5 0;
}
}</style>
@@ -0,0 +1,461 @@
<template>
<div class="decision-making-page">
<DocumentHeader
title="Decision Making Process"
description="When to act independently, when to seek consensus, and how to make group decisions efficiently."
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="tip" title="Core Principle">
<p>
<strong>Default to action.</strong> Most decisions should be made by whoever
is doing the work. Group decisions are only for irreversible changes or
things that affect everyone.
</p>
</CalloutBox>
<section id="decision-framework">
<h2>The Decision Framework</h2>
<div class="decision-tree">
<div class="decision-level individual">
<h3>Individual Action (Just Do It)</h3>
<p><strong>Timeline:</strong> Immediate</p>
<p><strong>Who decides:</strong> You</p>
<ul>
<li>Reversible changes</li>
<li>Under $50 cost</li>
<li>Doesn't affect others' work</li>
<li>Safety improvements</li>
<li>Cleaning and organizing</li>
<li>Documentation</li>
</ul>
</div>
<div class="decision-level feedback">
<h3>Seek Feedback (Post & Wait)</h3>
<p><strong>Timeline:</strong> 3-7 days</p>
<p><strong>Who decides:</strong> You, with input</p>
<ul>
<li>$50-$200 expenses</li>
<li>Changes to shared spaces</li>
<li>New procedures or guidelines</li>
<li>Events using significant space</li>
<li>Tool modifications</li>
<li>Affects specific groups</li>
</ul>
</div>
<div class="decision-level consensus">
<h3>Group Consensus (Meeting)</h3>
<p><strong>Timeline:</strong> 9-14 days</p>
<p><strong>Who decides:</strong> Present members</p>
<ul>
<li>Over $200 expenses</li>
<li>Permanent infrastructure</li>
<li>Policy changes</li>
<li>Access and membership</li>
<li>Irreversible changes</li>
<li>Affects everyone</li>
</ul>
</div>
</div>
</section>
<section id="feedback-process">
<h2>The Feedback Process</h2>
<p>
When your action needs feedback (middle tier), here's how to gather it effectively:
</p>
<ol>
<li>
<h4>1. Document Your Proposal</h4>
<p>Write a clear description including:</p>
<ul>
<li>What you want to do</li>
<li>Why it's needed</li>
<li>How it affects others</li>
<li>Estimated cost and timeline</li>
<li>How to provide feedback</li>
</ul>
</li>
<li>
<h4>2. Post in Multiple Places</h4>
<ul>
<li>Wiki or documentation site</li>
<li>Slack/Discord announcement</li>
<li>Physical board in the space</li>
<li>Mailing list if significant</li>
</ul>
</li>
<li>
<h4>3. Set a Deadline</h4>
<ul>
<li>Small changes: 72 hours</li>
<li>Medium changes: 7 days</li>
<li>Large but not permanent: 9-14 days</li>
</ul>
</li>
<li>
<h4>4. Address Feedback</h4>
<ul>
<li>Acknowledge all input</li>
<li>Adjust plan if needed</li>
<li>Explain if you can't accommodate</li>
<li>Find compromise when possible</li>
</ul>
</li>
<li>
<h4>5. Proceed or Escalate</h4>
<ul>
<li>No objections? Do it!</li>
<li>Minor concerns? Address and proceed</li>
<li>Major objections? Bring to meeting</li>
<li>Deadlock? Board mediates</li>
</ul>
</li>
</ol>
</section>
<section id="meetings">
<h2>Membership Meetings</h2>
<p>
Some decisions need face-to-face discussion. Here's how our meetings work:
</p>
<h3>Regular Meetings</h3>
<ul>
<li><strong>Frequency:</strong> Monthly, first Tuesday</li>
<li><strong>Time:</strong> 7:00 PM</li>
<li><strong>Location:</strong> Main area of the space</li>
<li><strong>Who can attend:</strong> Anyone (guests welcome)</li>
<li><strong>Who can vote:</strong> Dues-paying members</li>
</ul>
<h3>Meeting Agenda</h3>
<ol>
<li>Welcome and introductions (5 min)</li>
<li>Review previous meeting actions (5 min)</li>
<li>Officer reports (10 min)</li>
<li>Old business (15 min)</li>
<li>New proposals (30 min)</li>
<li>Open discussion (15 min)</li>
<li>Action items and close (5 min)</li>
</ol>
<h3>Proposal Process</h3>
<ul>
<li>Post proposal 14 days before meeting</li>
<li>Present proposal at meeting (5 min max)</li>
<li>Q&A and discussion (10 min max)</li>
<li>Modify based on feedback if needed</li>
<li>Call for consensus or vote</li>
</ul>
<CalloutBox type="info">
<p>
<strong>Keep it short:</strong> Meetings should be under 90 minutes.
Long discussions can continue after the formal meeting.
</p>
</CalloutBox>
</section>
<section id="consensus">
<h2>Consensus vs Voting</h2>
<h3>We Prefer Consensus</h3>
<p>
Consensus doesn't mean everyone loves the decision, but everyone can live with it.
Signs of consensus:
</p>
<ul>
<li>No strong objections raised</li>
<li>People saying "I can live with that"</li>
<li>Thumbs up or sideways (not down)</li>
<li>General nodding and agreement</li>
</ul>
<h3>When to Vote</h3>
<p>If consensus fails after reasonable discussion:</p>
<ul>
<li>Board elections (always vote)</li>
<li>Bylaw changes (2/3 majority required)</li>
<li>Budget over $500 (majority)</li>
<li>Membership issues (majority)</li>
<li>Deadlocked after 15 minutes discussion</li>
</ul>
<h3>Blocking Consensus</h3>
<p>
Anyone can block consensus, but it's a serious action. If you block:
</p>
<ul>
<li>Explain your fundamental concern</li>
<li>Propose an alternative if possible</li>
<li>Be willing to work toward resolution</li>
<li>Consider if it's really block-worthy</li>
</ul>
<p class="text-muted">
Blocking should be rare. Most concerns can be addressed through modification.
</p>
</section>
<section id="special-decisions">
<h2>Special Decision Types</h2>
<h3>Emergency Decisions</h3>
<p>When immediate action is needed (safety, legal, infrastructure failure):</p>
<ul>
<li>Any member can act to protect safety</li>
<li>Any board member can make emergency decisions</li>
<li>Document actions taken</li>
<li>Report at next meeting</li>
<li>Retroactive approval if needed</li>
</ul>
<h3>Financial Decisions</h3>
<table>
<thead>
<tr>
<th>Amount</th>
<th>Who Decides</th>
<th>Process</th>
</tr>
</thead>
<tbody>
<tr>
<td>Under $50</td>
<td>Individual member</td>
<td>Just do it, save receipt</td>
</tr>
<tr>
<td>$50 - $200</td>
<td>Individual with feedback</td>
<td>Post proposal, wait 72 hours</td>
</tr>
<tr>
<td>$200 - $500</td>
<td>Membership meeting</td>
<td>Proposal + discussion</td>
</tr>
<tr>
<td>Over $500</td>
<td>Membership vote</td>
<td>14-day notice + formal vote</td>
</tr>
</tbody>
</table>
<h3>Access Decisions</h3>
<ul>
<li><strong>New member approval:</strong> Board reviews application</li>
<li><strong>Key/card access:</strong> After orientation completion</li>
<li><strong>Tool certification:</strong> Certified member signs off</li>
<li><strong>Access revocation:</strong> Board decision with member appeal rights</li>
<li><strong>Banning:</strong> See Community Standards process</li>
</ul>
</section>
<section id="documentation">
<h2>Documenting Decisions</h2>
<p>All decisions need documentation proportional to their impact:</p>
<h3>Individual Actions</h3>
<ul>
<li>Note in appropriate log or wiki</li>
<li>Receipt in expense folder</li>
<li>Before/after photos if visual change</li>
</ul>
<h3>Feedback Decisions</h3>
<ul>
<li>Original proposal preserved</li>
<li>Feedback received noted</li>
<li>Final implementation documented</li>
<li>Outcomes tracked</li>
</ul>
<h3>Meeting Decisions</h3>
<ul>
<li>Recorded in meeting minutes</li>
<li>Posted within 7 days</li>
<li>Action items tracked</li>
<li>Follow-up at next meeting</li>
</ul>
</section>
<section id="conflicts">
<h2>When Decisions Conflict</h2>
<p>Sometimes decisions or actions conflict. Here's the precedence:</p>
<ol>
<li><strong>Safety always wins</strong> - Safety concerns override everything</li>
<li><strong>Legal requirements</strong> - We must follow the law</li>
<li><strong>Bylaws</strong> - Our governing document</li>
<li><strong>Meeting decisions</strong> - Group consensus/votes</li>
<li><strong>Board decisions</strong> - Within their scope</li>
<li><strong>Do-ocracy actions</strong> - Individual initiative</li>
</ol>
<p>When same-level decisions conflict:</p>
<ul>
<li>More recent generally wins</li>
<li>More specific overrides general</li>
<li>Irreversible overrides reversible</li>
<li>Talk it out when unclear</li>
</ul>
</section>
<section id="tips">
<h2>Tips for Good Decision Making</h2>
<div class="tips-grid">
<div class="tip">
<h4>Bias Toward Action</h4>
<p>When in doubt, try it. Most things are reversible.</p>
</div>
<div class="tip">
<h4>Communicate Early</h4>
<p>Surprises create conflict. Share plans before implementing.</p>
</div>
<div class="tip">
<h4>Accept Good Enough</h4>
<p>Perfect consensus is rare. Workable solutions are valuable.</p>
</div>
<div class="tip">
<h4>Time Box Discussions</h4>
<p>Set limits. Not every decision needs an hour of debate.</p>
</div>
<div class="tip">
<h4>Document Rationale</h4>
<p>Future members need to understand why, not just what.</p>
</div>
<div class="tip">
<h4>Review and Adjust</h4>
<p>Decisions aren't permanent. Review and improve over time.</p>
</div>
</div>
</section>
<CalloutBox type="tip">
<p>
<strong>Remember:</strong> The goal is to enable action, not prevent it.
When the decision-making process becomes a barrier to doing things,
it's time to simplify the process.
</p>
</CalloutBox>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.decision-making-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
.decision-tree {
display: grid;
gap: $space-4;
margin: $space-5 0;
.decision-level {
padding: $space-4;
border-radius: $radius-md;
border: 2px solid;
h3 {
margin-bottom: $space-2;
}
p {
margin-bottom: $space-3;
font-size: $font-size-sm;
}
&.individual {
background-color: rgba($color-success, 0.05);
border-color: $color-success;
h3 {
color: $color-success;
}
}
&.feedback {
background-color: rgba($color-warning, 0.05);
border-color: $color-warning;
h3 {
color: $color-warning;
}
}
&.consensus {
background-color: rgba($color-accent, 0.05);
border-color: $color-accent;
h3 {
color: $color-accent;
}
}
}
}
ol li {
margin-bottom: $space-4;
h4 {
color: $color-accent;
margin-bottom: $space-2;
}
}
.tips-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: $space-4;
margin: $space-5 0;
.tip {
padding: $space-3;
background-color: $color-paper-light;
border-radius: $radius-md;
h4 {
color: $color-accent;
margin-bottom: $space-2;
font-size: $font-size-md;
}
p {
margin: 0;
font-size: $font-size-sm;
}
}
}
table {
margin: $space-5 0;
}
}</style>
+393
View File
@@ -0,0 +1,393 @@
<template>
<div class="do-ocracy-page">
<DocumentHeader
title="The Do-ocracy Guide"
description="How to actually get things done at HeatSync Labs. If you want something done: Just do it!"
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="tip" title="The Golden Rule">
<p>
<strong>If you want something done: Just do it!</strong>
</p>
<p>
Doing a task is in itself justification for you being the person who does that job.
Authority is earned through action, not election.
</p>
</CalloutBox>
<section id="what-is-doocracy">
<h2>What is Do-ocracy?</h2>
<p class="lead">
In a do-ocracy, individuals choose to take on tasks and roles independently.
The authority to make decisions and take action lies with those who do the work.
</p>
<p>
This is different from democracy (where everyone votes) and different from
meritocracy (where the "best" person does it). In a do-ocracy, <strong>whoever
shows up and does the work has the authority to make decisions about that work.</strong>
</p>
<h3>Core Principles</h3>
<ul>
<li><strong>Initiative:</strong> Don't wait for permission or assignment</li>
<li><strong>Action:</strong> Doing beats planning</li>
<li><strong>Communication:</strong> Tell others what you're doing</li>
<li><strong>Openness:</strong> Be receptive to feedback and help</li>
<li><strong>Responsibility:</strong> Own your actions and their outcomes</li>
</ul>
</section>
<section id="how-it-works">
<h2>How It Works in Practice</h2>
<div class="process-steps">
<div class="step">
<h3>1. See a Need</h3>
<p>Notice something that needs doing: broken equipment, messy area, missing documentation, cool project idea.</p>
</div>
<div class="step">
<h3>2. Communicate Intent</h3>
<p>For significant actions, post your plan on the wiki, Slack, or physical board. This allows for feedback.</p>
</div>
<div class="step">
<h3>3. Seek Input</h3>
<p>Actively ask for feedback, especially from those who might be affected. Address constructive objections.</p>
</div>
<div class="step">
<h3>4. Take Action</h3>
<p>If no unresolvable objections arise within 9-14 days (or immediately for small tasks), proceed responsibly.</p>
</div>
<div class="step">
<h3>5. Document Results</h3>
<p>Record what you did, how much it cost, and any relevant details for future reference.</p>
</div>
</div>
</section>
<section id="when-to-act">
<h2>When to Just Act vs When to Discuss</h2>
<div class="decision-grid">
<div class="decision-card act">
<h3>Just Do It</h3>
<ul>
<li>Cleaning and organizing</li>
<li>Fixing broken things</li>
<li>Routine maintenance</li>
<li>Documentation improvements</li>
<li>Small improvements (under $50)</li>
<li>Reversible changes</li>
<li>Safety fixes</li>
</ul>
</div>
<div class="decision-card discuss">
<h3>Seek Feedback First</h3>
<ul>
<li>Changes affecting others' work</li>
<li>Spending $50-$200</li>
<li>Moving/reorganizing shared spaces</li>
<li>New policies or procedures</li>
<li>Tool modifications</li>
<li>Events using significant space</li>
</ul>
</div>
<div class="decision-card vote">
<h3>Needs Formal Approval</h3>
<ul>
<li>Spending over $200</li>
<li>Permanent infrastructure changes</li>
<li>Legal commitments</li>
<li>Bylaw changes</li>
<li>Safety policy changes</li>
<li>Membership decisions</li>
</ul>
</div>
</div>
</section>
<section id="practical-examples">
<h2>Practical Examples</h2>
<div class="example-box">
<h3>Example: Organizing a Workshop</h3>
<p>Sarah wants to run a soldering workshop:</p>
<ol>
<li>She posts on Slack: "Planning a soldering workshop for next Saturday 2-5pm"</li>
<li>Gets feedback about material costs and space availability</li>
<li>Orders supplies using the workshop budget</li>
<li>Runs the workshop</li>
<li>Documents attendance and expenses on the wiki</li>
</ol>
<p class="text-muted">
Sarah didn't need permission - she took initiative, communicated, and made it happen.
</p>
</div>
<div class="example-box">
<h3>Example: Tool Area Reorganization</h3>
<p>Mike notices the electronics bench is chaotic:</p>
<ol>
<li>Takes photos of current state</li>
<li>Posts proposal with mockup on wiki: "Reorganizing electronics bench for better workflow"</li>
<li>Waits 10 days for feedback, incorporates suggestions</li>
<li>Spends a Saturday reorganizing with help from volunteers</li>
<li>Updates tool documentation with new layout</li>
</ol>
<p class="text-muted">
Mike communicated first because this affected others' workspaces, but still led the change himself.
</p>
</div>
</section>
<section id="budget">
<h2>Do-ocracy Budget Guidelines</h2>
<table>
<thead>
<tr>
<th>Amount</th>
<th>Process</th>
<th>Documentation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Under $50</td>
<td>Just do it</td>
<td>Save receipt, note in expense log</td>
</tr>
<tr>
<td>$50 - $200</td>
<td>Post intent, wait 72 hours for feedback</td>
<td>Receipt + brief wiki entry</td>
</tr>
<tr>
<td>Over $200</td>
<td>Formal proposal at meeting</td>
<td>Full proposal + receipts + report</td>
</tr>
</tbody>
</table>
<CalloutBox type="info">
<p>
<strong>Reimbursement:</strong> Submit receipts with documentation to the
treasurer. Approved do-ocracy expenses are reimbursed within 30 days.
</p>
</CalloutBox>
</section>
<section id="boundaries">
<h2>Boundaries and Limitations</h2>
<h3>Do-ocracy Does NOT Apply To:</h3>
<ul>
<li><strong>Safety violations:</strong> Never compromise safety for expediency</li>
<li><strong>Others' property:</strong> Don't modify someone else's project without permission</li>
<li><strong>Irreversible changes:</strong> Major alterations need group consensus</li>
<li><strong>Legal matters:</strong> Contracts, liability issues need board approval</li>
<li><strong>Access control:</strong> Membership and access decisions follow formal process</li>
</ul>
<h3>Conflict Resolution</h3>
<p>When do-ocracy actions conflict:</p>
<ol>
<li><strong>Direct dialogue:</strong> Talk to each other first</li>
<li><strong>Seek mediation:</strong> Ask a neutral member to help</li>
<li><strong>Community input:</strong> Bring to next meeting if needed</li>
<li><strong>Board intervention:</strong> Only for unresolvable disputes</li>
</ol>
</section>
<section id="tips">
<h2>Tips for Successful Do-ocracy</h2>
<div class="tips-grid">
<div class="tip">
<h4>Start Small</h4>
<p>Build trust by successfully completing small projects before taking on major initiatives.</p>
</div>
<div class="tip">
<h4>Document Everything</h4>
<p>Future members benefit from knowing what was done and why. Over-documentation beats under-documentation.</p>
</div>
<div class="tip">
<h4>Ask for Help</h4>
<p>Do-ocracy doesn't mean working alone. Recruit others who share your vision.</p>
</div>
<div class="tip">
<h4>Accept Feedback Gracefully</h4>
<p>Not all ideas work out. Be ready to adjust or even abandon plans based on community input.</p>
</div>
<div class="tip">
<h4>Celebrate Successes</h4>
<p>Share what you accomplished! It inspires others and builds community momentum.</p>
</div>
<div class="tip">
<h4>Learn from Failures</h4>
<p>Things will go wrong. Document what didn't work so others can learn.</p>
</div>
</div>
</section>
<CalloutBox type="tip" title="Remember">
<p>
<strong>Perfect is the enemy of done.</strong> It's better to do something
imperfectly than to do nothing perfectly. The community will help iterate
and improve over time.
</p>
</CalloutBox>
<section id="resources">
<h2>Resources</h2>
<ul>
<li>Wiki: Document your projects and read about others</li>
<li>Slack #do-ocracy: Coordinate with other doers</li>
<li>Physical board: Post plans and gather feedback</li>
<li>Treasurer: Submit reimbursement requests</li>
<li>Meeting notes: Review past do-ocracy discussions</li>
</ul>
</section>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.do-ocracy-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
.process-steps {
margin: $space-5 0;
.step {
padding: $space-4;
margin-bottom: $space-3;
background-color: $color-paper-light;
border-left: 4px solid $color-accent;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
margin: 0;
}
}
}
.decision-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $space-4;
margin: $space-5 0;
.decision-card {
padding: $space-4;
border-radius: $radius-md;
h3 {
margin-bottom: $space-3;
font-size: $font-size-lg;
}
ul {
margin: 0;
padding-left: $space-4;
}
&.act {
background-color: rgba($color-success, 0.05);
border: 2px solid $color-success;
h3 {
color: $color-success;
}
}
&.discuss {
background-color: rgba($color-warning, 0.05);
border: 2px solid $color-warning;
h3 {
color: $color-warning;
}
}
&.vote {
background-color: rgba($color-accent, 0.05);
border: 2px solid $color-accent;
h3 {
color: $color-accent;
}
}
}
}
.example-box {
padding: $space-5;
margin: $space-4 0;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-3;
}
ol {
margin: $space-3 0;
}
}
.tips-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: $space-4;
margin: $space-5 0;
.tip {
padding: $space-3;
background-color: $color-paper-light;
border-radius: $radius-md;
h4 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
margin: 0;
font-size: $font-size-sm;
}
}
}
table {
margin: $space-5 0;
}
}</style>
+225
View File
@@ -0,0 +1,225 @@
<template>
<div class="home-page">
<DocumentHeader
title="Hackerspace Governance in a Box"
description="A complete governance framework for hackerspaces, based on do-ocracy principles and community-driven decision making."
:show-meta="false"
/>
<section class="intro-section">
<h2>Welcome to Your Governance Framework</h2>
<p class="lead">
This site contains everything you need to run a successful hackerspace:
bylaws, community standards, decision-making processes, and operational
guidelines that actually work in practice.
</p>
</section>
<CalloutBox type="tip" title="Adapt This for Your Space">
<p>
While this framework is tailored for {{ hackerspaceStore.hackerspace.name }},
it's designed to be easily adapted for any hackerspace. Replace our name
with yours, adjust the specifics to match your community's needs, and
you'll have a complete governance system ready to go.
</p>
</CalloutBox>
<section class="principles-section">
<h2>Core Principles</h2>
<div class="principle-grid">
<div class="principle-card">
<h3>Do-ocracy</h3>
<p>
If you want something done, do it. Authority comes from taking action,
not from titles or elections. Those who do the work make the decisions.
</p>
</div>
<div class="principle-card">
<h3>Be Excellent</h3>
<p>
Respect everyone's right to exist and make things. Take care of the
space so others can use it. Handle conflicts directly when you can.
</p>
</div>
<div class="principle-card">
<h3>Community First</h3>
<p>
The space exists so people can make things. Every decision should
support that mission. We protect the community's ability to create.
</p>
</div>
<div class="principle-card">
<h3>Iterate & Improve</h3>
<p>
Our governance isn't perfect, and that's okay. We continuously update
our systems based on what works and what doesn't.
</p>
</div>
</div>
</section>
<section class="structure-section">
<h2>How This Framework Works</h2>
<dl class="structure-list">
<dt>Bylaws</dt>
<dd>
The legal foundation required for 501(c)(3) status. Minimal and
empowering, designed to meet legal requirements while maximizing
member autonomy.
</dd>
<dt>Community Standards</dt>
<dd>
Clear expectations for behavior and a transparent accountability
process. Protects everyone's ability to participate safely.
</dd>
<dt>Do-ocracy Guide</dt>
<dd>
How to actually get things done. When to act independently, when
to seek feedback, and how to document your work.
</dd>
<dt>Decision Making</dt>
<dd>
When meetings are needed vs when you can just act. Designed for
9-14 day proposal cycles, not months of bureaucracy.
</dd>
<dt>The Board</dt>
<dd>
Limited to infrastructure and conflict resolution. Board members
are "wardens" not leaders, maintaining the space without
controlling its direction.
</dd>
</dl>
</section>
<section class="getting-started">
<h2>Getting Started</h2>
<p>
Whether you're a new member, a board member, or starting your own
hackerspace, here's how to use this framework:
</p>
<ol>
<li>
<strong>New Members:</strong> Start with the Community Standards
to understand expectations, then read the Do-ocracy Guide to learn
how to contribute.
</li>
<li>
<strong>Active Members:</strong> Reference the Decision Making
section when proposing changes. Use the Do-ocracy Guide for daily
operations.
</li>
<li>
<strong>Board Members:</strong> Focus on the Bylaws and Board
sections. Remember: your role is to maintain, not to lead.
</li>
<li>
<strong>Other Hackerspaces:</strong> Jump to "Adapt This" for a
guide on customizing this framework for your community.
</li>
</ol>
</section>
<CalloutBox type="info" title="About This Framework">
<p>
This governance framework synthesizes best practices from successful
hackerspaces worldwide, particularly drawing from the Hackerspace
Blueprint and decades of community experience. It's licensed under
Creative Commons for sharing and adaptation.
</p>
</CalloutBox>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
import { useHackerspaceStore } from '@/stores/hackerspace'
const hackerspaceStore = useHackerspaceStore()
</script>
<style lang="scss" scoped>
.home-page {
max-width: $max-content-width;
}
.intro-section {
margin-bottom: $space-7;
}
.principles-section {
margin-bottom: $space-7;
}
.principle-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $space-5;
margin-top: $space-5;
}
.principle-card {
padding: $space-5;
background-color: $color-paper-light;
border-radius: $radius-md;
border-left: 4px solid $color-accent;
h3 {
font-size: $font-size-lg;
margin-bottom: $space-3;
color: $color-accent;
}
p {
margin: 0;
font-size: $font-size-sm;
}
}
.structure-section {
margin-bottom: $space-7;
}
.structure-list {
margin-top: $space-5;
dt {
font-weight: 600;
margin-bottom: $space-2;
color: $color-accent;
}
dd {
margin-bottom: $space-4;
margin-left: 0;
padding-left: $space-5;
border-left: 2px solid $color-border;
color: $color-text;
}
}
.getting-started {
margin-bottom: $space-7;
ol {
margin-top: $space-4;
padding-left: $space-5;
li {
margin-bottom: $space-3;
line-height: 1.6;
}
}
}
</style>
@@ -0,0 +1,470 @@
<template>
<div class="membership-page">
<DocumentHeader
title="Membership"
description="How to join HeatSync Labs, membership levels, benefits, and expectations."
:last-updated="new Date('2024-12-05')"
/>
<CalloutBox type="info">
<p>
<strong>HeatSync Labs is open to everyone.</strong> You don't need to be an
expert, have specific skills, or fit any particular mold. If you want to
make things and learn alongside others, you belong here.
</p>
</CalloutBox>
<section id="becoming-member">
<h2>Becoming a Member</h2>
<div class="membership-steps">
<div class="step">
<h3>1. Visit the Space</h3>
<p>Come to an open house or public event. Get a feel for the community and space.</p>
</div>
<div class="step">
<h3>2. Attend Orientation</h3>
<p>Learn about safety, culture, and how to use the space effectively.</p>
</div>
<div class="step">
<h3>3. Submit Application</h3>
<p>Simple form with emergency contact and agreement to community standards.</p>
</div>
<div class="step">
<h3>4. Pay Dues</h3>
<p>Monthly dues support rent, utilities, and supplies. Sliding scale available.</p>
</div>
<div class="step">
<h3>5. Get Access</h3>
<p>Receive your key/card and start making things!</p>
</div>
</div>
</section>
<section id="membership-levels">
<h2>Membership Levels</h2>
<div class="membership-grid">
<div class="membership-card">
<h3>Friend of the Space</h3>
<p class="price">Free</p>
<ul>
<li>Attend public events</li>
<li>Use space during open hours</li>
<li>Join mailing list/Slack</li>
<li>Participate in community</li>
</ul>
<p class="note">No voting rights or 24/7 access</p>
</div>
<div class="membership-card featured">
<h3>Regular Member</h3>
<p class="price">$50/month</p>
<ul>
<li>24/7 access to space</li>
<li>Storage space (small)</li>
<li>Tool certification eligibility</li>
<li>Workshop discounts</li>
<li>Voting rights after 3 months</li>
</ul>
<p class="note">Standard membership for most</p>
</div>
<div class="membership-card">
<h3>Supporting Member</h3>
<p class="price">$100+/month</p>
<ul>
<li>All regular member benefits</li>
<li>Additional storage space</li>
<li>Priority workshop registration</li>
<li>Guest passes (2/month)</li>
<li>Good karma and our thanks</li>
</ul>
<p class="note">For those who can contribute more</p>
</div>
</div>
<CalloutBox type="tip">
<p>
<strong>Sliding Scale Available:</strong> We never want money to be a barrier.
If you can't afford full dues, talk to a board member about reduced rates
or work-trade options. We'd rather have you as an active member than not at all.
</p>
</CalloutBox>
</section>
<section id="voting-member">
<h2>Becoming a Voting Member</h2>
<p>
Voting members shape the direction of HeatSync Labs. To become one:
</p>
<ol>
<li><strong>Be a dues-paying member</strong> in good standing</li>
<li><strong>Actively contribute</strong> within the last 6 months</li>
<li><strong>Complete orientation</strong> and understand our culture</li>
<li><strong>Participate regularly</strong> in space activities</li>
</ol>
<h3>What Counts as Active Contribution?</h3>
<ul>
<li>Working on projects in the space</li>
<li>Teaching workshops or skills</li>
<li>Maintaining tools or areas</li>
<li>Organizing events</li>
<li>Improving documentation</li>
<li>Helping other members</li>
<li>Participating in workdays</li>
</ul>
<p class="text-muted">
Contribution is self-documented. If you're doing things, you're contributing.
No need for formal tracking or approval.
</p>
</section>
<section id="member-benefits">
<h2>Member Benefits</h2>
<div class="benefits-grid">
<div class="benefit">
<h4>24/7 Access</h4>
<p>Work on projects whenever inspiration strikes</p>
</div>
<div class="benefit">
<h4>Tool Library</h4>
<p>Access to thousands of dollars worth of tools</p>
</div>
<div class="benefit">
<h4>Community Knowledge</h4>
<p>Learn from experts in dozens of fields</p>
</div>
<div class="benefit">
<h4>Project Space</h4>
<p>Room to work on things you can't do at home</p>
</div>
<div class="benefit">
<h4>Storage</h4>
<p>Keep projects and materials at the space</p>
</div>
<div class="benefit">
<h4>Classes & Workshops</h4>
<p>Free or discounted learning opportunities</p>
</div>
</div>
</section>
<section id="expectations">
<h2>Member Expectations</h2>
<p>
With membership comes responsibility. We expect all members to:
</p>
<h3>Follow the Prime Directive</h3>
<ul>
<li><strong>Be excellent to each other</strong></li>
<li>Follow Community Standards</li>
<li>Respect others' work and space</li>
<li>Communicate constructively</li>
</ul>
<h3>Maintain the Space</h3>
<ul>
<li>Clean up after yourself</li>
<li>Return tools to their homes</li>
<li>Report broken things</li>
<li>Participate in occasional workdays</li>
<li>Leave things better than you found them</li>
</ul>
<h3>Engage with Community</h3>
<ul>
<li>Share knowledge when you can</li>
<li>Ask for help when you need it</li>
<li>Attend meetings occasionally</li>
<li>Contribute to the culture</li>
</ul>
<h3>Pay Your Dues</h3>
<ul>
<li>Pay on time (by the 5th)</li>
<li>Communicate if you have issues</li>
<li>Update payment info when needed</li>
</ul>
</section>
<section id="guest-policy">
<h2>Guest Policy</h2>
<p>
Members can bring guests, but are responsible for them:
</p>
<ul>
<li><strong>Always accompany guests</strong> - Don't leave them alone</li>
<li><strong>Explain safety rules</strong> - Especially for tools</li>
<li><strong>Limit frequency</strong> - Regular visitors should become members</li>
<li><strong>Take responsibility</strong> - You're liable for guest actions</li>
<li><strong>Sign them in</strong> - Log in the guest book</li>
</ul>
<CalloutBox type="info">
<p>
Guests are welcome during open hours without a member host.
This policy applies to 24/7 access times.
</p>
</CalloutBox>
</section>
<section id="suspension">
<h2>Suspension & Termination</h2>
<p>
We hate to lose members, but sometimes it's necessary:
</p>
<h3>Automatic Suspension</h3>
<ul>
<li>Dues 60+ days overdue</li>
<li>During investigation of serious violations</li>
<li>Safety violations endangering others</li>
</ul>
<h3>Termination Causes</h3>
<ul>
<li>Serious Community Standards violations</li>
<li>Theft or intentional damage</li>
<li>Repeated violations after warnings</li>
<li>Actions harming the organization</li>
</ul>
<h3>Due Process</h3>
<ol>
<li>Member notified of issue</li>
<li>Opportunity to respond</li>
<li>Board review and decision</li>
<li>Appeal to membership if desired</li>
</ol>
<p class="text-muted">
See Community Standards for detailed violation and appeals process.
</p>
</section>
<section id="taking-break">
<h2>Taking a Break</h2>
<p>
Life happens. If you need to pause membership:
</p>
<ul>
<li><strong>Notify the board</strong> before dues are due</li>
<li><strong>Return any borrowed items</strong></li>
<li><strong>Clean out personal storage</strong></li>
<li><strong>Stay connected</strong> via Slack/mailing list if desired</li>
</ul>
<p>
We'll welcome you back whenever you're ready. Alumni are always
part of the HeatSync family.
</p>
</section>
<section id="how-to-join">
<h2>Ready to Join?</h2>
<div class="join-options">
<div class="join-card">
<h3>Visit First</h3>
<p>Come to our next open house:</p>
<ul>
<li>Every Thursday, 7-10 PM</li>
<li>First Saturday, 12-4 PM</li>
<li>Or any public event</li>
</ul>
</div>
<div class="join-card">
<h3>Apply Online</h3>
<p>If you've visited:</p>
<ul>
<li>Fill out application</li>
<li>Schedule orientation</li>
<li>Set up payment</li>
</ul>
<a href="#" class="btn">Apply Now</a>
</div>
<div class="join-card">
<h3>Questions?</h3>
<p>Contact us:</p>
<ul>
<li>membership@heatsynclabs.org</li>
<li>Join Slack for quick answers</li>
<li>Ask any member</li>
</ul>
</div>
</div>
</section>
<CalloutBox type="tip">
<p>
<strong>Pro tip:</strong> The best way to know if HeatSync is right for you
is to visit. Every community has its own vibe. Come see if ours matches what
you're looking for.
</p>
</CalloutBox>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.membership-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
.membership-steps {
display: grid;
gap: $space-3;
margin: $space-5 0;
.step {
display: flex;
gap: $space-4;
padding: $space-3;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin: 0;
white-space: nowrap;
}
p {
margin: 0;
}
}
}
.membership-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $space-4;
margin: $space-5 0;
.membership-card {
padding: $space-5;
border: 2px solid $color-border;
border-radius: $radius-md;
text-align: center;
&.featured {
border-color: $color-accent;
background-color: rgba($color-accent, 0.02);
}
h3 {
color: $color-accent;
margin-bottom: $space-2;
}
.price {
font-size: $font-size-2xl;
font-weight: 700;
color: $color-text;
margin: $space-3 0;
}
ul {
text-align: left;
margin: $space-4 0;
padding-left: $space-4;
}
.note {
font-size: $font-size-sm;
color: $color-text-muted;
font-style: italic;
}
}
}
.benefits-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: $space-4;
margin: $space-5 0;
.benefit {
padding: $space-3;
background-color: $color-paper-light;
border-radius: $radius-md;
h4 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
margin: 0;
font-size: $font-size-sm;
}
}
}
.join-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $space-4;
margin: $space-5 0;
.join-card {
padding: $space-4;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-3;
}
ul {
margin: $space-3 0;
}
.btn {
display: inline-block;
padding: $space-2 $space-4;
background-color: $color-accent;
color: white;
border-radius: $radius-md;
text-decoration: none;
margin-top: $space-3;
&:hover {
background-color: darken($color-accent, 10%);
}
}
}
}
}</style>
+418
View File
@@ -0,0 +1,418 @@
<template>
<div class="resources-page">
<DocumentHeader
title="Resources & Templates"
description="Practical tools, templates, and resources for running your hackerspace."
:last-updated="new Date('2024-12-05')"
/>
<section id="templates">
<h2>Document Templates</h2>
<div class="template-grid">
<div class="template-card">
<h3>Meeting Templates</h3>
<ul>
<li>Meeting agenda template</li>
<li>Meeting minutes format</li>
<li>Proposal template</li>
<li>Action items tracker</li>
</ul>
<button class="btn-download">Download Pack</button>
</div>
<div class="template-card">
<h3>Membership Forms</h3>
<ul>
<li>Membership application</li>
<li>Liability waiver</li>
<li>Guest sign-in sheet</li>
<li>Orientation checklist</li>
</ul>
<button class="btn-download">Download Pack</button>
</div>
<div class="template-card">
<h3>Financial Documents</h3>
<ul>
<li>Budget template</li>
<li>Expense report form</li>
<li>Reimbursement request</li>
<li>Monthly treasurer report</li>
</ul>
<button class="btn-download">Download Pack</button>
</div>
<div class="template-card">
<h3>Safety & Training</h3>
<ul>
<li>Tool certification form</li>
<li>Safety checklist</li>
<li>Incident report</li>
<li>Training log</li>
</ul>
<button class="btn-download">Download Pack</button>
</div>
</div>
</section>
<section id="guides">
<h2>How-To Guides</h2>
<div class="guide-list">
<div class="guide-item">
<h3>Starting a Hackerspace</h3>
<p>Step-by-step guide from idea to opening day</p>
<ul>
<li>Finding founding members</li>
<li>Choosing a legal structure</li>
<li>Finding and negotiating space</li>
<li>Initial fundraising</li>
<li>Building community</li>
</ul>
</div>
<div class="guide-item">
<h3>501(c)(3) Application</h3>
<p>Navigate the nonprofit application process</p>
<ul>
<li>Form 1023 walkthrough</li>
<li>Required documentation</li>
<li>Common pitfalls</li>
<li>Timeline expectations</li>
<li>State-specific requirements</li>
</ul>
</div>
<div class="guide-item">
<h3>Insurance for Hackerspaces</h3>
<p>Protect your organization and members</p>
<ul>
<li>General liability basics</li>
<li>Directors & Officers insurance</li>
<li>Equipment coverage</li>
<li>Event insurance</li>
<li>Working with brokers</li>
</ul>
</div>
<div class="guide-item">
<h3>Tool Acquisition</h3>
<p>Building your tool library strategically</p>
<ul>
<li>Priority tool lists by area</li>
<li>New vs used equipment</li>
<li>Donation strategies</li>
<li>Grants and funding</li>
<li>Maintenance planning</li>
</ul>
</div>
</div>
</section>
<section id="software">
<h2>Recommended Software</h2>
<div class="software-grid">
<div class="software-card">
<h3>Membership Management</h3>
<ul>
<li><strong>Wild Apricot:</strong> All-in-one membership platform</li>
<li><strong>MemberPress:</strong> WordPress-based solution</li>
<li><strong>Open Source:</strong> CiviCRM for nonprofits</li>
<li><strong>DIY:</strong> Google Workspace + scripts</li>
</ul>
</div>
<div class="software-card">
<h3>Access Control</h3>
<ul>
<li><strong>RFID:</strong> DIY solutions on GitHub</li>
<li><strong>Commercial:</strong> Kisi, Brivo systems</li>
<li><strong>Hybrid:</strong> Arduino + cloud services</li>
<li><strong>Simple:</strong> Keypad locks + codes</li>
</ul>
</div>
<div class="software-card">
<h3>Communication</h3>
<ul>
<li><strong>Chat:</strong> Slack, Discord, Matrix</li>
<li><strong>Forum:</strong> Discourse, phpBB</li>
<li><strong>Wiki:</strong> MediaWiki, DokuWiki</li>
<li><strong>Calendar:</strong> Google Calendar, Nextcloud</li>
</ul>
</div>
<div class="software-card">
<h3>Financial Tools</h3>
<ul>
<li><strong>Accounting:</strong> QuickBooks, Wave</li>
<li><strong>Payments:</strong> Stripe, PayPal, Square</li>
<li><strong>Expense:</strong> Expensify for reimbursements</li>
<li><strong>Fundraising:</strong> Open Collective</li>
</ul>
</div>
</div>
</section>
<section id="community">
<h2>Hackerspace Community</h2>
<h3>Networks & Organizations</h3>
<ul>
<li><strong>Hackerspace.org:</strong> Global hackerspace wiki and directory</li>
<li><strong>Space Federation:</strong> European hackerspace network</li>
<li><strong>School Factory:</strong> Educational programs framework</li>
<li><strong>Maker Faire:</strong> Event network and resources</li>
</ul>
<h3>Conferences & Events</h3>
<ul>
<li><strong>Chaos Communication Congress:</strong> Annual hacker conference</li>
<li><strong>DEF CON:</strong> Security and hacking conference</li>
<li><strong>Maker Faire:</strong> Regional maker events</li>
<li><strong>EMF Camp:</strong> UK hacker camp</li>
</ul>
<h3>Online Resources</h3>
<ul>
<li><strong>Hackerspace Design Patterns:</strong> hackerspace.design</li>
<li><strong>Hackerspace Blueprint:</strong> GitHub repository</li>
<li><strong>Discourse Forum:</strong> discuss.hackerspaces.org</li>
<li><strong>Reddit:</strong> r/hackerspaces</li>
</ul>
</section>
<section id="books">
<h2>Recommended Reading</h2>
<div class="book-grid">
<div class="book">
<h4>The Hackerspace Cookbook</h4>
<p>Practical recipes for common hackerspace challenges</p>
</div>
<div class="book">
<h4>Making Spaces</h4>
<p>Design patterns for collaborative workshops</p>
</div>
<div class="book">
<h4>The Art of Community</h4>
<p>Building and managing online and offline communities</p>
</div>
<div class="book">
<h4>Nonprofit Kit for Dummies</h4>
<p>Comprehensive guide to nonprofit management</p>
</div>
</div>
</section>
<section id="legal">
<h2>Legal Resources</h2>
<CalloutBox type="warning">
<p>
<strong>Not Legal Advice:</strong> These resources are for reference only.
Always consult with a qualified attorney for your specific situation.
</p>
</CalloutBox>
<h3>Key Documents</h3>
<ul>
<li>IRS 501(c)(3) requirements and forms</li>
<li>State nonprofit incorporation guides</li>
<li>Sample bylaws from other hackerspaces</li>
<li>Liability waiver templates</li>
<li>Insurance requirement checklists</li>
</ul>
<h3>Legal Help</h3>
<ul>
<li><strong>Pro Bono:</strong> Local bar association referrals</li>
<li><strong>Low Cost:</strong> Legal aid societies</li>
<li><strong>Specialized:</strong> Nonprofit law centers</li>
<li><strong>Online:</strong> LegalZoom, Nolo guides</li>
</ul>
</section>
<section id="downloads">
<h2>Quick Downloads</h2>
<div class="download-section">
<h3>Complete Governance Package</h3>
<p>All documents from this site in various formats:</p>
<div class="download-buttons">
<button class="btn-download">PDF Package</button>
<button class="btn-download">Markdown Files</button>
<button class="btn-download">Word Documents</button>
<button class="btn-download">Google Docs Templates</button>
</div>
</div>
<div class="download-section">
<h3>Source Code</h3>
<p>This website's source code for your own adaptation:</p>
<div class="download-buttons">
<a href="https://github.com/yourusername/governance-site" class="btn-download">
View on GitHub
</a>
<button class="btn-download">Download ZIP</button>
</div>
</div>
</section>
<CalloutBox type="tip">
<p>
<strong>Contributing:</strong> Have resources to share? Submit a pull request
on GitHub or email resources@heatsynclabs.org with your suggestions.
</p>
</CalloutBox>
</div>
</template>
<script setup lang="ts">
import DocumentHeader from '@/components/document/DocumentHeader.vue'
import CalloutBox from '@/components/ui/CalloutBox.vue'
</script>
<style lang="scss" scoped>
.resources-page {
max-width: $max-content-width;
section {
margin-bottom: $space-7;
}
.template-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: $space-4;
margin: $space-5 0;
.template-card {
padding: $space-4;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-3;
}
ul {
margin: $space-3 0;
font-size: $font-size-sm;
}
}
}
.guide-list {
.guide-item {
margin-bottom: $space-5;
padding: $space-4;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
margin-bottom: $space-3;
font-style: italic;
color: $color-text-muted;
}
}
}
.software-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: $space-4;
margin: $space-5 0;
.software-card {
padding: $space-4;
border: 1px solid $color-border;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-3;
}
ul {
font-size: $font-size-sm;
li {
margin-bottom: $space-2;
}
}
}
}
.book-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: $space-4;
margin: $space-5 0;
.book {
padding: $space-3;
background-color: $color-paper-light;
border-radius: $radius-md;
h4 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
font-size: $font-size-sm;
margin: 0;
}
}
}
.download-section {
margin-bottom: $space-5;
padding: $space-4;
background-color: $color-paper-light;
border-radius: $radius-md;
h3 {
color: $color-accent;
margin-bottom: $space-2;
}
p {
margin-bottom: $space-3;
}
.download-buttons {
display: flex;
flex-wrap: wrap;
gap: $space-2;
}
}
.btn-download {
padding: $space-2 $space-4;
background-color: $color-accent;
color: white;
border: none;
border-radius: $radius-md;
cursor: pointer;
font-size: $font-size-sm;
text-decoration: none;
display: inline-block;
&:hover {
background-color: darken($color-accent, 10%);
}
}
}</style>
+77
View File
@@ -0,0 +1,77 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import HomePage from '@/pages/HomePage.vue'
import BylawsPage from '@/pages/BylawsPage.vue'
import CommunityStandardsPage from '@/pages/CommunityStandardsPage.vue'
import DoOcracyPage from '@/pages/DoOcracyPage.vue'
import DecisionMakingPage from '@/pages/DecisionMakingPage.vue'
import MembershipPage from '@/pages/MembershipPage.vue'
import BoardPage from '@/pages/BoardPage.vue'
import ResourcesPage from '@/pages/ResourcesPage.vue'
import AdaptThisPage from '@/pages/AdaptThisPage.vue'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'home',
component: HomePage
},
{
path: '/bylaws',
name: 'bylaws',
component: BylawsPage
},
{
path: '/community-standards',
name: 'community-standards',
component: CommunityStandardsPage
},
{
path: '/do-ocracy',
name: 'do-ocracy',
component: DoOcracyPage
},
{
path: '/decision-making',
name: 'decision-making',
component: DecisionMakingPage
},
{
path: '/membership',
name: 'membership',
component: MembershipPage
},
{
path: '/board',
name: 'board',
component: BoardPage
},
{
path: '/resources',
name: 'resources',
component: ResourcesPage
},
{
path: '/adapt-this',
name: 'adapt-this',
component: AdaptThisPage
}
]
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, _from, savedPosition) {
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth'
}
}
if (savedPosition) {
return savedPosition
}
return { top: 0 }
}
})
export default router
+21
View File
@@ -0,0 +1,21 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Hackerspace } from '@/types'
export const useHackerspaceStore = defineStore('hackerspace', () => {
const hackerspace = ref<Hackerspace>({
name: 'HeatSync Labs',
location: 'Mesa, Arizona',
website: 'https://heatsynclabs.org',
established: new Date('2009-01-01')
})
const updateHackerspace = (updates: Partial<Hackerspace>) => {
hackerspace.value = { ...hackerspace.value, ...updates }
}
return {
hackerspace,
updateHackerspace
}
})
+77
View File
@@ -0,0 +1,77 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { NavItem } from '@/types'
export const useNavigationStore = defineStore('navigation', () => {
const navItems = ref<NavItem[]>([
{
id: 'home',
title: 'Introduction',
path: '/'
},
{
id: 'bylaws',
title: 'Bylaws',
path: '/bylaws'
},
{
id: 'community-standards',
title: 'Community Standards',
path: '/community-standards'
},
{
id: 'do-ocracy',
title: 'Do-ocracy Guide',
path: '/do-ocracy'
},
{
id: 'decision-making',
title: 'Decision Making',
path: '/decision-making'
},
{
id: 'membership',
title: 'Membership',
path: '/membership'
},
{
id: 'board',
title: 'The Board',
path: '/board'
},
{
id: 'resources',
title: 'Resources',
path: '/resources'
},
{
id: 'adapt-this',
title: 'Adapt This',
path: '/adapt-this'
}
])
const isMenuOpen = ref(false)
const activeSection = ref<string>('')
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value
}
const closeMenu = () => {
isMenuOpen.value = false
}
const setActiveSection = (sectionId: string) => {
activeSection.value = sectionId
}
return {
navItems,
isMenuOpen,
activeSection,
toggleMenu,
closeMenu,
setActiveSection
}
})
+79
View File
@@ -0,0 +1,79 @@
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
+122
View File
@@ -0,0 +1,122 @@
// Print styles
@media print {
body {
font-size: 12pt;
line-height: 1.4;
color: #000;
background: white;
}
// Hide navigation and unnecessary elements
nav,
.navigation,
.sidebar,
.header,
.footer,
.no-print,
button,
.btn {
display: none !important;
}
// Ensure content uses full width
.content,
.container {
max-width: 100% !important;
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
}
// Typography adjustments
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid;
page-break-inside: avoid;
}
h1 {
font-size: 24pt;
}
h2 {
font-size: 20pt;
border-bottom: 1pt solid #ccc;
}
h3 {
font-size: 16pt;
}
h4 {
font-size: 14pt;
}
p, ul, ol, blockquote {
orphans: 3;
widows: 3;
}
ul, ol {
page-break-inside: avoid;
}
// Links
a {
color: #000;
text-decoration: underline;
}
a[href^="http"]:after {
content: " (" attr(href) ")";
font-size: 10pt;
color: #666;
}
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
// Tables
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1pt solid #ccc;
padding: 4pt;
}
th {
background-color: #f0f0f0;
}
// Code blocks
pre, code {
font-family: monospace;
font-size: 10pt;
background-color: #f5f5f5;
border: 1pt solid #ddd;
}
pre {
padding: 8pt;
page-break-inside: avoid;
}
// Images
img {
max-width: 100% !important;
page-break-inside: avoid;
}
// Page breaks
.page-break {
page-break-before: always;
}
.no-page-break {
page-break-inside: avoid;
}
}
+103
View File
@@ -0,0 +1,103 @@
// Modern CSS Reset
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
}
html {
font-size: $font-size-base;
-webkit-text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
min-height: 100vh;
font-family: $font-family-base;
line-height: $line-height-base;
color: $color-text;
background-color: $color-paper;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
height: auto;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
a {
color: $color-accent;
text-decoration: none;
transition: color $transition-fast;
&:hover, &:focus {
text-decoration: underline;
}
&:focus-visible {
outline: 2px solid $color-accent;
outline-offset: 2px;
}
}
button {
cursor: pointer;
background: transparent;
border: none;
&:focus-visible {
outline: 2px solid $color-accent;
outline-offset: 2px;
}
}
ul, ol {
list-style-position: inside;
}
blockquote {
border-left: 4px solid $color-border;
padding-left: $space-4;
margin: $space-4 0;
color: $color-text-muted;
}
hr {
border: none;
border-top: 1px solid $color-border;
margin: $space-6 0;
}
code {
font-family: $font-family-mono;
font-size: 0.875em;
background-color: $color-paper-light;
padding: 2px 6px;
border-radius: $radius-sm;
}
pre {
font-family: $font-family-mono;
font-size: 0.875rem;
background-color: $color-paper-light;
padding: $space-4;
border-radius: $radius-md;
overflow-x: auto;
code {
background: transparent;
padding: 0;
}
}
+150
View File
@@ -0,0 +1,150 @@
// Typography System
h1, h2, h3, h4, h5, h6 {
line-height: $line-height-heading;
font-weight: 600;
margin-bottom: $space-3;
color: $color-text;
}
h1 {
font-size: $font-size-3xl;
margin-bottom: $space-5;
font-weight: 700;
letter-spacing: -0.02em;
}
h2 {
font-size: $font-size-2xl;
margin-top: $space-7;
margin-bottom: $space-4;
padding-bottom: $space-2;
border-bottom: 1px solid $color-border;
}
h3 {
font-size: $font-size-xl;
margin-top: $space-6;
margin-bottom: $space-3;
}
h4 {
font-size: $font-size-lg;
margin-top: $space-5;
margin-bottom: $space-3;
}
h5 {
font-size: $font-size-md;
margin-top: $space-4;
margin-bottom: $space-2;
font-weight: 700;
}
h6 {
font-size: $font-size-sm;
margin-top: $space-4;
margin-bottom: $space-2;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
}
p {
margin-bottom: $space-4;
max-width: $max-content-width;
&:last-child {
margin-bottom: 0;
}
}
.lead {
font-size: $font-size-lg;
line-height: 1.5;
color: $color-text-muted;
margin-bottom: $space-5;
}
.text-small {
font-size: $font-size-sm;
}
.text-xs {
font-size: $font-size-xs;
}
.text-muted {
color: $color-text-muted;
}
.text-mono {
font-family: $font-family-mono;
}
strong, b {
font-weight: 600;
}
em, i {
font-style: italic;
}
mark {
background-color: rgba($color-warning, 0.2);
padding: 2px 4px;
border-radius: $radius-sm;
}
// Lists
ul, ol {
margin-bottom: $space-4;
padding-left: $space-5;
li {
margin-bottom: $space-2;
}
ul, ol {
margin-top: $space-2;
margin-bottom: $space-2;
}
}
// Definition lists
dl {
margin-bottom: $space-4;
dt {
font-weight: 600;
margin-bottom: $space-1;
}
dd {
margin-bottom: $space-3;
margin-left: $space-5;
color: $color-text-muted;
}
}
// Tables
table {
width: 100%;
border-collapse: collapse;
margin-bottom: $space-5;
font-size: $font-size-sm;
th, td {
padding: $space-3;
text-align: left;
border-bottom: 1px solid $color-border;
}
th {
font-weight: 600;
background-color: $color-paper-light;
}
tbody tr:hover {
background-color: rgba($color-paper-light, 0.5);
}
}
+189
View File
@@ -0,0 +1,189 @@
// Utility Classes
// Display
.d-none { display: none !important; }
.d-block { display: block !important; }
.d-inline { display: inline !important; }
.d-inline-block { display: inline-block !important; }
.d-flex { display: flex !important; }
.d-grid { display: grid !important; }
// Flexbox
.flex-row { flex-direction: row !important; }
.flex-column { flex-direction: column !important; }
.flex-wrap { flex-wrap: wrap !important; }
.flex-nowrap { flex-wrap: nowrap !important; }
.justify-start { justify-content: flex-start !important; }
.justify-center { justify-content: center !important; }
.justify-end { justify-content: flex-end !important; }
.justify-between { justify-content: space-between !important; }
.justify-around { justify-content: space-around !important; }
.align-start { align-items: flex-start !important; }
.align-center { align-items: center !important; }
.align-end { align-items: flex-end !important; }
.align-stretch { align-items: stretch !important; }
.flex-grow { flex-grow: 1 !important; }
.flex-shrink-0 { flex-shrink: 0 !important; }
// Grid
.gap-1 { gap: $space-1 !important; }
.gap-2 { gap: $space-2 !important; }
.gap-3 { gap: $space-3 !important; }
.gap-4 { gap: $space-4 !important; }
.gap-5 { gap: $space-5 !important; }
.gap-6 { gap: $space-6 !important; }
// Spacing
@each $size, $value in (
1: $space-1,
2: $space-2,
3: $space-3,
4: $space-4,
5: $space-5,
6: $space-6,
7: $space-7,
8: $space-8,
9: $space-9
) {
.m-#{$size} { margin: $value !important; }
.mt-#{$size} { margin-top: $value !important; }
.mr-#{$size} { margin-right: $value !important; }
.mb-#{$size} { margin-bottom: $value !important; }
.ml-#{$size} { margin-left: $value !important; }
.mx-#{$size} {
margin-left: $value !important;
margin-right: $value !important;
}
.my-#{$size} {
margin-top: $value !important;
margin-bottom: $value !important;
}
.p-#{$size} { padding: $value !important; }
.pt-#{$size} { padding-top: $value !important; }
.pr-#{$size} { padding-right: $value !important; }
.pb-#{$size} { padding-bottom: $value !important; }
.pl-#{$size} { padding-left: $value !important; }
.px-#{$size} {
padding-left: $value !important;
padding-right: $value !important;
}
.py-#{$size} {
padding-top: $value !important;
padding-bottom: $value !important;
}
}
.m-0 { margin: 0 !important; }
.p-0 { padding: 0 !important; }
.m-auto { margin: auto !important; }
.mx-auto {
margin-left: auto !important;
margin-right: auto !important;
}
// Width & Height
.w-full { width: 100% !important; }
.w-auto { width: auto !important; }
.h-full { height: 100% !important; }
.h-auto { height: auto !important; }
.min-h-screen { min-height: 100vh !important; }
// Position
.relative { position: relative !important; }
.absolute { position: absolute !important; }
.fixed { position: fixed !important; }
.sticky { position: sticky !important; }
.top-0 { top: 0 !important; }
.right-0 { right: 0 !important; }
.bottom-0 { bottom: 0 !important; }
.left-0 { left: 0 !important; }
// Text
.text-left { text-align: left !important; }
.text-center { text-align: center !important; }
.text-right { text-align: right !important; }
.text-justify { text-align: justify !important; }
// Visibility
.visible { visibility: visible !important; }
.invisible { visibility: hidden !important; }
// Overflow
.overflow-auto { overflow: auto !important; }
.overflow-hidden { overflow: hidden !important; }
.overflow-scroll { overflow: scroll !important; }
.overflow-x-auto { overflow-x: auto !important; }
.overflow-y-auto { overflow-y: auto !important; }
// Borders
.border { border: 1px solid $color-border !important; }
.border-0 { border: 0 !important; }
.border-t { border-top: 1px solid $color-border !important; }
.border-r { border-right: 1px solid $color-border !important; }
.border-b { border-bottom: 1px solid $color-border !important; }
.border-l { border-left: 1px solid $color-border !important; }
// Border radius
.rounded { border-radius: $radius-md !important; }
.rounded-sm { border-radius: $radius-sm !important; }
.rounded-lg { border-radius: $radius-lg !important; }
.rounded-0 { border-radius: 0 !important; }
// Shadows
.shadow-sm { box-shadow: $shadow-sm !important; }
.shadow-md { box-shadow: $shadow-md !important; }
.shadow-lg { box-shadow: $shadow-lg !important; }
.shadow-none { box-shadow: none !important; }
// Responsive utilities
@media (min-width: $breakpoint-sm) {
.sm\:d-none { display: none !important; }
.sm\:d-block { display: block !important; }
.sm\:d-flex { display: flex !important; }
}
@media (min-width: $breakpoint-md) {
.md\:d-none { display: none !important; }
.md\:d-block { display: block !important; }
.md\:d-flex { display: flex !important; }
}
@media (min-width: $breakpoint-lg) {
.lg\:d-none { display: none !important; }
.lg\:d-block { display: block !important; }
.lg\:d-flex { display: flex !important; }
}
// Container
.container {
width: 100%;
max-width: 1280px;
margin-left: auto;
margin-right: auto;
padding-left: $space-4;
padding-right: $space-4;
@media (min-width: $breakpoint-md) {
padding-left: $space-5;
padding-right: $space-5;
}
@media (min-width: $breakpoint-lg) {
padding-left: $space-6;
padding-right: $space-6;
}
}
// Screen reader only
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@@ -0,0 +1,65 @@
// Color Palette
$color-paper: #FAFAF8;
$color-paper-light: #F5F5F0;
$color-text: #1A1A1A;
$color-text-muted: #666666;
$color-accent: #0066CC;
$color-warning: #D97706;
$color-error: #DC2626;
$color-success: #059669;
$color-border: #E5E5E5;
// Typography
$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
$font-family-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Fira Mono', 'Droid Sans Mono', monospace;
$font-size-base: 16px;
$line-height-base: 1.6;
$line-height-heading: 1.2;
// Typography Scale (Golden Ratio)
$font-size-xs: 0.618rem;
$font-size-sm: 0.875rem;
$font-size-md: 1rem;
$font-size-lg: 1.25rem;
$font-size-xl: 1.618rem;
$font-size-2xl: 2.058rem;
$font-size-3xl: 2.618rem;
$font-size-4xl: 3.272rem;
// Spacing Scale
$space-1: 4px;
$space-2: 8px;
$space-3: 12px;
$space-4: 16px;
$space-5: 24px;
$space-6: 32px;
$space-7: 48px;
$space-8: 64px;
$space-9: 96px;
// Layout
$max-content-width: 75ch;
$sidebar-width: 280px;
$header-height: 64px;
// Breakpoints
$breakpoint-sm: 640px;
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
$breakpoint-xl: 1280px;
// Transitions
$transition-fast: 150ms ease-in-out;
$transition-base: 250ms ease-in-out;
$transition-slow: 350ms ease-in-out;
// Shadows
$shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
// Border Radius
$radius-sm: 2px;
$radius-md: 4px;
$radius-lg: 8px;
+5
View File
@@ -0,0 +1,5 @@
@import 'variables';
@import 'reset';
@import 'typography';
@import 'utilities';
@import 'print';
+30
View File
@@ -0,0 +1,30 @@
export interface NavItem {
id: string
title: string
path: string
children?: NavItem[]
}
export interface DocumentSection {
id: string
title: string
content: string
order: number
subsections?: DocumentSection[]
}
export interface GovernanceDocument {
id: string
title: string
description: string
lastUpdated: Date
sections: DocumentSection[]
}
export interface Hackerspace {
name: string
location: string
website?: string
established?: Date
logo?: string
}
+26
View File
@@ -0,0 +1,26 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"types": ["vite/client", "node"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
/* Linting */
"strict": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}
+7
View File
@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": ["ES2023"],
"module": "ESNext",
"types": ["node"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}
+20
View File
@@ -0,0 +1,20 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/_variables.scss";`
}
}
}
})