feat(signup): community guidelines agreement and policies routes

Introduces /community-guidelines and /policies/{privacy,terms,[slug]} pages,
swaps the signup/invite checkbox from agreedToTerms to agreedToGuidelines,
adds Member.agreement.acceptedAt, and stamps the field when a Helcim
customer is created.
This commit is contained in:
Jennie Robinson Faber 2026-04-18 17:06:10 +01:00
parent e0d11e47f4
commit c5e901ed24
13 changed files with 1292 additions and 54 deletions

View file

@ -0,0 +1,79 @@
<template>
<PageShell :title="policy.title" subtitle="Ghost Guild Policy">
<div class="policy-prose">
<p class="policy-status">This policy is being finalized.</p>
<p>
{{ policy.description }}
</p>
<p>
The full text will be published here ahead of launch. In the meantime,
the expectations that apply are summarized in our
<NuxtLink to="/community-guidelines">Community Guidelines</NuxtLink>.
</p>
<p>
Questions? Contact the Membership Committee at
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>.
</p>
</div>
</PageShell>
</template>
<script setup>
// Note: /policies/code-of-conduct and /policies/conflict-resolution are
// handled by routeRules in nuxt.config.ts and redirect to external Obsidian
// pages. /policies/privacy and /policies/terms have dedicated pages
// (privacy.vue, terms.vue) that take precedence over this dynamic route.
const POLICIES = {
'by-laws': {
title: 'By-Laws',
description:
"Ghost Guild's governing by-laws, including membership classes, voting rights, and the structure of the Membership Committee.",
},
}
const route = useRoute()
const slug = String(route.params.slug || '')
const policy = POLICIES[slug]
if (!policy) {
throw createError({ statusCode: 404, statusMessage: 'Policy not found', fatal: true })
}
useHead({
title: `${policy.title} · Ghost Guild`,
})
</script>
<style scoped>
.policy-prose {
max-width: 640px;
padding: 32px;
}
.policy-status {
font-family: "Commit Mono", monospace;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--candle);
margin-bottom: 16px;
}
.policy-prose p {
font-size: 13px;
color: var(--text-dim);
line-height: 1.7;
margin-bottom: 14px;
}
.policy-prose a {
color: var(--candle);
}
@media (max-width: 640px) {
.policy-prose {
padding: 20px 16px;
}
}
</style>

View file

@ -0,0 +1,328 @@
<template>
<PageShell title="Privacy Policy" subtitle="How Ghost Guild handles your data">
<div class="policy-prose">
<p class="policy-updated">Last updated: April 18, 2026</p>
<section class="policy-section">
<p>
Ghost Guild is a program of Baby Ghosts, a Canadian non-profit. This
policy explains what information we collect when you use
ghostguild.org and wiki.ghostguild.org, what we do with it, and what
choices you have.
</p>
<p>
We treat your data as something you've trusted us with, not something
we own. If anything here is unclear or feels off, email us at
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>.
</p>
</section>
<section class="policy-section">
<h2>What we collect</h2>
<p>
<strong>When you apply for membership:</strong> your name, pronouns,
location, email, the answers you give in your application, and which
membership circle you're applying for.
</p>
<p>
<strong>When you build a profile:</strong> anything you choose to add
(bio, studio affiliation, skills, social links, availability for peer
support, Slack handle). Your profile is visible to other Ghost Guild
members. It isn't made public or visible to search engines. If you
don't want something seen by other members, don't put it in your
profile.
</p>
<p>
<strong>When you contribute to the wiki:</strong> your edits,
comments, and authorship are recorded so members can see who wrote
what and so we can roll back if needed.
</p>
<p>
<strong>When you post on the bulletin board:</strong> your posts
(needs you have, offers you can make), your name as the poster, and
the timestamps. The actual connecting between members happens in
Slack, not on our platform.
</p>
<p>
<strong>When you pay dues:</strong> payment is handled by Helcim. We
see the amount, date, and that the payment came from you. We don't
see or store card numbers or banking details.
</p>
<p>
<strong>When you get emails from us:</strong> Resend delivers them.
They process your email address and basic delivery metadata.
</p>
<p>
<strong>For site analytics:</strong> we use Plausible. Plausible
doesn't use tracking cookies, doesn't store IP addresses, and doesn't
follow you across sites. It tells us aggregate things like which
pages get visited and roughly how many people use the site. It
doesn't tell us who you are.
</p>
<p>
We don't use Google Analytics, advertising pixels, or any other
tracking. The site uses cookies needed to keep you logged in. That's
it.
</p>
</section>
<section class="policy-section">
<h2>Why we collect it</h2>
<p>
<strong>To run the membership program:</strong> review applications,
give you access, support your participation, send you things you've
signed up for.
</p>
<p>
<strong>To help members find each other:</strong> making your profile
and bulletin board posts visible to the rest of the community.
</p>
<p>
<strong>To report on impact:</strong> anonymized, aggregated numbers
for funders and the community (how many members, what topics come up
on the bulletin board, where members are based).
</p>
<p>
<strong>To meet our obligations</strong> as a non-profit corporation
under Canadian law.
</p>
</section>
<section class="policy-section">
<h2>Who else sees it</h2>
<p>The services that store or process your data on our behalf:</p>
<ul>
<li>Helcim, payment processing, Canada</li>
<li>Resend, transactional email, US</li>
<li>Hetzner, server hosting, Germany</li>
<li>Outline, wiki software running on our Hetzner server</li>
<li>Plausible, anonymous site analytics, EU</li>
<li>
Slack, if you accept an invitation to the shared Gamma Space
workspace
</li>
</ul>
<p>
<strong>Other Ghost Guild members:</strong> they can see your profile
and any bulletin board posts you make. None of this is public or
visible to search engines.
</p>
<p>
<strong>Wiki contributions:</strong> anything you post on
wiki.ghostguild.org is part of a public knowledge commons (see the
<NuxtLink to="/policies/terms">Terms of Service</NuxtLink> for the
specifics) and may be visible to anyone on the internet.
</p>
<p>
<strong>Baby Ghosts staff and the Membership Committee:</strong> for
purposes related to running the program.
</p>
</section>
<section class="policy-section">
<h2>What we don't do</h2>
<p>We don't sell your data.</p>
<p>We don't share it with third parties for marketing.</p>
<p>
We don't feed your messages, profile, applications, bulletin board
posts, or other community content into generative AI tools, and we
don't allow members to do that with each other's content either. This
is a community commitment, not just a policy line.
</p>
<p>
If we ever want to do something different than what's in this policy,
we'll ask first.
</p>
</section>
<section class="policy-section">
<h2>How long we keep it</h2>
<p>
<strong>While you're a member:</strong> as long as you have an
account.
</p>
<p>
<strong>After you leave:</strong> we keep basic account records for
one year for administrative reasons (renewals, returning members,
financial records we're required to keep). Your wiki contributions
remain in the commons under their license; that's how a commons works
(see <NuxtLink to="/policies/terms">Terms of Service</NuxtLink>).
Your bulletin board posts are removed when you close your account.
Aggregate impact data has no expiry and doesn't identify you.
</p>
<p>
<strong>Financial records:</strong> we keep what we have to keep
under tax law (currently six years).
</p>
<p>
You can ask us to delete your account and personal data at any time.
We'll do it unless we're legally required to retain something
specific, in which case we'll tell you what and why.
</p>
</section>
<section class="policy-section">
<h2>Your rights</h2>
<p>You can:</p>
<ul>
<li>See what we have about you</li>
<li>Correct anything that's wrong</li>
<li>Download your data</li>
<li>Delete your account</li>
<li>Withdraw consent for anything you previously agreed to</li>
</ul>
<p>
To do any of these, email
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>. We'll
respond within 30 days.
</p>
<p>
If you live in a province with its own privacy law (Quebec, British
Columbia, Alberta), you may have additional rights under that law.
PIPEDA may also apply to some of what we do. We'll respect those
rights regardless of which framework technically covers your
situation.
</p>
</section>
<section class="policy-section">
<h2>Security</h2>
<p>
We host on a private server, encrypt data in transit, and limit
access to staff who need it. Perfect security doesn't exist. If
something happens that affects your data, we'll tell you within a
reasonable time and explain what we're doing about it.
</p>
</section>
<section class="policy-section">
<h2>Children</h2>
<p>
Ghost Guild is for adults. We don't knowingly collect data from
anyone under 18.
</p>
</section>
<section class="policy-section">
<h2>Changes</h2>
<p>
If we change this policy in a way that affects how we handle your
data, we'll email members and post the change with a date stamp at
least 30 days before it takes effect. Continued use after that means
you accept the changes. If you don't, close your account first.
</p>
</section>
<section class="policy-section">
<h2>Contact</h2>
<p>
Questions, requests, complaints:
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>
</p>
<p class="policy-address">
Baby Ghosts<br>
3230 Yonge Street #4052<br>
Toronto ON M4N 3P6<br>
Canada
</p>
</section>
</div>
</PageShell>
</template>
<script setup>
useHead({
title: 'Privacy Policy · Ghost Guild',
})
</script>
<style scoped>
.policy-prose {
max-width: 720px;
padding: 32px;
}
.policy-updated {
font-family: "Commit Mono", monospace;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--candle);
margin-bottom: 24px;
}
.policy-section {
padding: 28px 0;
border-bottom: 1px dashed var(--border);
}
.policy-section:first-of-type {
padding-top: 0;
}
.policy-section:last-child {
border-bottom: none;
}
.policy-section h2 {
font-family: "Brygada 1918", serif;
font-size: 20px;
font-weight: 600;
color: var(--text-bright);
letter-spacing: -0.01em;
margin-bottom: 16px;
line-height: 1.25;
}
.policy-section p {
font-size: 13px;
color: var(--text-dim);
line-height: 1.7;
margin-bottom: 12px;
}
.policy-section ul {
list-style: none;
padding: 0;
margin: 8px 0 14px;
}
.policy-section ul li {
position: relative;
padding: 2px 0 2px 18px;
font-size: 13px;
color: var(--text-dim);
line-height: 1.7;
margin-bottom: 4px;
}
.policy-section ul li::before {
content: "";
position: absolute;
left: 0;
top: 2px;
color: var(--candle-faint);
font-size: 14px;
line-height: 1.7;
}
.policy-section a {
color: var(--candle);
}
.policy-section strong {
color: var(--text-bright);
font-weight: 600;
}
.policy-address {
font-family: "Commit Mono", monospace;
font-size: 12px;
line-height: 1.7;
color: var(--text-dim);
margin-top: 16px;
}
@media (max-width: 640px) {
.policy-prose {
padding: 20px 16px;
}
}
</style>

View file

@ -0,0 +1,357 @@
<template>
<PageShell title="Terms of Service" subtitle="Using ghostguild.org and wiki.ghostguild.org">
<div class="policy-prose">
<p class="policy-updated">Last updated: April 18, 2026</p>
<section class="policy-section">
<p>
These terms apply to your use of ghostguild.org and
wiki.ghostguild.org, run by Baby Ghosts (a Canadian non-profit). The
<NuxtLink to="/community-guidelines">Member Agreement</NuxtLink> and
<NuxtLink to="/policies/code-of-conduct">Code of Conduct</NuxtLink>
also apply if you're a member; they sit alongside these terms, and
the more specific document wins if there's ever a conflict.
</p>
</section>
<section class="policy-section">
<h2>Who can use Ghost Guild</h2>
<p>You can browse public pages without an account.</p>
<p>
To become a member, you have to be 18 or older, complete an
application, and be accepted by the Membership Committee. Membership
is reviewed against our values and processes; we can decline
applications, and we don't always provide detailed reasons.
</p>
</section>
<section class="policy-section">
<h2>Your account</h2>
<p>
You're responsible for what happens under your account. Don't share
login credentials. If you suspect unauthorized access, tell us at
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>.
</p>
<p>
We may suspend or close accounts that violate these terms, the
<NuxtLink to="/policies/code-of-conduct">Code of Conduct</NuxtLink>,
or the
<NuxtLink to="/community-guidelines">Member Agreement</NuxtLink>. The
process for that lives in our
<NuxtLink to="/policies/conflict-resolution">Conflict Resolution Policy</NuxtLink>.
</p>
<p>
We don't suspend or close accounts because a payment didn't go
through. If there's a problem with your contribution, we'll reach
out.
</p>
</section>
<section class="policy-section">
<h2>Membership and dues</h2>
<p>
Membership runs annually and renews unless you cancel. You can pay
your annual dues all at once or in monthly installments; both result
in the same annual membership.
</p>
<p>
Dues are pay-what-you-can: you choose your contribution, and you can
change it any time as your situation changes. The full pricing
structure is on the membership page.
</p>
<p>
We don't refund dues. If paying ever becomes a problem, the
Solidarity Fund is there for that reason; reach out and we'll work it
out.
</p>
</section>
<section class="policy-section">
<h2>Acceptable use</h2>
<p>
The
<NuxtLink to="/policies/code-of-conduct">Code of Conduct</NuxtLink>
governs how members behave in Ghost Guild spaces. Some basics that
also apply here:
</p>
<ul>
<li>Don't harass, harm, or discriminate against other members</li>
<li>
Don't share other members' content (Slack messages, profile
information, bulletin board posts, application materials, private
comments) outside the community without their consent
</li>
<li>
Don't feed community content, including other members'
contributions, into generative AI tools
</li>
<li>
Don't use Ghost Guild for illegal activity, spam, or attempts to
compromise the platform
</li>
<li>
Don't impersonate others or misrepresent your identity or
affiliations
</li>
<li>
Don't scrape the site or use automated tools to extract member data
</li>
</ul>
<p>
If you violate these, we follow the
<NuxtLink to="/policies/conflict-resolution">Conflict Resolution Policy</NuxtLink>.
Outcomes range from a conversation through to removal from the
community.
</p>
</section>
<section class="policy-section">
<h2>Your content</h2>
<p>
There are two different things happening with content on Ghost Guild,
and they work differently.
</p>
<h3>Profiles, bulletin board posts, comments, and other member-only content</h3>
<p>
You keep ownership of profile information, bulletin board posts,
comments, messages, and anything else you post in member-only spaces.
By posting these, you give Ghost Guild a non-exclusive license to
display them within the platform to other members.
</p>
<p>
If you delete your account, we remove this content from member-facing
areas. Backups may persist for a reasonable period before being
purged.
</p>
<h3>Wiki contributions</h3>
<p>
The wiki at
<a href="https://wiki.ghostguild.org">wiki.ghostguild.org</a> is a
knowledge commons. When you contribute to it (creating pages, editing
existing ones, adding examples, leaving comments on wiki pages), your
contribution is automatically and irrevocably licensed under the
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
(CC-BY-SA 4.0).
</p>
<p>In plain terms:</p>
<ul>
<li>You still hold the copyright to what you wrote</li>
<li>
Anyone (members, the public, other cooperatives, organizations
adapting the material) can use, share, adapt, and build on your
contribution, including for commercial purposes, as long as they
credit you and license their derivatives under the same terms
</li>
<li>
You can't pull your contribution back out of the commons later,
even if you leave Ghost Guild
</li>
<li>
If we publish wiki material in other places (like
<a href="https://coop.love">coop.love</a>), it stays under
CC-BY-SA 4.0 and you stay credited
</li>
</ul>
<p>
This is how a knowledge commons works, and it's central to what Ghost
Guild is doing. We're explicit about it because we want you to
contribute knowing exactly what's happening to your work. If you have
something you'd rather keep private or under a more restrictive
license, don't put it in the wiki.
</p>
</section>
<section class="policy-section">
<h2>Our content</h2>
<p>
Educational materials, templates, and resources we publish on
ghostguild.org are for member use within the spirit of the
cooperative movement. Where a specific license is attached (like
Creative Commons), follow that license. We ask for attribution to
Ghost Guild or Baby Ghosts.
</p>
</section>
<section class="policy-section">
<h2>Third-party services</h2>
<p>
Ghost Guild relies on Helcim (payments), Resend (email), Hetzner
(hosting), Outline (wiki), Plausible (analytics), and Slack (via the
shared Gamma Space workspace). Their terms apply when you interact
with their services. We've picked them carefully but we can't
guarantee they'll never have outages, security issues, or policy
changes.
</p>
</section>
<section class="policy-section">
<h2>Disclaimers</h2>
<p>
Ghost Guild is provided as-is. We work to keep things running and
resources accurate, but we don't guarantee uptime, completeness, or
that information on the site is right for your specific situation.
Treat our templates and educational materials as starting points, not
legal, financial, or business advice. Talk to qualified professionals
before you make decisions that need them.
</p>
</section>
<section class="policy-section">
<h2>Limitation of liability</h2>
<p>
To the extent the law allows, Baby Ghosts isn't liable for indirect,
incidental, or consequential damages arising from your use of the
site. Our total liability is capped at the amount of dues you've paid
in the past 12 months (which may well be zero, given how our pricing
works).
</p>
</section>
<section class="policy-section">
<h2>Disputes</h2>
<p>
For disputes between members, we use the
<NuxtLink to="/policies/conflict-resolution">Conflict Resolution Policy</NuxtLink>.
</p>
<p>
For disputes with Baby Ghosts about these terms or your account,
please reach out first. Most things we can sort out by talking. If we
can't, the dispute will be governed by the laws of Ontario, Canada.
</p>
</section>
<section class="policy-section">
<h2>Changes</h2>
<p>
We'll update these terms from time to time. For changes that
materially affect your rights or our obligations, we'll email members
at least 30 days before the new terms take effect. Continued use
after that means you accept the changes. If you don't, close your
account before they kick in.
</p>
</section>
<section class="policy-section">
<h2>Contact</h2>
<p>
<a href="mailto:hello@ghostguild.org">hello@ghostguild.org</a>
</p>
<p class="policy-address">
Baby Ghosts<br>
3230 Yonge Street #4052<br>
Toronto ON M4N 3P6<br>
Canada
</p>
</section>
</div>
</PageShell>
</template>
<script setup>
useHead({
title: 'Terms of Service · Ghost Guild',
})
</script>
<style scoped>
.policy-prose {
max-width: 720px;
padding: 32px;
}
.policy-updated {
font-family: "Commit Mono", monospace;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--candle);
margin-bottom: 24px;
}
.policy-section {
padding: 28px 0;
border-bottom: 1px dashed var(--border);
}
.policy-section:first-of-type {
padding-top: 0;
}
.policy-section:last-child {
border-bottom: none;
}
.policy-section h2 {
font-family: "Brygada 1918", serif;
font-size: 20px;
font-weight: 600;
color: var(--text-bright);
letter-spacing: -0.01em;
margin-bottom: 16px;
line-height: 1.25;
}
.policy-section h3 {
font-family: "Commit Mono", monospace;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-bright);
margin: 20px 0 10px;
}
.policy-section p {
font-size: 13px;
color: var(--text-dim);
line-height: 1.7;
margin-bottom: 12px;
}
.policy-section ul {
list-style: none;
padding: 0;
margin: 8px 0 14px;
}
.policy-section ul li {
position: relative;
padding: 2px 0 2px 18px;
font-size: 13px;
color: var(--text-dim);
line-height: 1.7;
margin-bottom: 4px;
}
.policy-section ul li::before {
content: "";
position: absolute;
left: 0;
top: 2px;
color: var(--candle-faint);
font-size: 14px;
line-height: 1.7;
}
.policy-section a {
color: var(--candle);
}
.policy-section strong {
color: var(--text-bright);
font-weight: 600;
}
.policy-address {
font-family: "Commit Mono", monospace;
font-size: 12px;
line-height: 1.7;
color: var(--text-dim);
margin-top: 16px;
}
@media (max-width: 640px) {
.policy-prose {
padding: 20px 16px;
}
}
</style>